}
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;
}
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
}