2121#pragma warning(disable: 4706)
2222#endif
2323
24- #define WS_BLOCK 1
24+ #define WS_BLOCK 10000 /* ms, blocks read operation for 10 seconds */
25+ #define WS_SOFT_BLOCK 1000 /* ms, blocks read operation for 1 second */
2526#define WS_NOBLOCK 0
2627
2728#define WS_INIT_SANITY 5000
@@ -267,7 +268,7 @@ int ws_handshake(wsh_t *wsh)
267268 return -3 ;
268269 }
269270
270- while ((bytes = ws_raw_read (wsh , wsh -> buffer + wsh -> datalen , wsh -> buflen - wsh -> datalen , WS_BLOCK )) > 0 ) {
271+ while ((bytes = ws_raw_read (wsh , wsh -> buffer + wsh -> datalen , wsh -> buflen - wsh -> datalen , WS_NOBLOCK )) > 0 ) {
271272 wsh -> datalen += bytes ;
272273 if (strstr (wsh -> buffer , "\r\n\r\n" ) || strstr (wsh -> buffer , "\n\n" )) {
273274 break ;
@@ -344,20 +345,26 @@ int ws_handshake(wsh_t *wsh)
344345 ws_raw_write (wsh , respond , strlen (respond ));
345346 }
346347
348+ if (bytes == -2 ) {
349+ return 0 ;
350+ }
351+
347352 ws_close (wsh , WS_NONE );
348353 }
349354
350355 return -1 ;
351356
352357}
353358
359+ #define SSL_IO_ERROR (err ) (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL)
354360#define SSL_WANT_READ_WRITE (err ) (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
355361int wss_error (wsh_t * wsh , int ssl_err , char const * who );
356362
357363ssize_t ws_raw_read (wsh_t * wsh , void * data , size_t bytes , int block )
358364{
359365 ssize_t r ;
360366 int ssl_err = 0 ;
367+ int block_n = block / 10 ;
361368
362369 wsh -> x ++ ;
363370 if (wsh -> x > 250 ) ms_sleep (1 );
@@ -367,7 +374,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
367374 //ERR_clear_error();
368375 r = SSL_read (wsh -> ssl , data , bytes );
369376
370- if (r < 0 ) {
377+ if (r <= 0 ) {
371378 ssl_err = SSL_get_error (wsh -> ssl , r );
372379
373380 if (SSL_WANT_READ_WRITE (ssl_err )) {
@@ -379,12 +386,16 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
379386 ms_sleep (10 );
380387 } else {
381388 wss_error (wsh , ssl_err , "ws_raw_read: SSL_read" );
389+ if (SSL_IO_ERROR (ssl_err )) {
390+ wsh -> ssl_io_error = 1 ;
391+ }
392+
382393 r = -1 ;
383394 goto end ;
384395 }
385396 }
386397
387- } while (r < 0 && SSL_WANT_READ_WRITE (ssl_err ) && wsh -> x < 1000 );
398+ } while (r < 0 && SSL_WANT_READ_WRITE (ssl_err ) && wsh -> x < block_n );
388399
389400 goto end ;
390401 }
@@ -404,11 +415,11 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
404415 ms_sleep (10 );
405416 }
406417 }
407- } while (r == -1 && xp_is_blocking (xp_errno ()) && wsh -> x < 1000 );
418+ } while (r == -1 && xp_is_blocking (xp_errno ()) && wsh -> x < block_n );
408419
409420 end :
410421
411- if (wsh -> x >= 10000 || (block && wsh -> x >= 1000 )) {
422+ if (wsh -> x >= 10000 || (block && wsh -> x >= block_n )) {
412423 r = -1 ;
413424 }
414425
@@ -510,6 +521,11 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
510521 r = SSL_write (wsh -> ssl , buf , size );
511522
512523 if (r == 0 ) {
524+ ssl_err = SSL_get_error (wsh -> ssl , r );
525+ if (SSL_IO_ERROR (ssl_err )) {
526+ wsh -> ssl_io_error = 1 ;
527+ }
528+
513529 ssl_err = -42 ;
514530 break ;
515531 }
@@ -528,16 +544,22 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
528544 ms = 50 ;
529545 }
530546 }
547+
531548 ms_sleep (ms );
532549 }
533550
534551 if (r < 0 ) {
535552 ssl_err = SSL_get_error (wsh -> ssl , r );
536553
537554 if (!SSL_WANT_READ_WRITE (ssl_err )) {
555+ if (SSL_IO_ERROR (ssl_err )) {
556+ wsh -> ssl_io_error = 1 ;
557+ }
558+
538559 ssl_err = wss_error (wsh , ssl_err , "ws_raw_write: SSL_write" );
539560 break ;
540561 }
562+
541563 ssl_err = 0 ;
542564 }
543565
@@ -600,18 +622,6 @@ static int setup_socket(ws_socket_t sock)
600622
601623}
602624
603- static int restore_socket (ws_socket_t sock )
604- {
605- unsigned long v = 0 ;
606-
607- if (ioctlsocket (sock , FIONBIO , & v ) == SOCKET_ERROR ) {
608- return -1 ;
609- }
610-
611- return 0 ;
612-
613- }
614-
615625#else
616626
617627static int setup_socket (ws_socket_t sock )
@@ -620,16 +630,6 @@ static int setup_socket(ws_socket_t sock)
620630 return fcntl (sock , F_SETFL , flags | O_NONBLOCK );
621631}
622632
623- static int restore_socket (ws_socket_t sock )
624- {
625- int flags = fcntl (sock , F_GETFL , 0 );
626-
627- flags &= ~O_NONBLOCK ;
628-
629- return fcntl (sock , F_SETFL , flags );
630-
631- }
632-
633633#endif
634634
635635
@@ -814,25 +814,60 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
814814 ws_raw_write (wsh , fr , 4 );
815815 }
816816
817- restore_socket (wsh -> sock );
818-
819817 if (wsh -> ssl ) {
820- int code = 0 ;
818+ int code = 0 , rcode = 0 ;
821819 int ssl_error = 0 ;
822- const char * buf = "0" ;
820+ int n = 0 , block_n = WS_SOFT_BLOCK / 10 ;
823821
824- /* check if no fatal error occurs on connection */
825- code = SSL_write (wsh -> ssl , buf , 1 );
826- ssl_error = SSL_get_error (wsh -> ssl , code );
822+ /* SSL layer was never established or underlying IO error occured */
823+ if (!wsh -> secure_established || wsh -> ssl_io_error ) {
824+ goto ssl_finish_it ;
825+ }
827826
828- if (ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL ) {
827+ /* connection has been already closed */
828+ if (SSL_get_shutdown (wsh -> ssl ) & SSL_SENT_SHUTDOWN ) {
829+ goto ssl_finish_it ;
830+ }
831+
832+ /* peer closes the connection */
833+ if (SSL_get_shutdown (wsh -> ssl ) & SSL_RECEIVED_SHUTDOWN ) {
834+ SSL_shutdown (wsh -> ssl );
829835 goto ssl_finish_it ;
830836 }
831837
832- code = SSL_shutdown (wsh -> ssl );
833- if (code == 0 ) {
834- /* need to make sure there is no more data to read */
835- ws_raw_read (wsh , wsh -> buffer , 9 , WS_BLOCK );
838+ /* us closes the connection. We do bidirection shutdown handshake */
839+ for (;;) {
840+ code = SSL_shutdown (wsh -> ssl );
841+ ssl_error = SSL_get_error (wsh -> ssl , code );
842+ if (code <= 0 && ssl_error == SSL_ERROR_WANT_READ ) {
843+ /* need to make sure there are no more data to read */
844+ for (;;) {
845+ if ((rcode = SSL_read (wsh -> ssl , wsh -> buffer , 9 )) <= 0 ) {
846+ ssl_error = SSL_get_error (wsh -> ssl , rcode );
847+ if (ssl_error == SSL_ERROR_ZERO_RETURN ) {
848+ break ;
849+ } else if (SSL_IO_ERROR (ssl_error )) {
850+ goto ssl_finish_it ;
851+ } else if (ssl_error == SSL_ERROR_WANT_READ ) {
852+ if (++ n == block_n ) {
853+ goto ssl_finish_it ;
854+ }
855+
856+ ms_sleep (10 );
857+ } else {
858+ goto ssl_finish_it ;
859+ }
860+ }
861+ }
862+ } else if (code == 0 || (code < 0 && ssl_error == SSL_ERROR_WANT_WRITE )) {
863+ if (++ n == block_n ) {
864+ goto ssl_finish_it ;
865+ }
866+
867+ ms_sleep (10 );
868+ } else { /* code != 0 */
869+ goto ssl_finish_it ;
870+ }
836871 }
837872
838873ssl_finish_it :
0 commit comments