diff --git a/CMakeLists.txt b/CMakeLists.txt index fcd678dd..4d511e28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -486,7 +486,7 @@ if (LWS_WITH_SSL) message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") include_directories("${OPENSSL_INCLUDE_DIR}") - list(APPEND LIB_LIST ${OPENSSL_LIBRARIES}) + list(APPEND LIB_LIST ${OPENSSL_LIBRARIES} dl) endif() endif(LWS_WITH_SSL) diff --git a/README.build b/README.build index 9c33e175..4620661d 100644 --- a/README.build +++ b/README.build @@ -60,6 +60,13 @@ Building on Unix: following to the cmake line -DLIB_SUFFIX=64 + + NOTE4 + If you are building against a non-distro OpenSSL (eg, in order to get + access to ALPN support only in newer OpenSSL versions) the nice way to + express that in one cmake command is eg, + + -DOPENSSL_ROOT_DIR=/usr/local/ssl 4. Finally you can build using the generated Makefile: diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 8d564584..c5b17013 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1010,6 +1010,7 @@ enum pending_timeout { PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, PENDING_TIMEOUT_SSL_ACCEPT, PENDING_TIMEOUT_HTTP_CONTENT, + PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, }; LWS_VISIBLE LWS_EXTERN void diff --git a/lib/output.c b/lib/output.c index a7e2087b..5502ae90 100644 --- a/lib/output.c +++ b/lib/output.c @@ -123,42 +123,16 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) * nope, send it on the socket directly */ lws_latency_pre(context, wsi); -#ifdef LWS_OPENSSL_SUPPORT - if (wsi->ssl) { - n = SSL_write(wsi->ssl, buf, len); - lws_latency(context, wsi, "SSL_write lws_issue_raw", n, n >= 0); - if (n < 0) { - n = SSL_get_error(wsi->ssl, n); - if (n == SSL_ERROR_WANT_READ || - n == SSL_ERROR_WANT_WRITE) { - if (n == SSL_ERROR_WANT_WRITE) - lws_set_blocking_send(wsi); - n = 0; - goto handle_truncated_send; - } - lwsl_debug("ERROR writing to socket\n"); - return -1; - } - } else { -#endif - n = send(wsi->sock, buf, len, MSG_NOSIGNAL); - lws_latency(context, wsi, "send lws_issue_raw", n, n == len); - if (n < 0) { - if (LWS_ERRNO == LWS_EAGAIN || - LWS_ERRNO == LWS_EWOULDBLOCK || - LWS_ERRNO == LWS_EINTR) { - if (LWS_ERRNO == LWS_EWOULDBLOCK) - lws_set_blocking_send(wsi); - n = 0; - goto handle_truncated_send; - } - lwsl_debug("ERROR writing len %d to skt %d\n", len, n); - return -1; - } -#ifdef LWS_OPENSSL_SUPPORT + n = lws_ssl_capable_write(wsi, buf, len); + lws_latency(context, wsi, "send lws_issue_raw", n, n == len); + switch (n) { + case LWS_SSL_CAPABLE_ERROR: + return -1; + case LWS_SSL_CAPABLE_MORE_SERVICE: + n = 0; + goto handle_truncated_send; } -#endif handle_truncated_send: /* @@ -549,3 +523,38 @@ all_sent: return 0; /* indicates further processing must be done */ } + +LWS_VISIBLE int +lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len) +{ + int n; + + n = recv(wsi->sock, buf, len, 0); + if (n < 0) { + lwsl_warn("error on reading from skt\n"); + return LWS_SSL_CAPABLE_ERROR; + } + + return n; +} + +LWS_VISIBLE int +lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len) +{ + int n; + + n = send(wsi->sock, buf, len, MSG_NOSIGNAL); + if (n < 0) { + if (LWS_ERRNO == LWS_EAGAIN || + LWS_ERRNO == LWS_EWOULDBLOCK || + LWS_ERRNO == LWS_EINTR) { + if (LWS_ERRNO == LWS_EWOULDBLOCK) + lws_set_blocking_send(wsi); + return LWS_SSL_CAPABLE_MORE_SERVICE; + } + lwsl_debug("ERROR writing len %d to skt %d\n", len, n); + return LWS_SSL_CAPABLE_ERROR; + } + + return n; +} diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index c365a808..9df66517 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -327,6 +327,7 @@ enum connection_mode { LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT, LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY, LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE, + LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2, LWS_CONNMODE_WS_CLIENT_WAITING_SSL, LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY, LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT, @@ -742,9 +743,18 @@ SHA1(const unsigned char *d, size_t n, unsigned char *md); #define lws_context_init_server_ssl(_a, _b) (0) #define lws_ssl_destroy(_a) #define lws_context_init_http2_ssl(_a) +#define lws_ssl_pending(_a) (0) +#define lws_ssl_capable_read lws_ssl_capable_read_no_ssl +#define lws_ssl_capable_write lws_ssl_capable_write_no_ssl #else - +LWS_EXTERN int lws_ssl_pending(struct libwebsocket *wsi); LWS_EXTERN int openssl_websocket_private_data_index; +LWS_EXTERN int +lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len); + +LWS_EXTERN int +lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len); + #ifndef LWS_NO_SERVER LWS_EXTERN int lws_context_init_server_ssl(struct lws_context_creation_info *info, @@ -755,6 +765,17 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, LWS_EXTERN void lws_ssl_destroy(struct libwebsocket_context *context); +enum lws_ssl_capable_status { + LWS_SSL_CAPABLE_ERROR = -1, + LWS_SSL_CAPABLE_MORE_SERVICE = -2, +}; + +LWS_EXTERN int +lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len); + +LWS_EXTERN int +lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len); + /* HTTP2-related */ #ifdef LWS_USE_HTTP2 @@ -763,7 +784,6 @@ lws_context_init_http2_ssl(struct libwebsocket_context *context); #else #define lws_context_init_http2_ssl(_a) #endif - #endif #ifndef LWS_NO_CLIENT diff --git a/lib/ssl.c b/lib/ssl.c index 480256fd..c653454d 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -331,4 +331,53 @@ int lws_context_init_client_ssl(struct lws_context_creation_info *info, return 0; } -#endif \ No newline at end of file +#endif + +LWS_VISIBLE int +lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len) +{ + int n; + + if (!wsi->ssl) + return lws_ssl_capable_read_no_ssl(wsi, buf, len); + + n = SSL_read(wsi->ssl, buf, len); + if (n >= 0) + return n; + + n = SSL_get_error(wsi->ssl, len); + if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) + return LWS_SSL_CAPABLE_MORE_SERVICE; + + return LWS_SSL_CAPABLE_ERROR; +} + +LWS_VISIBLE int +lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len) +{ + int n; + + if (!wsi->ssl) + return lws_ssl_capable_write_no_ssl(wsi, buf, len); + + n = SSL_write(wsi->ssl, buf, len); + if (n >= 0) + return n; + + n = SSL_get_error(wsi->ssl, len); + if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) { + if (n == SSL_ERROR_WANT_WRITE) + lws_set_blocking_send(wsi); + return LWS_SSL_CAPABLE_MORE_SERVICE; + } + + return LWS_SSL_CAPABLE_ERROR; +} + +LWS_VISIBLE int +lws_ssl_pending(struct libwebsocket *wsi) +{ + if (wsi->ssl) + return SSL_pending(wsi->ssl); + return 0; +} \ No newline at end of file