diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index e81a4fc8b..7cefff282 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -195,36 +195,50 @@ send_hs: wsi->protocol->name, rawish, wsi->vhost->name); /* we are making our own connection */ + +#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) + + /* we have connected if we got here */ + + if (lwsi_state(wsi) == LRS_WAITING_CONNECT && + (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { + + if (!wsi->transaction_from_pipeline_queue && + lws_tls_restrict_borrow(wsi->context)) { + cce = "tls restriction limit"; + goto failed; + } + + /* we can retry this... just cook the SSL BIO the first time */ + + if (lws_ssl_client_bio_create(wsi) < 0) { + lwsl_err("%s: bio_create failed\n", __func__); + goto failed; + } + +//#if !defined(LWS_WITH_SYS_ASYNC_DNS) + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + n = lws_ssl_client_connect1(wsi); + if (!n) + return wsi; + if (n < 0) { + lwsl_err("%s: lws_ssl_client_connect1 failed\n", __func__); + goto failed; + } + } +//#endif + + lwsi_set_state(wsi, LRS_WAITING_SSL); + return wsi; + } +#endif + if (!rawish) lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); else { /* for a method = "RAW" connection, this makes us * established */ -#if defined(LWS_WITH_TLS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - - /* we can retry this... just cook the SSL BIO the first time */ - - if (lws_ssl_client_bio_create(wsi) < 0) { - lwsl_err("%s: bio_create failed\n", __func__); - goto failed; - } - - //#if !defined(LWS_WITH_SYS_ASYNC_DNS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (!n) - return wsi; - if (n < 0) { - lwsl_err("%s: lws_ssl_client_connect1 failed\n", __func__); - goto failed; - } - } - //#endif - } -#endif - #if 0 #if defined(LWS_WITH_SYS_ASYNC_DNS) if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { @@ -374,9 +388,12 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, goto failed; } #endif - +#if !defined(WIN32) /* - * We can check using getsockopt if our connect actually completed + * We can check using getsockopt if our connect actually completed. + * Posix connect() allows nonblocking to redo the connect to + * find out if it succeeded, for win32 we have to use this path + * and take WSAEALREADY as a successful connect. */ if (lwsi_state(wsi) == LRS_WAITING_CONNECT && @@ -409,6 +426,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, __func__, LWS_ERRNO); goto try_next_result_fds; } +#endif #if defined(LWS_WITH_UNIX_SOCK) if (ads && *ads == '+') { @@ -667,6 +685,7 @@ ads_known: errno_copy != LWS_EWOULDBLOCK #ifdef _WIN32 && errno_copy != WSAEINVAL + && errno_copy != WSAEISCONN #endif ) { #if defined(_DEBUG) @@ -681,6 +700,8 @@ ads_known: #if defined(WIN32) if (lws_plat_check_connection_error(wsi)) goto try_next_result_fds; + if (errno_copy == WSAEISCONN) + goto conn_good; #endif /* diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 636dcba25..cbf95f509 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -369,12 +369,34 @@ lws_tls_client_connect(struct lws *wsi) char a[32]; unsigned int len; #endif - int m, n; + int m, n, en; errno = 0; ERR_clear_error(); n = SSL_connect(wsi->tls.ssl); - if (n == 1) { + en = errno; + + m = lws_ssl_get_error(wsi, n); + + if (m == SSL_ERROR_SYSCALL +#if defined(WIN32) + && en +#endif + ) { + lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en); + return LWS_SSL_CAPABLE_ERROR; + } + + if (m == SSL_ERROR_SSL) + return LWS_SSL_CAPABLE_ERROR; + + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) + return LWS_SSL_CAPABLE_MORE_SERVICE_READ; + + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) + return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; + + if (n == 1 || m == SSL_ERROR_SYSCALL) { #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len); @@ -391,17 +413,6 @@ lws_tls_client_connect(struct lws *wsi) return LWS_SSL_CAPABLE_DONE; } - m = lws_ssl_get_error(wsi, n); - - if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL) - return LWS_SSL_CAPABLE_ERROR; - - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) - return LWS_SSL_CAPABLE_MORE_SERVICE_READ; - - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) - return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; - if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE;