diff --git a/src/mod/endpoints/mod_verto/ws.c b/src/mod/endpoints/mod_verto/ws.c index 1185743298..f33ce57239 100644 --- a/src/mod/endpoints/mod_verto/ws.c +++ b/src/mod/endpoints/mod_verto/ws.c @@ -698,23 +698,6 @@ void ws_destroy(wsh_t *wsh) } if (wsh->ssl) { - int code, ssl_err, sanity = 100; - do { - code = SSL_shutdown(wsh->ssl); - if (code == 1) { - break; - } - if (code < 0) { - ssl_err = SSL_get_error(wsh->ssl, code); - } - if (wsh->block) { - ms_sleep(10); - } else { - ms_sleep(1); - } - - } while ((code == 0 || (code < 0 && SSL_WANT_READ_WRITE(ssl_err))) && --sanity > 0); - SSL_free(wsh->ssl); wsh->ssl = NULL; } @@ -749,12 +732,30 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason) ws_raw_write(wsh, fr, 4); } + if (wsh->ssl && wsh->sock != ws_sock_invalid) { + /* first invocation of SSL_shutdown() would normally return 0 and just try to send SSL protocol close request. + we just slightly polite, since we want to close socket fast and + not bother waiting for SSL protocol close response before closing socket, + since we want cleanup to be done fast for scenarios like: + client change NAT (like jump from one WiFi to another) and now unreachable from old ip:port, however + immidiately reconnect with new ip:port but old session id (and thus should replace the old session/channel) + */ + SSL_shutdown(wsh->ssl); + } + + /* restore to blocking here, so any further read/writes will block */ restore_socket(wsh->sock); if (wsh->close_sock && wsh->sock != ws_sock_invalid) { + /* signal socket to shutdown() before close(): FIN-ACK-FIN-ACK insead of RST-RST + do not really handle errors here since it all going to die anyway. + all buffered writes if any(like SSL_shutdown() ones) will still be sent. + */ #ifndef WIN32 + shutdown(wsh->sock, SHUT_RDWR); close(wsh->sock); #else + shutdown(wsh->sock, SD_BOTH); closesocket(wsh->sock); #endif }