[Libwebsockets] Re-connection logic for libwebsockets

Hemant Kumar hkumar at arubanetworks.com
Wed Dec 9 04:29:37 CET 2015


Hi Andy

I was able to figure out the reason for this one.

Basically, every time I was trying to kill the server, client was failing on another end with segmentation fault owing to null pointer access for user data.

I see following code for extended connect:

LWS_VISIBLE struct libwebsocket *
libwebsocket_client_connect_extended(struct libwebsocket_context *context,
                  const char *address,
                  int port,
                  int ssl_connection,
                  const char *path,
                  const char *host,
                  const char *origin,
                  const char *protocol,
                  int ietf_version_or_minus_one,
                  void *userdata)
{
    struct libwebsocket *ws =
        libwebsocket_client_connect(context, address, port,
            ssl_connection, path, host, origin, protocol,
                             ietf_version_or_minus_one);

    if (ws && !ws->user_space && userdata) {
        ws->user_space_externally_allocated = 1;
        ws->user_space = userdata ;
    }   

    return ws ;
}

so, basically, if in protocols structure if someone has defined the per session data structure, then 
we do not put data as per "ws->user_space = userdata" line above since, if condition will not hold true.


I was doing extended connect with user_data (passing as argument in end) as well as having per session data defined 
in protocols array as:

static struct libwebsocket_protocols protocols[] = { 
    {   
        "comm-protocol",
        data_callback_handler,
        sizeof(struct per_session_data__sprotocol),
        0,  
    },  
    { /* end of list */
        NULL,
        NULL,
        0,  
        0,  
    }   
};


As soon as I removed, sizeof(struct per_session_data__sprotocol) above, I get the reconnection logic right and client doesnt die with segmentation fault
as I was trying to access value of user data as mentioned earlier email , in callback handler.

Thanks for your help.

Much appreciated.
Hemant








________________________________________
From: Andy Green [andy.green at linaro.org] on behalf of Andy Green [andy at warmcat.com]
Sent: Tuesday, December 8, 2015 7:09 PM
To: Hemant Kumar; libwebsockets at ml.libwebsockets.org
Subject: Re: [Libwebsockets] Re-connection logic for libwebsockets

On December 9, 2015 11:03:35 AM GMT+08:00, Hemant Kumar <hkumar at arubanetworks.com> wrote:
>Sorry Andy to bother once again.
>
>In the same client program,  if I put extended connect api instead of
>regular connect, since I need to have access to some user data , it
>fails after I kill the server.

What does 'fails' actually mean... how and where?

-Andy

>wsi_dumb = libwebsocket_client_connect_extended(context, address, port,
>use_ssl,
>                            "/", address, address,
>                           protocols[0].name, ietf_version, (void*)&a);
>
>       /*wsi_dumb = libwebsocket_client_connect(context, address, port,
>                    use_ssl, "/", address, address,
>                    protocols[0].name,
>                    ietf_version);
>                */
>
>
>Enabling the commented code, reconnection logic works just fine.
>
>In callback handler, I am accessing value of as :
>
>   b = (int*)(user);
>   printf("value of user data b %d\n", *b);
>
>
>Any clue about this behavior?
>
>Thanks
>Hemant
>
>________________________________________
>From: Hemant Kumar [andy.green at linaro.org]
>Sent: Tuesday, December 8, 2015 6:24 PM
>To: libwebsockets at ml.libwebsockets.org
>Subject: Re: [Libwebsockets] Re-connection logic for libwebsockets
>
>Thanks a lot Andy for the much needed support.
>This works like gem
>
>My client is able to establish connection with server after later is
>killed and brought up again with your logic.
>
>Regards
>Hemant
>
>________________________________________
>From: Andy Green [andy.green at linaro.org] on behalf of Andy Green
>[andy at warmcat.com]
>Sent: Tuesday, December 8, 2015 3:21 PM
>To: Hemant Kumar; libwebsockets at ml.libwebsockets.org
>Subject: Re: [Libwebsockets] Re-connection logic for libwebsockets
>
>On December 9, 2015 4:07:50 AM GMT+08:00, Hemant Kumar
><hkumar at arubanetworks.com> wrote:
>>Also I can see , for reconnection case, connection establishement flow
>>exits after making the call with  LWS_CALLBACK_UNLOCK_POLL  from
>inside
>>insert_wsi_socket_into_fds.
>>
>>"{
>>
>>
>>    lws_plat_insert_socket_into_fds(context, wsi);
>>
>>    /* external POLL support via protocol 0 */
>>    context->protocols[0].callback(context, wsi,
>>        LWS_CALLBACK_ADD_POLL_FD,
>>        wsi->user_space, (void *) &pa, 0);
>>
>>    context->protocols[0].callback(context, wsi,
>>        LWS_CALLBACK_UNLOCK_POLL,
>>        wsi->user_space, (void *)&pa, 0);
>>
>>    return 0;
>>}
>>
>>
>>For first successful establishment, instead of exiting, callback
>>handler is called with LWS_CALLBACK_GET_THREAD_ID.
>
>I added support for automatic rate-limited reconnect to the test
>client...
>
>http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/commit/?id=e97378960fa26510b8a403448122a7ab1e790141
>
>...it works fine if I kill the server and restart it later.
>
>Please try that and see if you get the same result.
>
>-Andy
>
>>Thanks
>>Hemant
>>
>>
>>________________________________________
>>From: Hemant Kumar [andy.green at linaro.org]
>>Sent: Tuesday, December 8, 2015 11:06 AM
>>To: libwebsockets at ml.libwebsockets.org
>>Subject: Re: [Libwebsockets] Re-connection logic for libwebsockets
>>
>>Hi Andy
>>
>>Basically, client thread calls the following function for websocket
>>connection establishment.
>>For the very first time, or every time I kill the client process and
>>start again , it is able to establish the connection with server.
>>
>>But if I kill the server instead and make the client do connection
>>retries, for which it calls the following function, it fails.
>>Stack trace on client end:
>>
>>[441:1062] NOTICE: Initial logging level 15
>>[441:1062] NOTICE: Library version: 1.3 unknown-build-hash
>>[441:1062] NOTICE: IPV6 compiled in and enabled
>>[441:1062] NOTICE: libev support not compiled in
>>[441:1063] INFO:  LWS_MAX_HEADER_LEN: 1024
>>[441:1063] INFO:  LWS_MAX_PROTOCOLS: 5
>>[441:1063] INFO:  SPEC_LATEST_SUPPORTED: 13
>>[441:1063] INFO:  AWAITING_TIMEOUT: 5
>>[441:1063] INFO:  SYSTEM_RANDOM_FILEPATH: '/dev/urandom'
>>[441:1063] INFO:  LWS_MAX_ZLIB_CONN_BUFFER: 65536
>>[441:1064] NOTICE:  static allocation: 65912 + (12 x 1024 fds) = 78200
>>bytes
>>[441:1064] INFO:  LWS_MAX_EXTENSIONS_ACTIVE: 3
>>[441:1065] NOTICE:  canonical_hostname = XXX_Hemant
>>[441:1065] NOTICE:  per-conn mem: 128 + 1594 headers + protocol rx buf
>>[441:1137] NOTICE: context created
>>[441:1139] INFO: insert_wsi_socket_into_fds: wsi=0x51f234, sock=18,
>fds
>>pos=1
>>Exiting
>>[441:1140] NOTICE: libwebsocket_context_destroy
>>LWS_CALLBACK_CLIENT_CONNECTION_ERROR
>>[441:1140] NOTICE: LWS_CALLBACK_CLIENT_CONNECTION_ERROR
>>
>>
>>
>>
>>int amon_sender_websocket_proc(dest_ctxt_t *dcp)
>>{
>>    int n = 0;
>>    int ret = 0;
>>    int port = WS_PORT;
>>    int use_ssl = 0;
>>    __u32 server_address = 0;
>>    const char *address;
>>    struct in_addr serv_ip_addr;
>>
>>    struct libwebsocket *client_socket;
>>    int ietf_version = -1; /* latest */
>>    struct lws_context_creation_info ctxt_info;
>>
>>    fprintf(stderr, "amon_sender_websocket_proc()...\n");
>>    fprintf(stderr, "dcp = %p\n", dcp);
>>        //usleep(1000000);
>>
>>    thread_context_t *lws_queue_ctx;
>>   lws_queue_ctx =
>(thread_context_t*)malloc(sizeof(thread_context_t));
>>    memset((void*)lws_queue_ctx, 0, sizeof(thread_context_t));
>>
>>    /*List of supported protocols*/
>>    struct libwebsocket_protocols protocols[] = {
>>        {
>>            "comm-protocol",
>>            data_callback_handler,
>>            sizeof(struct per_session_data__sprotocol),
>>            0,
>>        },
>>        {   /* end of list */
>>            NULL,
>>            NULL,
>>            0,
>>            0,
>>        }
>>    };
>>syslog(LOG_ERR," mgmt-server transport_type
>>%d\n",dcp->mgmtsrv->transport_type);
>>syslog(LOG_ERR," mgmt-server security_type
>>%d\n",dcp->mgmtsrv->security_type);
>>
>>        //usleep(1000000);
>>
>>    //Initialize the context info
>>memset((void *)&ctxt_info, 0, sizeof(ctxt_info)); <<<<<<<<<<,Doing
>>memset of info struct for every time a connection attempt is made.
>>
>>    //client side websocket do not listens on any port
>>
>> ctxt_info.port = CONTEXT_PORT_NO_LISTEN;
>>    ctxt_info.protocols = protocols;
>>    ctxt_info.gid = -1;
>>    ctxt_info.uid = -1;
>>if ((dcp->mgmtsrv->transport_type == WEBSOCKET_MODE ||
>>dcp->mgmtsrv->transport_type == MIX_MODE)
>>            && dcp->mgmtsrv->security_type == SECURE_MODE )
>>    {
>>        use_ssl = 2;
>>        syslog(LOG_ERR," use_ssl flag set\n");
>>    }
>>        //usleep(1000000);
>>    if(use_ssl == 2){
>>        syslog(LOG_ERR," starting WS-SSL \n");
>>        ctxt_info.ssl_cert_filepath = CERT_PATH;
>>        ctxt_info.ssl_private_key_filepath = KEY_PATH;
>>    }else{
>>        ctxt_info.ssl_cert_filepath = NULL;
>>        ctxt_info.ssl_private_key_filepath = NULL;
>>    }
>>        //usleep(1000000);
>>
>>   lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO,
>NULL);
>>
>>    server_address =  dcp->mgmtsrv->primary_server_ip;
>>    serv_ip_addr.s_addr = server_address;
>>    address = inet_ntoa(serv_ip_addr);
>>    dcp->context = libwebsocket_create_context(&ctxt_info);
>>    if (dcp->context == NULL) {
>>        fprintf(stderr, "Creating libwebsocket context failed\n");
>>        syslog(LOG_ERR," Creating libwebsocket context failed\n");
>>        free(lws_queue_ctx);
>>        return -1;
>>    }
>>
>>    lwsl_notice("context created\n");
>>        //usleep(1000000);
>>    //register a signal handler for stopping the client
>>    signal(SIGINT, sighandler);
>>
>>
>>    lws_queue_ctx->dcp = dcp;
>>
>>   //Get client web socket
>>client_socket = libwebsocket_client_connect_extended(dcp->context,
>>address, port, use_ssl,
>>                                                "/", address, address,
>>              protocols[0].name, ietf_version,
>(void*)(lws_queue_ctx));
>>
>>
>>    //Use it in sender thread for invoking the callback
>>    dcp->wsi = client_socket;
>>
>>    if (client_socket == NULL) {
>>          fprintf(stderr, "libwebsocket connect failed:
>%s\n",address);
>>          syslog(LOG_ERR," libwebsocket connect failed:
>%s\n",address);
>>            ret = 1;
>>            goto bail;
>>    }
>>//lwsl_notice("connected to server..%s user data %d\n",address,
>>*((int*)(client_socket->user_space)));
>>    syslog(LOG_ERR,"libwebsocket connected: %s",address);
>>    n = 0;
>>    while (n >= 0 && !dcp->was_closed && !dcp->force_exit) {
>>            n = libwebsocket_service(dcp->context, 100000);
>>            if (n < 0) {
>>                //continue;  TBD dharani
>>                break;
>>            }
>>
>>    }
>>
>>    bail:
>>        fprintf(stderr, "Exiting\n");
>>        libwebsocket_context_destroy(dcp->context);
>>
>>        dcp->context = NULL;
>>        dcp->wsi = NULL;
>>
>>        return ret;
>>}
>>
>>
>>Any help will be appreciated.
>>
>>Thanks
>>Hemant
>>
>>________________________________________
>>From: Andy Green [andy.green at linaro.org] on behalf of Andy Green
>>[andy at warmcat.com]
>>Sent: Monday, December 7, 2015 7:52 PM
>>To: Hemant Kumar; libwebsockets at ml.libwebsockets.org
>>Subject: Re: [Libwebsockets] Re-connection logic for libwebsockets
>>
>>On December 8, 2015 11:18:47 AM GMT+08:00, Hemant Kumar
>><hkumar at arubanetworks.com> wrote:
>>>I have a working libwebsocket client server and I am trying to
>>>implement reconnection logic between the two entities.
>>>Basically, when connectivity to server is down for some reason,
>client
>>>keeps on trying libwebsocket_connect with same
>>>parameters as used for the initial successful connection
>>establishment.
>>>
>>>I do see , client making repeated tries but every time connection
>>>attempt fails , although server is UP on another end.
>>>For every failed try, I see libwebsocket_conext_destrory being also
>>>called, wondering if I am missing anything to clean
>>>the old context for the re-establishment of connection.
>>
>>Need more info about where (and / or why) it fails.
>>
>>However a common mistake is to not memset the info struct to zero
>>before filling it in.
>>
>>Another way to get 'memory' between sessions is via your protocols
>>struct, try copying it each time into another protocols struct and
>give
>>that one to lws_client_connect.
>>
>>-Andy
>>
>>>
>>>Please advise.
>>>
>>>Thanks
>>>Hemant
>>>
>>>
>>>------------------------------------------------------------------------
>>>
>>>_______________________________________________
>>>Libwebsockets mailing list
>>>Libwebsockets at ml.libwebsockets.org
>>>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>>
>>_______________________________________________
>>Libwebsockets mailing list
>>Libwebsockets at ml.libwebsockets.org
>>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>>_______________________________________________
>>Libwebsockets mailing list
>>Libwebsockets at ml.libwebsockets.org
>>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>
>_______________________________________________
>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org
>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>_______________________________________________
>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org
>http://ml.libwebsockets.org/mailman/listinfo/libwebsockets




More information about the Libwebsockets mailing list