@@ -211,10 +211,17 @@ int LibWebsocketClientPool::eventCallback(struct lws* wsi, enum lws_callback_rea
211211                {
212212                    lws_set_timeout (waiting_client->m_wsi , static_cast <pending_timeout>(1 ), LWS_TO_KILL_SYNC);
213213                }
214-                 lws_vhost_destroy (waiting_client->m_vhost );
215-                 waiting_client->m_vhost                    = nullptr ;
216-                 waiting_client->m_connected                = false ;
217-                 waiting_client->m_disconnect_process_done  = true ;
214+                 if  (waiting_client->m_vhost )
215+                 {
216+                     lws_vhost_destroy (waiting_client->m_vhost );
217+                 }
218+ 
219+                 std::lock_guard<std::mutex> lock (waiting_client->m_disconnect_mutex );
220+                 waiting_client->m_protocol .clear ();
221+                 waiting_client->m_vhost                           = nullptr ;
222+                 waiting_client->m_connected                       = false ;
223+                 waiting_client->m_disconnect_process_in_progress  = false ;
224+                 waiting_client->m_disconnect_process_done         = true ;
218225                waiting_client->m_disconnect_cond_var .notify_all ();
219226            }
220227        }
@@ -242,6 +249,7 @@ LibWebsocketClientPool::Client::Client(LibWebsocketClientPool& pool)
242249      m_connected(false ),
243250      m_disconnect_cond_var(),
244251      m_disconnect_mutex(),
252+       m_disconnect_process_in_progress(false ),
245253      m_disconnect_process_done(false ),
246254      m_context(m_pool.m_context),
247255      m_vhost(nullptr ),
@@ -282,6 +290,8 @@ bool LibWebsocketClientPool::Client::connect(const std::string&        url,
282290{
283291    bool  ret = false ;
284292
293+     std::lock_guard<std::mutex> lock (m_disconnect_mutex);
294+ 
285295    //  Check if thread is alive and if a listener has been registered
286296    if  (!m_vhost && m_listener)
287297    {
@@ -334,19 +344,21 @@ bool LibWebsocketClientPool::Client::disconnect()
334344{
335345    bool  ret = false ;
336346
347+     std::unique_lock<std::mutex> lock (m_disconnect_mutex);
348+ 
337349    //  Check if connected
338-     if  (m_vhost )
350+     if  (!m_disconnect_process_in_progress && !m_protocol. empty () )
339351    {
340352        //  Schedule disconnection
341-         m_retry_interval          = 0 ;
342-         m_disconnect_process_done = false ;
353+         m_retry_interval                 = 0 ;
354+         m_disconnect_process_in_progress = true ;
355+         m_disconnect_process_done        = false ;
343356        m_pool.m_waiting_disconnect_queue .push (this );
344357        lws_cancel_service (m_context);
345358
346359        //  Wait actual disconnection
347360        if  (std::this_thread::get_id () != m_pool.m_thread ->get_id ())
348361        {
349-             std::unique_lock<std::mutex> lock (m_disconnect_mutex);
350362            m_disconnect_cond_var.wait (lock, [&] { return  m_disconnect_process_done; });
351363        }
352364    }
@@ -374,6 +386,8 @@ bool LibWebsocketClientPool::Client::send(const void* data, size_t size)
374386{
375387    bool  ret = false ;
376388
389+     std::lock_guard<std::mutex> lock (m_disconnect_mutex);
390+ 
377391    //  Check if connected
378392    if  (m_connected)
379393    {
@@ -434,136 +448,144 @@ void LibWebsocketClientPool::Client::connectCallback(struct lws_sorted_usec_list
434448    ScheduleData* schedule_data = lws_container_of (sul, ScheduleData, sched_list);
435449    if  (schedule_data)
436450    {
437-         //  Check if vhost has been created
438-         Client* client = schedule_data->client ;
439-         if  (!client->m_vhost )
451+         Client*                     client = schedule_data->client ;
452+         std::lock_guard<std::mutex> lock (client->m_disconnect_mutex );
453+ 
454+         //  Check if a disconnect process is in progress
455+         if  (!client->m_disconnect_process_in_progress )
440456        {
441-             //  Define callback
442-             struct  lws_protocols  protocols[] = {
443-                 {" LibWebsocketClientPoolClient"  , &LibWebsocketClientPool::Client::eventCallback, 0 , 0 , 0 , client, 0 },
444-                 LWS_PROTOCOL_LIST_TERM};
445- 
446-             //  Fill vhost information
447-             struct  lws_context_creation_info  vhost_info;
448-             memset (&vhost_info, 0 , sizeof (vhost_info));
449-             vhost_info.options               = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
450-             vhost_info.port                  = CONTEXT_PORT_NO_LISTEN;
451-             vhost_info.timeout_secs          = client->m_connect_timeout ;
452-             vhost_info.connect_timeout_secs  = client->m_connect_timeout ;
453-             vhost_info.protocols             = protocols;
454-             vhost_info.log_cx                = &pool->m_logs_context ;
455-             if  (client->m_url .protocol () == " wss"  )
457+             //  Check if vhost has been created
458+             if  (!client->m_vhost )
456459            {
457-                 if  (!client->m_credentials .tls12_cipher_list .empty ())
460+                 //  Define callback
461+                 struct  lws_protocols  protocols[] = {
462+                     {" LibWebsocketClientPoolClient"  , &LibWebsocketClientPool::Client::eventCallback, 0 , 0 , 0 , client, 0 },
463+                     LWS_PROTOCOL_LIST_TERM};
464+ 
465+                 //  Fill vhost information
466+                 struct  lws_context_creation_info  vhost_info;
467+                 memset (&vhost_info, 0 , sizeof (vhost_info));
468+                 vhost_info.options               = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
469+                 vhost_info.port                  = CONTEXT_PORT_NO_LISTEN;
470+                 vhost_info.timeout_secs          = client->m_connect_timeout ;
471+                 vhost_info.connect_timeout_secs  = client->m_connect_timeout ;
472+                 vhost_info.protocols             = protocols;
473+                 vhost_info.log_cx                = &pool->m_logs_context ;
474+                 if  (client->m_url .protocol () == " wss"  )
458475                {
459-                     vhost_info.client_ssl_cipher_list  = client->m_credentials .tls12_cipher_list .c_str ();
460-                 }
461-                 if  (!client->m_credentials .tls13_cipher_list .empty ())
462-                 {
463-                     vhost_info.client_tls_1_3_plus_cipher_list  = client->m_credentials .tls13_cipher_list .c_str ();
464-                 }
465-                 if  (client->m_credentials .encoded_pem_certificates )
466-                 {
467-                     //  Use PEM encoded data
468-                     if  (!client->m_credentials .server_certificate_ca .empty ())
476+                     if  (!client->m_credentials .tls12_cipher_list .empty ())
469477                    {
470-                         vhost_info.client_ssl_ca_mem      = client->m_credentials .server_certificate_ca .c_str ();
471-                         vhost_info.client_ssl_ca_mem_len  = static_cast <unsigned  int >(client->m_credentials .server_certificate_ca .size ());
478+                         vhost_info.client_ssl_cipher_list  = client->m_credentials .tls12_cipher_list .c_str ();
472479                    }
473-                     if  (!client->m_credentials .client_certificate .empty ())
480+                     if  (!client->m_credentials .tls13_cipher_list .empty ())
474481                    {
475-                         vhost_info.client_ssl_cert_mem      = client->m_credentials .client_certificate .c_str ();
476-                         vhost_info.client_ssl_cert_mem_len  = static_cast <unsigned  int >(client->m_credentials .client_certificate .size ());
482+                         vhost_info.client_tls_1_3_plus_cipher_list  = client->m_credentials .tls13_cipher_list .c_str ();
477483                    }
478-                     if  (! client->m_credentials .client_certificate_private_key . empty () )
484+                     if  (client->m_credentials .encoded_pem_certificates )
479485                    {
480-                         vhost_info.client_ssl_key_mem  = client->m_credentials .client_certificate_private_key .c_str ();
481-                         vhost_info.client_ssl_key_mem_len  =
482-                             static_cast <unsigned  int >(client->m_credentials .client_certificate_private_key .size ());
486+                         //  Use PEM encoded data
487+                         if  (!client->m_credentials .server_certificate_ca .empty ())
488+                         {
489+                             vhost_info.client_ssl_ca_mem  = client->m_credentials .server_certificate_ca .c_str ();
490+                             vhost_info.client_ssl_ca_mem_len  =
491+                                 static_cast <unsigned  int >(client->m_credentials .server_certificate_ca .size ());
492+                         }
493+                         if  (!client->m_credentials .client_certificate .empty ())
494+                         {
495+                             vhost_info.client_ssl_cert_mem      = client->m_credentials .client_certificate .c_str ();
496+                             vhost_info.client_ssl_cert_mem_len  = static_cast <unsigned  int >(client->m_credentials .client_certificate .size ());
497+                         }
498+                         if  (!client->m_credentials .client_certificate_private_key .empty ())
499+                         {
500+                             vhost_info.client_ssl_key_mem  = client->m_credentials .client_certificate_private_key .c_str ();
501+                             vhost_info.client_ssl_key_mem_len  =
502+                                 static_cast <unsigned  int >(client->m_credentials .client_certificate_private_key .size ());
503+                         }
483504                    }
484-                 }
485-                 else 
486-                 {
487-                     //  Load PEM files from filesystem
488-                     if  (!client->m_credentials .server_certificate_ca .empty ())
505+                     else 
489506                    {
490-                         vhost_info.client_ssl_ca_filepath  = client->m_credentials .server_certificate_ca .c_str ();
507+                         //  Load PEM files from filesystem
508+                         if  (!client->m_credentials .server_certificate_ca .empty ())
509+                         {
510+                             vhost_info.client_ssl_ca_filepath  = client->m_credentials .server_certificate_ca .c_str ();
511+                         }
512+                         if  (!client->m_credentials .client_certificate .empty ())
513+                         {
514+                             vhost_info.client_ssl_cert_filepath  = client->m_credentials .client_certificate .c_str ();
515+                         }
516+                         if  (!client->m_credentials .client_certificate_private_key .empty ())
517+                         {
518+                             vhost_info.client_ssl_private_key_filepath  = client->m_credentials .client_certificate_private_key .c_str ();
519+                         }
491520                    }
492-                     if  (!client->m_credentials .client_certificate .empty ())
521+                     if  (!client->m_credentials .client_certificate_private_key_passphrase .empty ())
493522                    {
494-                         vhost_info.client_ssl_cert_filepath  = client->m_credentials .client_certificate .c_str ();
523+                         vhost_info.client_ssl_private_key_password  =
524+                             client->m_credentials .client_certificate_private_key_passphrase .c_str ();
495525                    }
496-                     if  (!client->m_credentials .client_certificate_private_key .empty ())
497-                     {
498-                         vhost_info.client_ssl_private_key_filepath  = client->m_credentials .client_certificate_private_key .c_str ();
499-                     }
500-                 }
501-                 if  (!client->m_credentials .client_certificate_private_key_passphrase .empty ())
502-                 {
503-                     vhost_info.client_ssl_private_key_password  = client->m_credentials .client_certificate_private_key_passphrase .c_str ();
504526                }
505-             }
506527
507-             //  Create vhost
508-             client->m_vhost  = lws_create_vhost (client->m_context , &vhost_info);
509-         }
510-         if  (client->m_vhost )
511-         {
512-             //  Connexion parameters
513-             struct  lws_client_connect_info  connect_info;
514-             memset (&connect_info, 0 , sizeof (connect_info));
515-             connect_info.context  = client->m_context ;
516-             connect_info.vhost    = client->m_vhost ;
517-             connect_info.address  = client->m_url .address ().c_str ();
518-             connect_info.path     = client->m_url .path ().c_str ();
519-             connect_info.host     = connect_info.address ;
520-             connect_info.origin   = connect_info.address ;
521-             if  (client->m_url .protocol () == " wss"  )
528+                 //  Create vhost
529+                 client->m_vhost  = lws_create_vhost (client->m_context , &vhost_info);
530+             }
531+             if  (client->m_vhost )
522532            {
523-                 connect_info.ssl_connection  = LCCSCF_USE_SSL;
524-                 if  (client->m_credentials .allow_selfsigned_certificates )
533+                 //  Connexion parameters
534+                 struct  lws_client_connect_info  connect_info;
535+                 memset (&connect_info, 0 , sizeof (connect_info));
536+                 connect_info.context  = client->m_context ;
537+                 connect_info.vhost    = client->m_vhost ;
538+                 connect_info.address  = client->m_url .address ().c_str ();
539+                 connect_info.path     = client->m_url .path ().c_str ();
540+                 connect_info.host     = connect_info.address ;
541+                 connect_info.origin   = connect_info.address ;
542+                 if  (client->m_url .protocol () == " wss"  )
525543                {
526-                     connect_info.ssl_connection  |= LCCSCF_ALLOW_SELFSIGNED;
544+                     connect_info.ssl_connection  = LCCSCF_USE_SSL;
545+                     if  (client->m_credentials .allow_selfsigned_certificates )
546+                     {
547+                         connect_info.ssl_connection  |= LCCSCF_ALLOW_SELFSIGNED;
548+                     }
549+                     if  (client->m_credentials .allow_expired_certificates )
550+                     {
551+                         connect_info.ssl_connection  |= LCCSCF_ALLOW_EXPIRED;
552+                     }
553+                     if  (client->m_credentials .accept_untrusted_certificates )
554+                     {
555+                         connect_info.ssl_connection  |= LCCSCF_ALLOW_INSECURE;
556+                     }
557+                     if  (client->m_credentials .skip_server_name_check )
558+                     {
559+                         connect_info.ssl_connection  |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
560+                     }
561+                     connect_info.port  = 443 ;
527562                }
528-                 if  (client-> m_credentials . allow_expired_certificates ) 
563+                 else 
529564                {
530-                     connect_info.ssl_connection  |= LCCSCF_ALLOW_EXPIRED ;
565+                     connect_info.port  =  80 ;
531566                }
532-                 if  (client->m_credentials . accept_untrusted_certificates )
567+                 if  (client->m_url . port () )
533568                {
534-                     connect_info.ssl_connection  |= LCCSCF_ALLOW_INSECURE ;
569+                     connect_info.port  =  static_cast < int >(client-> m_url . port ()) ;
535570                }
536-                 if  (client->m_credentials .skip_server_name_check )
571+                 connect_info.protocol               = client->m_protocol .c_str ();
572+                 connect_info.local_protocol_name    = " LibWebsocketClientPoolClient"  ;
573+                 connect_info.pwsi                   = &client->m_wsi ;
574+                 connect_info.retry_and_idle_policy  = &client->m_retry_policy ;
575+                 connect_info.userdata               = client;
576+ 
577+                 //  Start connection
578+                 if  (!lws_client_connect_via_info (&connect_info))
537579                {
538-                     connect_info.ssl_connection  |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
580+                     //  Schedule a retry
581+                     client->m_retry_count  = 0 ;
582+                     lws_retry_sul_schedule (pool->m_context ,
583+                                            0 ,
584+                                            sul,
585+                                            &client->m_retry_policy ,
586+                                            &LibWebsocketClientPool::Client::connectCallback,
587+                                            &client->m_retry_count );
539588                }
540-                 connect_info.port  = 443 ;
541-             }
542-             else 
543-             {
544-                 connect_info.port  = 80 ;
545-             }
546-             if  (client->m_url .port ())
547-             {
548-                 connect_info.port  = static_cast <int >(client->m_url .port ());
549-             }
550-             connect_info.protocol               = client->m_protocol .c_str ();
551-             connect_info.local_protocol_name    = " LibWebsocketClientPoolClient"  ;
552-             connect_info.pwsi                   = &client->m_wsi ;
553-             connect_info.retry_and_idle_policy  = &client->m_retry_policy ;
554-             connect_info.userdata               = client;
555- 
556-             //  Start connection
557-             if  (!lws_client_connect_via_info (&connect_info))
558-             {
559-                 //  Schedule a retry
560-                 client->m_retry_count  = 0 ;
561-                 lws_retry_sul_schedule (pool->m_context ,
562-                                        0 ,
563-                                        sul,
564-                                        &client->m_retry_policy ,
565-                                        &LibWebsocketClientPool::Client::connectCallback,
566-                                        &client->m_retry_count );
567589            }
568590        }
569591    }
0 commit comments