@@ -211,10 +211,17 @@ int LibWebsocketClientPool::eventCallback(struct lws* wsi, enum lws_callback_rea
211
211
{
212
212
lws_set_timeout (waiting_client->m_wsi , static_cast <pending_timeout>(1 ), LWS_TO_KILL_SYNC);
213
213
}
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 ;
218
225
waiting_client->m_disconnect_cond_var .notify_all ();
219
226
}
220
227
}
@@ -242,6 +249,7 @@ LibWebsocketClientPool::Client::Client(LibWebsocketClientPool& pool)
242
249
m_connected(false ),
243
250
m_disconnect_cond_var(),
244
251
m_disconnect_mutex(),
252
+ m_disconnect_process_in_progress(false ),
245
253
m_disconnect_process_done(false ),
246
254
m_context(m_pool.m_context),
247
255
m_vhost(nullptr ),
@@ -282,6 +290,8 @@ bool LibWebsocketClientPool::Client::connect(const std::string& url,
282
290
{
283
291
bool ret = false ;
284
292
293
+ std::lock_guard<std::mutex> lock (m_disconnect_mutex);
294
+
285
295
// Check if thread is alive and if a listener has been registered
286
296
if (!m_vhost && m_listener)
287
297
{
@@ -334,19 +344,21 @@ bool LibWebsocketClientPool::Client::disconnect()
334
344
{
335
345
bool ret = false ;
336
346
347
+ std::unique_lock<std::mutex> lock (m_disconnect_mutex);
348
+
337
349
// Check if connected
338
- if (m_vhost )
350
+ if (!m_disconnect_process_in_progress && !m_protocol. empty () )
339
351
{
340
352
// 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 ;
343
356
m_pool.m_waiting_disconnect_queue .push (this );
344
357
lws_cancel_service (m_context);
345
358
346
359
// Wait actual disconnection
347
360
if (std::this_thread::get_id () != m_pool.m_thread ->get_id ())
348
361
{
349
- std::unique_lock<std::mutex> lock (m_disconnect_mutex);
350
362
m_disconnect_cond_var.wait (lock, [&] { return m_disconnect_process_done; });
351
363
}
352
364
}
@@ -374,6 +386,8 @@ bool LibWebsocketClientPool::Client::send(const void* data, size_t size)
374
386
{
375
387
bool ret = false ;
376
388
389
+ std::lock_guard<std::mutex> lock (m_disconnect_mutex);
390
+
377
391
// Check if connected
378
392
if (m_connected)
379
393
{
@@ -434,136 +448,144 @@ void LibWebsocketClientPool::Client::connectCallback(struct lws_sorted_usec_list
434
448
ScheduleData* schedule_data = lws_container_of (sul, ScheduleData, sched_list);
435
449
if (schedule_data)
436
450
{
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 )
440
456
{
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 )
456
459
{
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" )
458
475
{
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 ())
469
477
{
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 ();
472
479
}
473
- if (!client->m_credentials .client_certificate .empty ())
480
+ if (!client->m_credentials .tls13_cipher_list .empty ())
474
481
{
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 ();
477
483
}
478
- if (! client->m_credentials .client_certificate_private_key . empty () )
484
+ if (client->m_credentials .encoded_pem_certificates )
479
485
{
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
+ }
483
504
}
484
- }
485
- else
486
- {
487
- // Load PEM files from filesystem
488
- if (!client->m_credentials .server_certificate_ca .empty ())
505
+ else
489
506
{
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
+ }
491
520
}
492
- if (!client->m_credentials .client_certificate .empty ())
521
+ if (!client->m_credentials .client_certificate_private_key_passphrase .empty ())
493
522
{
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 ();
495
525
}
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 ();
504
526
}
505
- }
506
527
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 )
522
532
{
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" )
525
543
{
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 ;
527
562
}
528
- if (client-> m_credentials . allow_expired_certificates )
563
+ else
529
564
{
530
- connect_info.ssl_connection |= LCCSCF_ALLOW_EXPIRED ;
565
+ connect_info.port = 80 ;
531
566
}
532
- if (client->m_credentials . accept_untrusted_certificates )
567
+ if (client->m_url . port () )
533
568
{
534
- connect_info.ssl_connection |= LCCSCF_ALLOW_INSECURE ;
569
+ connect_info.port = static_cast < int >(client-> m_url . port ()) ;
535
570
}
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))
537
579
{
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 );
539
588
}
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 );
567
589
}
568
590
}
569
591
}
0 commit comments