[Deprecated] C libwebsockets

By | 2022년 2월 1일
Table of Contents

[Deprecated] C libwebsockets

라이브러리가 난잡하다……

참조

. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .

branch v4.3-stable

git clone https://github.com/warmcat/libwebsockets.git -b v4.3-stable
cd libwebsockets
sudo apt-get install libssl-dev
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig

서버 생성

https://www.skyer9.pe.kr/wordpress/?p=4668 에서 nodeJS 로 서버를 구성한다.

클라이언트 생성

#include <libwebsockets.h>

static int callback( lws*, lws_callback_reasons reason, void* user, void* p, size_t z )
{
    switch( reason ) {
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
            // Connected to server.
            break;

        case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
            // Unable to connect to server.  Check protocol?
            break;

        case LWS_CALLBACK_CLOSED:
            // Connection to server closed.
            break;

        case LWS_CALLBACK_CLIENT_RECEIVE:
            // Data of z bytes is accessible via pointer p.
            fprintf(stdout, "%s\n", (const char*)p); fflush(stdout);
            break;

        case LWS_CALLBACK_CLIENT_WRITEABLE:
            // Now is your chance to send stuff to server, use API
            // lws_write() to do so.
            break;

        default: break;
    }
    return 0;
}

static lws_protocols protocols[] = {
    {
        "test-protocol", // protocol name
        callback,        // callback for protocol
        0,               // per session data size
        0,               // receive buffer size
        0,               // user defined ID, not used by LWS
        nullptr,         // user defined pointer
        0                // transmit buffer size
    },
    { nullptr, nullptr, 0, 0, 0, nullptr, 0 } // protocol list terminator
};

int ws_parse_uri(const char *_url, struct lws_client_connect_info *ccinfo) {
    char url[1024];
    const char *protocol, *_path, *_address;
    char *path, *address;

    lws_strncpy(url, _url, sizeof(url));

    if (lws_parse_uri(url, &protocol, &_address, &ccinfo->port, &_path)) {
        return 1;
    }

    if (!strcmp(protocol, "https") || !strcmp(protocol, "wss")) {
        ccinfo->protocol = "wss";
        ccinfo->ssl_connection = LCCSCF_USE_SSL |
                                 LCCSCF_ALLOW_SELFSIGNED |
                                 LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
    } else {
        ccinfo->protocol = "ws";
        ccinfo->ssl_connection = 0;
    }

    address = (char *) malloc(sizeof (char) * (strlen(_address) + 1));
    memcpy(address, _address, (sizeof (char) * (strlen(_address) + 1)));

    if (_path[0] != '/') {
        path = (char *) malloc(sizeof (char) * (strlen(_path) + 2));
        path[0] = '/';
        memcpy(path + 1, _path, (sizeof (char) * (strlen(_path) + 1)));
    } else {
        path = (char *) malloc(sizeof (char) * (strlen(_path) + 1));
        memcpy(path, _path, sizeof (char) * (strlen(_path) + 1));
    }

    ccinfo->address = address;
    ccinfo->path = path;

    return 0;
}

int main(int argc, char **argv) {

    // ~/work/example/websocket/libwebsockets

    // ====================================================
    // creation info
    lws_context_creation_info cinfo;
    memset(&cinfo, 0, sizeof(cinfo));
    cinfo.port = CONTEXT_PORT_NO_LISTEN;
    cinfo.protocols = protocols;
    cinfo.extensions = nullptr;
    cinfo.gid = -1;
    cinfo.uid = -1;
    cinfo.user = nullptr;
    cinfo.options = 0;

    // ====================================================
    // context
    lws_context *context = lws_create_context(&cinfo);

    // ====================================================
    // client connect info
    const char *url = "ws://localhost:30001/index.html";
    struct lws_client_connect_info ccinfo;
    memset(&ccinfo, 0, sizeof(ccinfo));
    ws_parse_uri(url, &ccinfo);

    if(context) {
        ccinfo.context = context;
        ccinfo.protocol = "test-protocol";     // protocol
        ccinfo.ietf_version_or_minus_one = -1;   // IETF version

        // ====================================================
        // client connect
        lws *socket = lws_client_connect_via_info(&ccinfo);
        if( socket ) {
            bool running = true;
            while( running ) {
                lws_service(context, 0); // 0 : timeout is ignored
                lws_callback_on_writable_all_protocol(context, &protocols[0]);
            }
        }
        lws_context_destroy(context);
    }

    // printf("ccinfo.protocol : %s\n", ccinfo.protocol);
    // printf("ccinfo.address : %s\n", ccinfo.address);
    // printf("ccinfo.port : %i\n", ccinfo.port);
    // printf("ccinfo.path : %s\n", ccinfo.path);

    free((void *) ccinfo.address);
    free((void *) ccinfo.path);
}
gcc main.cpp -lwebsockets
./a.out

주의사항

참조