Libwesocket Client + Server all in one

581 views Asked by At

I'am curently building a C Tasker, the goal of the program is to connect to a Main Server via Websockets and keep the connection Alive(Client Watchdog) as long as it is possible.

In the mean time the Tasker should be able to receive Jsons from clients (Server Behaviour), process them accordingly and answer.

To perfom this i use GLib's multi threading methods and the Libwebsockets library for the network part.

The C Client/Server Tasker is working well so the next step should be : when the connection is lost with the Main Server to try to reconnect "forever" until the Main Server is up, or to Fallback on another Main Server.

The problem here is that when i cut the connection with the server the watchdog thread seems to ignore the reconnection. As the thread is completely isolated from the libwesockets callbacks.

Here are the code snippets :

Call of Tasker Client in Tasker Server init

       int janus_websockets_init(janus_transport_callbacks *callback, const char *config_path) {            
  if(g_atomic_int_get(&stopping)) {                                                                  

    return -1;                                                                                       
  }                                                                                                  
  if(callback == NULL || config_path == NULL)                                                        
    return -1;                                                                                       
        gateway = callback;                                                                          

        Client_start() 

Tasker Server configuration

 struct lws_context_creation_info info;                                       
                        memset(&info, 0, sizeof info);                                               
                        info.port = wsport;                                                          
                        info.iface = ip ? ip : interface;                                            
                        info.protocols = wss_protocols;                                              
                        info.extensions = NULL;                                                      
                        info.ssl_cert_filepath = NULL;                                               
                        info.ssl_private_key_filepath = NULL;                                        
                        info.gid = -1;                                                               
                        info.uid = -1;                                                               
                        info.options = 0;                                                            
                        /* Create the WebSocket context */                                           
                        wss = lws_create_context(&info);                                             
                        if(wss == NULL) {                                                            
                                ZETA_LOG(LOG_FATAL, "Error initializing libwebsockets...\n");        
                        } else {                                                                     
                                ZETA_LOG(LOG_INFO, "WebSockets server started (port %d)...\n", wspor\
t);                                                                                                  
                        }  

Tasker Client Configuration

int

Client_start()                                                                                   
{                                                                                                    
  //* register the signal SIGINT handler */                                                          

  struct lws_context_creation_info info;                                                             

  memset(&info, 0, sizeof info);                                                                     
  info.port = CONTEXT_PORT_NO_LISTEN;                                                                
  info.iface = NULL;                                                                                 
  info.protocols = wss_protocols;                                                                    
  info.ssl_cert_filepath = NULL;                                                                     
  info.ssl_private_key_filepath = NULL;                                                              
  info.extensions = lws_get_internal_extensions();                                                   
  info.gid = -1;                                                                                     
  info.uid = -1;                                                                                     
  info.options = 0;                                                                                  

  protocol.name  = "janus-protocol";                                                                 
  protocol.callback = &ws_client_service_callback;                                                   
  protocol.per_session_data_size = sizeof(struct session_data);                                      
  protocol.rx_buffer_size = 0;                                                                       
  protocol.id = 0;                                                                                   
  protocol.user = NULL;                                                                              

  context = lws_create_context(&info); 

Tasker Client Watchdog Thread Call

if (context == NULL) {                                                                             
    printf(KRED"[Main Service] context is NULL.\n"RESET);                                            
    return -1;                                                                                       
  }                                                                                                  

  wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,                                       
                           "/", "xxx.xxx.xxx.xxx:5000", NULL,                                        
                           protocol.name, -1);                                                       

  if (wsz == NULL) {                                                                                 
    printf(KRED"[Main] wsi create error.\n"RESET);                                                   
    return -1;                                                                                       
  }                                                                                                  
  reco = false;                                                                                      
  printf(KGRN"[Main] wsi create success.\n"RESET);                                                   

  printf(KRED"[Main Service] %d\n", ConnOk, RESET);                                                  

  keepAlive =  g_thread_try_new("KeepAliveLoop", keep_alive_routine, context, NULL);                 

  while(!dead)                                                                                       
    lws_service(context, 50);                                                                        

  lws_context_destroy(context);                                                                      

  return 0;                                                                                          
}   

Finnaly The Tasker Client Thread routine Loop and Thread Loop Execution code

static void keep_alive_loop()                                                                        
{                                                                                                    
  json_t *hb = NULL;                                                                                 
  char *toto = NULL;                                                                                 

    if (reco == true)                                                                                
   {                                                                                                 
     wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,                                    
                              "/", "xxx.xxx.xxx.xxx:5000", NULL,                                     
                              protocol.name, -1);                                                    
     printf(KRED"[Main Service] UNDER LOOOOOOPING .\n"RESET);                                        
     reco = false;                                                                                   
     return;                                                                                         
   }                                                                                                 

    hb = json_object();                                                                              
    json_object_set_new(hb, "zetapush", json_string("keepalive"));                                   
    json_object_set_new(hb, "timeout", json_integer(8000));                                          
    toto = json_dumps(hb, 0);                                                                        
    websocket_client_keep_alive_write_back(hb);                                                      
    lws_callback_on_writable(wsz);                                                                   
}                                                                                                    

static void *keep_alive_routine(void *data)                                                          
{                                                                                                    
  printf(KBRN"[pthread_routine] WATCHDOG READY AND ANGRY .\n"RESET);                                 

  g_timeout_add_seconds(8, keep_alive_loop, NULL);                                                   
  alive_loop = g_main_loop_new(NULL, 0);                                                             
  g_main_loop_run(alive_loop);                                                                       
}  

If any further precision is needed let me know, i can also upload to github for better reading, any help or hint would be much appreciated :).

0

There are 0 answers