2828#pragma warning(disable: 4706)
2929#endif
3030
31- #define WS_BLOCK 1
31+ #define WS_BLOCK 10000 /* ms, blocks read operation for 10 seconds */
32+ #define WS_SOFT_BLOCK 1000 /* ms, blocks read operation for 1 second */
3233#define WS_NOBLOCK 0
3334
3435#define WS_INIT_SANITY 5000
@@ -70,6 +71,7 @@ struct kws_s {
7071 char cipher_name [128 ];
7172 kws_flag_t flags ;
7273 int x ;
74+ int ssl_io_error ;
7375 void * write_buffer ;
7476 ks_size_t write_buffer_len ;
7577 char * req_uri ;
@@ -397,12 +399,14 @@ static int ws_server_handshake(kws_t *kws)
397399
398400}
399401
402+ #define SSL_IO_ERROR (err ) (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL)
400403#define SSL_ERROR_WANT_READ_WRITE (err ) (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
401404
402405KS_DECLARE (ks_ssize_t ) kws_raw_read (kws_t * kws , void * data , ks_size_t bytes , int block )
403406{
404407 int r ;
405408 int ssl_err = 0 ;
409+ int block_n = block / 10 ;
406410
407411 if (kws -> unprocessed_buffer_len > 0 ) {
408412 if (kws -> unprocessed_buffer_len > bytes ) {
@@ -430,6 +434,9 @@ KS_DECLARE(ks_ssize_t) kws_raw_read(kws_t *kws, void *data, ks_size_t bytes, int
430434 ssl_err = SSL_get_error (kws -> ssl , r );
431435 if (ssl_err != SSL_ERROR_ZERO_RETURN ) {
432436 ks_log (KS_LOG_WARNING , "Weird SSL_read error: %d\n" , ssl_err );
437+ if (SSL_IO_ERROR (ssl_err )) {
438+ kws -> ssl_io_error = 1 ;
439+ }
433440 }
434441 }
435442
@@ -444,12 +451,16 @@ KS_DECLARE(ks_ssize_t) kws_raw_read(kws_t *kws, void *data, ks_size_t bytes, int
444451 kws -> x ++ ;
445452 ks_sleep_ms (10 );
446453 } else {
454+ if (SSL_IO_ERROR (ssl_err )) {
455+ kws -> ssl_io_error = 1 ;
456+ }
457+
447458 r = -1 ;
448459 goto end ;
449460 }
450461 }
451462
452- } while (r < 0 && SSL_ERROR_WANT_READ_WRITE (ssl_err ) && kws -> x < 1000 );
463+ } while (r < 0 && SSL_ERROR_WANT_READ_WRITE (ssl_err ) && kws -> x < block_n );
453464
454465 goto end ;
455466 }
@@ -468,11 +479,11 @@ KS_DECLARE(ks_ssize_t) kws_raw_read(kws_t *kws, void *data, ks_size_t bytes, int
468479 ks_sleep_ms (10 );
469480 }
470481 }
471- } while (r == -1 && ks_errno_is_blocking (ks_errno ()) && kws -> x < 1000 );
482+ } while (r == -1 && ks_errno_is_blocking (ks_errno ()) && kws -> x < block_n );
472483
473484 end :
474485
475- if (kws -> x >= 10000 || (block && kws -> x >= 1000 )) {
486+ if (kws -> x >= 10000 || (block && kws -> x >= block_n )) {
476487 r = -1 ;
477488 }
478489
@@ -555,6 +566,11 @@ KS_DECLARE(ks_ssize_t) kws_raw_write(kws_t *kws, void *data, ks_size_t bytes)
555566 r = SSL_write (kws -> ssl , (void * )((unsigned char * )data + wrote ), (int )(bytes - wrote ));
556567
557568 if (r == 0 ) {
569+ ssl_err = SSL_get_error (kws -> ssl , r );
570+ if (SSL_IO_ERROR (ssl_err )) {
571+ kws -> ssl_io_error = 1 ;
572+ }
573+
558574 ssl_err = 42 ;
559575 break ;
560576 }
@@ -573,15 +589,21 @@ KS_DECLARE(ks_ssize_t) kws_raw_write(kws_t *kws, void *data, ks_size_t bytes)
573589 ms = 25 ;
574590 }
575591 }
592+
576593 ks_sleep_ms (ms );
577594 }
578595
579596 if (r < 0 ) {
580597 ssl_err = SSL_get_error (kws -> ssl , r );
581598
582599 if (!SSL_ERROR_WANT_READ_WRITE (ssl_err )) {
600+ if (SSL_IO_ERROR (ssl_err )) {
601+ kws -> ssl_io_error = 1 ;
602+ }
603+
583604 break ;
584605 }
606+
585607 ssl_err = 0 ;
586608 }
587609
@@ -873,7 +895,7 @@ KS_DECLARE(ks_status_t) kws_init_ex(kws_t **kwsP, ks_socket_t sock, SSL_CTX *ssl
873895 kws -> payload_size_max = ks_json_get_object_number_int (params , "payload_size_max" , 0 );
874896
875897 if ((flags & KWS_BLOCK )) {
876- kws -> block = 1 ;
898+ kws -> block = WS_BLOCK ;
877899 }
878900
879901 if (client_data ) {
@@ -1037,27 +1059,109 @@ KS_DECLARE(ks_ssize_t) kws_close(kws_t *kws, int16_t reason)
10371059 kws -> uri = NULL ;
10381060 }
10391061
1040- if (reason && kws -> sock != KS_SOCK_INVALID ) {
1062+ if (kws -> handshake && kws -> sock != KS_SOCK_INVALID ) {
10411063 uint16_t * u16 ;
1042- uint8_t fr [ 4 ] = { WSOC_CLOSE | 0x80 , 2 , 0 } ;
1064+ int16_t got_reason = reason ? reason : WS_NORMAL_CLOSE /* regular close initiated by us */ ;
10431065
1044- u16 = (uint16_t * ) & fr [2 ];
1045- * u16 = htons ((int16_t )reason );
1046- kws_raw_write (kws , fr , 4 );
1066+ if (kws -> type == KWS_CLIENT ) {
1067+ const uint8_t maskb = 0x80 ;
1068+ uint8_t size = 0x02 , fr [8 ] = {WSOC_CLOSE | 0x80 , size | maskb , 0 , 0 , 0 , 0 , 0 , 0 }, masking_key [4 ], i ;
1069+ uint8_t * p ;
1070+
1071+ u16 = (uint16_t * ) & fr [6 ];
1072+ * u16 = htons ((int16_t )got_reason );
1073+ p = (uint8_t * )u16 ; /*use p for masking the reason which is the payload */
1074+
1075+ gen_nonce (masking_key , 4 );
1076+ memcpy ((uint8_t * )fr + 2 , & masking_key , 4 );
1077+
1078+ for (i = 0 ; i < size ; i ++ ) {
1079+ * (p + i ) = (* ((uint8_t * )p + i )) ^ (* (masking_key + (i % 4 )));
1080+ }
1081+
1082+ kws_raw_write (kws , fr , 8 );
1083+ } else {
1084+ uint8_t fr [4 ] = {WSOC_CLOSE | 0x80 , 2 , 0 };
1085+
1086+ u16 = (uint16_t * ) & fr [2 ];
1087+ * u16 = htons ((int16_t )got_reason );
1088+ kws_raw_write (kws , fr , 4 );
1089+ }
10471090 }
10481091
10491092 if (kws -> ssl && kws -> sock != KS_SOCK_INVALID ) {
1050- /* first invocation of SSL_shutdown() would normally return 0 and just try to send SSL protocol close request.
1093+ /* first invocation of SSL_shutdown() would normally return 0 and just try to send SSL protocol close request (close_notify_alert) .
10511094 we just slightly polite, since we want to close socket fast and
10521095 not bother waiting for SSL protocol close response before closing socket,
10531096 since we want cleanup to be done fast for scenarios like:
10541097 client change NAT (like jump from one WiFi to another) and now unreachable from old ip:port, however
10551098 immidiately reconnect with new ip:port but old session id (and thus should replace the old session/channel)
1099+ However it is recommended to do bidirectional shutdown
1100+ and also to read all the remaining data sent by the client
1101+ before it indicates EOF (SSL_ERROR_ZERO_RETURN).
1102+ To avoid stuck in this process in case of dead peers,
1103+ we wait for WS_SOFT_BLOCK time (1s) before we give up.
10561104 */
1057- ERR_clear_error ();
1058- SSL_shutdown (kws -> ssl );
1105+ int code = 0 , rcode = 0 ;
1106+ int ssl_error = 0 ;
1107+ int n = 0 , block_n = WS_SOFT_BLOCK / 10 ;
1108+
1109+ /* SSL layer was never established or underlying IO error occured */
1110+ if (!kws -> secure_established || kws -> ssl_io_error ) {
1111+ goto end ;
1112+ }
1113+
1114+ /* connection has been already closed */
1115+ if (SSL_get_shutdown (kws -> ssl ) & SSL_SENT_SHUTDOWN ) {
1116+ goto end ;
1117+ }
1118+
1119+ /* peer closes the connection */
1120+ if (SSL_get_shutdown (kws -> ssl ) & SSL_RECEIVED_SHUTDOWN ) {
1121+ ERR_clear_error ();
1122+ SSL_shutdown (kws -> ssl );
1123+ goto end ;
1124+ }
1125+
1126+ /* us closes the connection. We do bidirection shutdown handshake */
1127+ for (;;) {
1128+ ERR_clear_error ();
1129+ code = SSL_shutdown (kws -> ssl );
1130+ ssl_error = SSL_get_error (kws -> ssl , code );
1131+ if (code <= 0 && ssl_error == SSL_ERROR_WANT_READ ) {
1132+ /* need to make sure there are no more data to read */
1133+ for (;;) {
1134+ ERR_clear_error ();
1135+ if ((rcode = SSL_read (kws -> ssl , kws -> buffer , 9 )) <= 0 ) {
1136+ ssl_error = SSL_get_error (kws -> ssl , rcode );
1137+ if (ssl_error == SSL_ERROR_ZERO_RETURN ) {
1138+ break ;
1139+ } else if (SSL_IO_ERROR (ssl_error )) {
1140+ goto end ;
1141+ } else if (ssl_error == SSL_ERROR_WANT_READ ) {
1142+ if (++ n == block_n ) {
1143+ goto end ;
1144+ }
1145+
1146+ ks_sleep_ms (10 );
1147+ } else {
1148+ goto end ;
1149+ }
1150+ }
1151+ }
1152+ } else if (code == 0 || (code < 0 && ssl_error == SSL_ERROR_WANT_WRITE )) {
1153+ if (++ n == block_n ) {
1154+ goto end ;
1155+ }
1156+
1157+ ks_sleep_ms (10 );
1158+ } else { /* code != 0 */
1159+ goto end ;
1160+ }
1161+ }
10591162 }
10601163
1164+ end :
10611165 /* restore to blocking here, so any further read/writes will block */
10621166 restore_socket (kws -> sock );
10631167
0 commit comments