diff --git a/CMakeLists.txt b/CMakeLists.txt index 78cb7dbf..fcd678dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF) option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" OFF) option(LWS_WITH_LIBEV "Compile with support for libev" OFF) option(LWS_IPV6 "Compile with support for ipv6" ON) +option(LWS_WITH_HTTP2 "Compile with support for http2" OFF) # Allow the user to override installation directories. set(LWS_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") @@ -125,6 +126,10 @@ if (LWS_IPV6) set(LWS_USE_IPV6 1) endif() +if (LWS_WITH_HTTP2) + set(LWS_USE_HTTP2 1) +endif() + if (MINGW) set(LWS_MINGW_SUPPORT 1) endif() @@ -282,6 +287,11 @@ if (LWS_WITH_SSL) ) endif() +if (LWS_WITH_HTTP2) + list(APPEND SOURCES + lib/ssl-http2.c + ) +endif() # select the active platform files if (WIN32) @@ -875,7 +885,8 @@ message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}") message(" LWS_WITH_LATENCY = ${LWS_WITH_LATENCY}") message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}") message(" LWS_USE_LIBEV = ${LWS_USE_LIBEV}") -message(" LWS_USE_IPV6 = ${LWS_USE_IPV6}") +message(" LWS_IPV6 = ${LWS_IPV6}") +message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}") message("---------------------------------------------------------------------") # These will be available to parent projects including libwebsockets using add_subdirectory() diff --git a/config.h.cmake b/config.h.cmake index ddd8ec6e..bc16e238 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -32,6 +32,9 @@ /* Build with support for ipv6 */ #cmakedefine LWS_USE_IPV6 +/* Build with support for HTTP2 */ +#cmakedefine LWS_USE_HTTP2 + /* Turn on latency measuring code */ #cmakedefine LWS_LATENCY diff --git a/lib/context.c b/lib/context.c index 0f4e1c4d..3580d4ac 100644 --- a/lib/context.c +++ b/lib/context.c @@ -109,8 +109,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info) #endif lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED); lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT); - if (info->ssl_cipher_list) - lwsl_info(" SSL ciphers: '%s'\n", info->ssl_cipher_list); lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER); @@ -229,38 +227,11 @@ libwebsocket_create_context(struct lws_context_creation_info *info) context->http_proxy_address, context->http_proxy_port); -#ifndef LWS_NO_SERVER - if (info->port != CONTEXT_PORT_NO_LISTEN) { - -#ifdef LWS_OPENSSL_SUPPORT - context->use_ssl = info->ssl_cert_filepath != NULL && - info->ssl_private_key_filepath != NULL; -#ifdef USE_CYASSL - lwsl_notice(" Compiled with CYASSL support\n"); -#else - lwsl_notice(" Compiled with OpenSSL support\n"); -#endif - if (context->use_ssl) - lwsl_notice(" Using SSL mode\n"); - else - lwsl_notice(" Using non-SSL mode\n"); - -#else - if (info->ssl_cert_filepath != NULL && - info->ssl_private_key_filepath != NULL) { - lwsl_notice(" Not compiled for OpenSSl support!\n"); - goto bail; - } - lwsl_notice(" Compiled without SSL support\n"); -#endif - - lwsl_notice( - " per-conn mem: %u + %u headers + protocol rx buf\n", + lwsl_notice( + " per-conn mem: %u + %u headers + protocol rx buf\n", sizeof(struct libwebsocket), sizeof(struct allocated_headers)); - } -#endif - + if (lws_context_init_server_ssl(info, context)) goto bail; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index da035a10..1443de00 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -739,6 +739,7 @@ unsigned char * 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) #else LWS_EXTERN int openssl_websocket_private_data_index; @@ -751,6 +752,16 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, #endif LWS_EXTERN void lws_ssl_destroy(struct libwebsocket_context *context); + +/* HTTP2-related */ + +#ifdef LWS_USE_HTTP2 +LWS_EXTERN void +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-http2.c b/lib/ssl-http2.c new file mode 100644 index 00000000..237f43cd --- /dev/null +++ b/lib/ssl-http2.c @@ -0,0 +1,78 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010-2014 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Some or all of this file is based on code from nghttp2, which has the + * following license. Since it's more liberal than lws license, you're also + * at liberty to get the original code from + * https://github.com/tatsuhiro-t/nghttp2 under his liberal terms alone. + * + * nghttp2 - HTTP/2.0 C Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "private-libwebsockets.h" + +#ifndef LWS_NO_SERVER + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +static int alpn_select_proto_cb(SSL* ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + void *arg) +{ + lwsl_err((char *)in); + return SSL_TLSEXT_ERR_OK; /* SSL_TLSEXT_ERR_NOACK */ +} +#endif + +LWS_VISIBLE void +lws_context_init_http2_ssl(struct libwebsocket_context *context) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + // ALPN selection callback + SSL_CTX_set_alpn_select_cb(context->ssl_ctx, alpn_select_proto_cb, NULL); + lwsl_notice(" HTTP2 / ALPN enabled\n"); +#else + lwsl_notice(" HTTP2 / ALPN configured but not supported by OpenSSL version\n"); +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L +} + +#endif \ No newline at end of file diff --git a/lib/ssl.c b/lib/ssl.c index 8033c164..480256fd 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -55,6 +55,36 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, int error; int n; +#ifndef LWS_NO_SERVER + if (info->port != CONTEXT_PORT_NO_LISTEN) { + + context->use_ssl = info->ssl_cert_filepath != NULL && + info->ssl_private_key_filepath != NULL; +#ifdef USE_CYASSL + lwsl_notice(" Compiled with CYASSL support\n"); +#else + lwsl_notice(" Compiled with OpenSSL support\n"); +#endif + + if (info->ssl_cipher_list) + lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list); + + if (context->use_ssl) + lwsl_notice(" Using SSL mode\n"); + else + lwsl_notice(" Using non-SSL mode\n"); + } + +#else + if (info->ssl_cert_filepath != NULL && + info->ssl_private_key_filepath != NULL) { + lwsl_notice(" Not compiled for OpenSSl support!\n"); + return 1; + } + lwsl_notice(" Compiled without SSL support\n"); + } +#endif /* no server */ + /* basic openssl init */ SSL_library_init(); @@ -155,7 +185,12 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, return 1; } - /* SSL is happy and has a cert it's content with */ + /* + * SSL is happy and has a cert it's content with + * If we're supporting HTTP2, initialize that + */ + + lws_context_init_http2_ssl(context); } return 0;