http2 add initial alpn support
authorAndy Green <andy.green@linaro.org>
Thu, 3 Apr 2014 06:33:48 +0000 (14:33 +0800)
committerAndy Green <andy.green@linaro.org>
Thu, 3 Apr 2014 06:33:48 +0000 (14:33 +0800)
Signed-off-by: Andy Green <andy.green@linaro.org>
CMakeLists.txt
config.h.cmake
lib/context.c
lib/private-libwebsockets.h
lib/ssl-http2.c [new file with mode: 0644]
lib/ssl.c

index 78cb7db..fcd678d 100644 (file)
@@ -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()
index ddd8ec6..bc16e23 100644 (file)
@@ -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
 
index 0f4e1c4..3580d4a 100644 (file)
@@ -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;
        
index da035a1..1443de0 100644 (file)
@@ -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 (file)
index 0000000..237f43c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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
index 8033c16..480256f 100644 (file)
--- 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;