HTTP_PROXY: make usable
authorAndy Green <andy@warmcat.com>
Mon, 12 Jun 2017 05:36:24 +0000 (13:36 +0800)
committerAndy Green <andy@warmcat.com>
Wed, 14 Jun 2017 01:53:09 +0000 (09:53 +0800)
CMakeLists.txt
README.lwsws.md
lib/client-handshake.c
lib/context.c
lib/libwebsockets.h
lib/parsers.c
lib/server.c
lib/service.c
lib/ssl-client.c
test-server/test-server-http.c
test-server/test-server.c

index 6d3bdee..a79fdf9 100644 (file)
@@ -98,7 +98,7 @@ option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF)
 option(LWS_WITH_HTTP2 "Compile with support for http2" OFF)
 option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF)
 option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF)
-option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying" OFF)
+option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying (requires libhubbub)" OFF)
 option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF)
 option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
 option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF)
@@ -392,7 +392,7 @@ if (LWS_WITH_HTTP2)
 endif()
 
 if ("${LWS_MAX_SMP}" STREQUAL "")
-       set(LWS_MAX_SMP 32)
+       set(LWS_MAX_SMP 1)
 endif()
 
 
@@ -735,7 +735,7 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID
 endif ()
 
 if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS)
-    if (UNIX)
+       if (UNIX AND LWS_MAX_SMP GREATER 1)
        # jeez clang understands -pthread but dies if he sees it at link time!
        # http://stackoverflow.com/questions/2391194/what-is-gs-pthread-equiv-in-clang
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread" )
@@ -1251,7 +1251,7 @@ if (NOT LWS_WITHOUT_TESTAPPS)
                                        ""
                                        "")
                        endif()
-                       if (UNIX AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")))
+                       if (UNIX AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND LWS_MAX_SMP GREATER 1)
                                create_test_app(test-server-pthreads
                                        "test-server/test-server-pthreads.c"
                                        "test-server/test-server-http.c"
index 12ad81e..04ba81a 100644 (file)
@@ -292,6 +292,20 @@ Mount protocols are used to control what kind of translation happens
 ```
  would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client.
 
+ - http:// or https://  these perform reverse proxying, serving the remote origin content from the mountpoint.  Eg
+
+```
+               {
+                "mountpoint": "/proxytest",
+                "origin": "https://libwebsockets.org"
+               }
+```
+
+This will cause your local url `/proxytest` to serve content fetched from libwebsockets.org over ssl; whether it's served from your server using ssl is unrelated and depends how you configured your local server.  Notice if you will use the proxying feature, `LWS_WITH_HTTP_PROXY` is required to be enabled at cmake, and for `https` proxy origins, your lwsws configuration must include `"init-ssl": "1"` and the vhost with the proxy mount must have `"enable-client-ssl": "1"`, even if you are not using ssl to serve.
+
+`/proxytest/abc`, or `/proxytest/abc?def=ghi` etc map to the origin + the part past `/proxytest`, so links and img src urls etc work as do all urls under the origin path.
+
+In addition link and src urls in the document are rewritten so / or the origin url part are rewritten to the mountpoint part.
 
 
 @section lwswsomo Lwsws Other mount options
index dc6de91..26543b9 100644 (file)
@@ -262,7 +262,8 @@ lws_client_connect_2(struct lws *wsi)
                n = sizeof(struct sockaddr);
        }
 
-       if (connect(wsi->desc.sockfd, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
+       if (connect(wsi->desc.sockfd, v, n) == -1 ||
+           LWS_ERRNO == LWS_EISCONN) {
                if (LWS_ERRNO == LWS_EALREADY ||
                    LWS_ERRNO == LWS_EINPROGRESS ||
                    LWS_ERRNO == LWS_EWOULDBLOCK
@@ -527,14 +528,14 @@ html_parser_cb(const hubbub_token *token, void *pw)
                                                "(force-quirks) " : "");
 
                if (token->data.doctype.public_missing)
-                       printf("\tpublic: missing\n");
+                       lwsl_debug("\tpublic: missing\n");
                else
                        p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
                                (int) token->data.doctype.public_id.len,
                                token->data.doctype.public_id.ptr);
 
                if (token->data.doctype.system_missing)
-                       printf("\tsystem: missing\n");
+                       lwsl_debug("\tsystem: missing\n");
                else
                        p += lws_snprintf(p, end - p, " \"%.*s\">\n",
                                (int) token->data.doctype.system_id.len,
@@ -557,25 +558,28 @@ html_parser_cb(const hubbub_token *token, void *pw)
                                const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
                                int plen = (int) token->data.tag.attributes[i].value.len;
 
-                               if (!hstrcmp(&token->data.tag.attributes[i].value,
-                                            r->from, r->from_len)) {
-                                       pp += r->from_len;
-                                       plen -= r->from_len;
+                               if (strncmp(pp, "http:", 5) && strncmp(pp, "https:", 6)) {
+
+                                       if (!hstrcmp(&token->data.tag.attributes[i].value,
+                                                    r->from, r->from_len)) {
+                                               pp += r->from_len;
+                                               plen -= r->from_len;
+                                       }
+                                       p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
+                                              (int) token->data.tag.attributes[i].name.len,
+                                              token->data.tag.attributes[i].name.ptr,
+                                              r->to, plen, pp);
+                                       continue;
                                }
-                               p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
-                                      (int) token->data.tag.attributes[i].name.len,
-                                      token->data.tag.attributes[i].name.ptr,
-                                      r->to, plen, pp);
-
-                       } else
-
-                               p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
-                                       (int) token->data.tag.attributes[i].name.len,
-                                       token->data.tag.attributes[i].name.ptr,
-                                       (int) token->data.tag.attributes[i].value.len,
-                                       token->data.tag.attributes[i].value.ptr);
+                       }
+
+                       p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
+                               (int) token->data.tag.attributes[i].name.len,
+                               token->data.tag.attributes[i].name.ptr,
+                               (int) token->data.tag.attributes[i].value.len,
+                               token->data.tag.attributes[i].value.ptr);
                }
-               p += lws_snprintf(p, end - p, ">\n");
+               p += lws_snprintf(p, end - p, ">");
                break;
        case HUBBUB_TOKEN_END_TAG:
                p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
@@ -593,7 +597,7 @@ html_parser_cb(const hubbub_token *token, void *pw)
                                (int) token->data.tag.attributes[i].value.len,
                                token->data.tag.attributes[i].value.ptr);
                }
-               p += lws_snprintf(p, end - p, ">\n");
+               p += lws_snprintf(p, end - p, ">");
                break;
        case HUBBUB_TOKEN_COMMENT:
                p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
@@ -601,6 +605,21 @@ html_parser_cb(const hubbub_token *token, void *pw)
                                token->data.comment.ptr);
                break;
        case HUBBUB_TOKEN_CHARACTER:
+               if (token->data.character.len == 1) {
+                       if (*token->data.character.ptr == '<') {
+                               p += lws_snprintf(p, end - p, "&lt;");
+                               break;
+                       }
+                       if (*token->data.character.ptr == '>') {
+                               p += lws_snprintf(p, end - p, "&gt;");
+                               break;
+                       }
+                       if (*token->data.character.ptr == '&') {
+                               p += lws_snprintf(p, end - p, "&amp;");
+                               break;
+                       }
+               }
+
                p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
                                token->data.character.ptr);
                break;
index f71f01d..fab3dc2 100644 (file)
@@ -222,10 +222,13 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
 {
 #ifdef LWS_WITH_CGI
        struct lws_cgi_args *args;
-       char buf[128];
+#endif
+#if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
+       char buf[512];
        int n;
 #endif
 
+
        switch (reason) {
        case LWS_CALLBACK_HTTP:
 #ifndef LWS_NO_SERVER
@@ -250,9 +253,92 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
                        break;
                }
 #endif
+#if defined(LWS_WITH_HTTP_PROXY)
+               if (wsi->reason_bf & 2) {
+                       char *px = buf + LWS_PRE;
+                       int lenx = sizeof(buf) - LWS_PRE;
+                       /*
+                        * our sink is writeable and our source has something
+                        * to read.  So read a lump of source material of
+                        * suitable size to send or what's available, whichever
+                        * is the smaller.
+                        */
 
+
+                       wsi->reason_bf &= ~2;
+                       if (!lws_get_child(wsi))
+                               break;
+                       if (lws_http_client_read(lws_get_child(wsi), &px, &lenx) < 0)
+                               return -1;
+                       break;
+               }
+#endif
+               break;
+
+#if defined(LWS_WITH_HTTP_PROXY)
+       case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
+               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p\n", wsi);
+               assert(lws_get_parent(wsi));
+               if (!lws_get_parent(wsi))
+                       break;
+               lws_get_parent(wsi)->reason_bf |= 2;
+               lws_callback_on_writable(lws_get_parent(wsi));
                break;
 
+       case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
+               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", (int)len);
+               assert(lws_get_parent(wsi));
+               n = lws_write(lws_get_parent(wsi), (unsigned char *)in,
+                               len, LWS_WRITE_HTTP);
+               if (n < 0)
+                       return -1;
+               break;
+
+       case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: {
+               unsigned char *p, *end;
+               char ctype[64], ctlen = 0;
+
+               //lwsl_err("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\n");
+       
+               p = (unsigned char *)buf + LWS_PRE;
+               end = p + sizeof(buf) - LWS_PRE;
+
+               if (lws_add_http_header_status(lws_get_parent(wsi), HTTP_STATUS_OK, &p, end))
+                       return 1;
+               if (lws_add_http_header_by_token(lws_get_parent(wsi),
+                               WSI_TOKEN_HTTP_SERVER,
+                               (unsigned char *)"libwebsockets",
+                               13, &p, end))
+                       return 1;
+
+               ctlen = lws_hdr_copy(wsi, ctype, sizeof(ctype), WSI_TOKEN_HTTP_CONTENT_TYPE);
+               if (ctlen > 0) {
+                       if (lws_add_http_header_by_token(lws_get_parent(wsi),
+                               WSI_TOKEN_HTTP_CONTENT_TYPE,
+                               (unsigned char *)ctype, ctlen, &p, end))
+                               return 1;
+               }
+#if 0
+               if (lws_add_http_header_content_length(lws_get_parent(wsi),
+                                                      file_len, &p, end))
+                       return 1;
+#endif
+               if (lws_finalize_http_header(lws_get_parent(wsi), &p, end))
+                       return 1;
+
+               *p = '\0';
+//             lwsl_info("%s\n", buf + LWS_PRE);
+
+               n = lws_write(lws_get_parent(wsi), (unsigned char *)buf + LWS_PRE,
+                             p - ((unsigned char *)buf + LWS_PRE),
+                             LWS_WRITE_HTTP_HEADERS);
+               if (n < 0)
+                       return -1;
+
+               break; }
+
+#endif
+
 #ifdef LWS_WITH_CGI
        /* CGI IO events (POLLIN/OUT) appear here, our default policy is:
         *
index 2db2fc6..23d6588 100644 (file)
@@ -2289,8 +2289,8 @@ struct lws_protocol_vhost_options {
  * served from a filesystem, or it is a cgi etc.
  */
 enum lws_mount_protocols {
-       LWSMPRO_HTTP            = 0, /**< not supported yet */
-       LWSMPRO_HTTPS           = 1, /**< not supported yet */
+       LWSMPRO_HTTP            = 0, /**< http reverse proxy */
+       LWSMPRO_HTTPS           = 1, /**< https reverse proxy */
        LWSMPRO_FILE            = 2, /**< serve from filesystem directory */
        LWSMPRO_CGI             = 3, /**< pass to CGI to handle */
        LWSMPRO_REDIR_HTTP      = 4, /**< redirect to http:// url */
index 1140b4d..9cd70e0 100644 (file)
@@ -321,15 +321,18 @@ int lws_header_table_detach(struct lws *wsi, int autoservice)
        pt->ah_wait_list_length--;
 
 #ifndef LWS_NO_CLIENT
-       if (wsi->state == LWSS_CLIENT_UNCONNECTED)
+       if (wsi->state == LWSS_CLIENT_UNCONNECTED) {
+               lws_pt_unlock(pt);
+
                if (!lws_client_connect_via_info2(wsi)) {
                        /* our client connect has failed, the wsi
                         * has been closed
                         */
-                       lws_pt_unlock(pt);
 
                        return -1;
                }
+               return 0;
+       }
 #endif
 
        assert(!!pt->ah_wait_list_length == !!(int)(long)pt->ah_wait_list);
index 54e974a..2693cc0 100644 (file)
@@ -662,6 +662,23 @@ lws_unauthorised_basic_auth(struct lws *wsi)
 
 #endif
 
+int lws_clean_url(char *p)
+{
+       while (*p) {
+               if (p[0] == '/' && p[1] == '/') {
+                       char *p1 = p;
+                       while (*p1) {
+                               *p1 = p1[1];
+                               p1++;
+                       }
+                       continue;
+               }
+               p++;
+       }
+
+       return 0;
+}
+
 int
 lws_http_action(struct lws *wsi)
 {
@@ -958,6 +975,7 @@ lws_http_action(struct lws *wsi)
                            "%s%s%s/", oprot[lws_is_ssl(wsi)],
                            lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
                            uri_ptr);
+               lws_clean_url((char *)end);
 
                n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
                                      end, n, &p, end);
@@ -1013,6 +1031,84 @@ lws_http_action(struct lws *wsi)
        }
 #endif
 
+#if defined(LWS_WITH_HTTP_PROXY)
+       /*
+        * The mount is a reverse proxy?
+        */
+
+       if (hit->origin_protocol == LWSMPRO_HTTPS ||
+           hit->origin_protocol == LWSMPRO_HTTP)  {
+               struct lws_client_connect_info i;
+               char ads[96], rpath[256], *pcolon, *pslash, *p;
+               int n, na;
+
+               memset(&i, 0, sizeof(i));
+               i.context = lws_get_context(wsi);
+
+               pcolon = strchr(hit->origin, ':');
+               pslash = strchr(hit->origin, '/');
+               if (!pslash) {
+                       lwsl_err("Proxy mount origin '%s' must have /\n", hit->origin);
+                       return -1;
+               }
+               if (pcolon > pslash)
+                       pcolon = NULL;
+               
+               if (pcolon)
+                       n = pcolon - hit->origin;
+               else
+                       n = pslash - hit->origin;
+
+               if (n >= sizeof(ads) - 2)
+                       n = sizeof(ads) - 2;
+
+               memcpy(ads, hit->origin, n);
+               ads[n] = '\0';
+
+               i.address = ads;
+               i.port = 80;
+               if (hit->origin_protocol == LWSMPRO_HTTPS) { 
+                       i.port = 443;
+                       i.ssl_connection = 1;
+               }
+               if (pcolon)
+                       i.port = atoi(pcolon + 1);
+               
+               lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", pslash + 1, uri_ptr + hit->mountpoint_len);
+               lws_clean_url(rpath);
+               na = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_URI_ARGS);
+               if (na) {
+                       p = rpath + strlen(rpath);
+                       *p++ = '?';
+                       lws_hdr_copy(wsi, p, &rpath[sizeof(rpath) - 1] - p, WSI_TOKEN_HTTP_URI_ARGS);
+                       while (--na) {
+                               if (*p == '\0')
+                                       *p = '&';
+                               p++;
+                       }
+               }
+                               
+
+               i.path = rpath;
+               i.host = i.address;
+               i.origin = NULL;
+               i.method = "GET";
+               i.parent_wsi = wsi;
+               i.uri_replace_from = hit->origin;
+               i.uri_replace_to = hit->mountpoint;
+
+               lwsl_notice("proxying to %s port %d url %s, ssl %d, from %s, to %s\n",
+                               i.address, i.port, i.path, i.ssl_connection, i.uri_replace_from, i.uri_replace_to);
+       
+               if (!lws_client_connect_via_info(&i)) {
+                       lwsl_err("proxy connect fail\n");
+                       return 1;
+               }
+
+               return 0;
+       }
+#endif
+
        /*
         * A particular protocol callback is mounted here?
         *
index 6f08dee..6d7e538 100644 (file)
@@ -1203,6 +1203,9 @@ drain:
                                lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP closed it\n");
                                goto close_and_handled;
                        }
+
+                       n = 0;
+                       goto handled;
                }
 #endif
                /*
index 45c9fb7..aba337b 100644 (file)
@@ -318,7 +318,7 @@ lws_ssl_client_connect2(struct lws *wsi)
        if (wsi->mode == LWSCM_WSCL_WAITING_SSL) {
                lws_latency_pre(context, wsi);
                n = SSL_connect(wsi->ssl);
-               lwsl_notice("%s: SSL_connect says %d\n", __func__, n);
+               lwsl_debug("%s: SSL_connect says %d\n", __func__, n);
 
                lws_latency(context, wsi,
                            "SSL_connect LWSCM_WSCL_WAITING_SSL", n, n > 0);
@@ -395,7 +395,7 @@ lws_ssl_client_connect2(struct lws *wsi)
        lws_latency(context, wsi,
                "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0);
 
-       lwsl_notice("get_verify says %d\n", n);
+       lwsl_debug("get_verify says %d\n", n);
 
        if (n != X509_V_OK) {
                if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
index eeda0f0..ea852c2 100644 (file)
@@ -230,38 +230,37 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                        goto try_to_reuse;
                }
 
-#ifndef LWS_NO_CLIENT
+#if !defined(LWS_NO_CLIENT) && defined(LWS_OPENSSL_SUPPORT)
                if (!strncmp(in, "/proxytest", 10)) {
                        struct lws_client_connect_info i;
-                       char *rootpath = "/";
+                       char *rootpath = "/git/";
                        const char *p = (const char *)in;
 
                        if (lws_get_child(wsi))
                                break;
 
                        pss->client_finished = 0;
-                       memset(&i,0, sizeof(i));
+                       memset(&i, 0, sizeof(i));
                        i.context = lws_get_context(wsi);
-                       i.address = "git.libwebsockets.org";
-                       i.port = 80;
-                       i.ssl_connection = 0;
+                       i.address = "libwebsockets.org";
+                       i.port = 443;
+                       i.ssl_connection = 1;
                        if (p[10])
                                i.path = (char *)in + 10;
                        else
                                i.path = rootpath;
-                       i.host = "git.libwebsockets.org";
+                       i.host = i.address;
                        i.origin = NULL;
                        i.method = "GET";
                        i.parent_wsi = wsi;
-                       i.uri_replace_from = "git.libwebsockets.org/";
+                       i.uri_replace_from = "libwebsockets.org/git/";
                        i.uri_replace_to = "/proxytest/";
+
                        if (!lws_client_connect_via_info(&i)) {
                                lwsl_err("proxy connect fail\n");
                                break;
                        }
 
-
-
                        break;
                }
 #endif
@@ -421,6 +420,11 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                 */
                break;
 
+        case LWS_CALLBACK_CLIENT_RECEIVE:
+                ((char *)in)[len] = '\0';
+                lwsl_info("rx %d '%s'\n", (int)len, (char *)in);
+                break;
+
        case LWS_CALLBACK_HTTP_BODY:
                /* create the POST argument parser if not already existing */
                if (!pss->spa) {
@@ -511,8 +515,10 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                if (pss->client_finished)
                        return -1;
 
-               if (!pss->fop_fd)
+               if (!lws_get_child(wsi) && !pss->fop_fd) {
+                       lwsl_notice("fop_fd NULL\n");
                        goto try_to_reuse;
+               }
 
 #ifndef LWS_NO_CLIENT
                if (pss->reason_bf & 2) {
@@ -524,17 +530,24 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
                         * suitable size to send or what's available, whichever
                         * is the smaller.
                         */
+
+
                        pss->reason_bf &= ~2;
                        wsi1 = lws_get_child(wsi);
                        if (!wsi1)
                                break;
                        if (lws_http_client_read(wsi1, &px, &lenx) < 0)
-                               goto bail;
+                               return -1;
 
                        if (pss->client_finished)
                                return -1;
+
                        break;
                }
+
+               if (lws_get_child(wsi))
+                       break;
+
 #endif
                /*
                 * we can send more of whatever it is we were sending
@@ -657,16 +670,12 @@ bail:
                assert(lws_get_parent(wsi));
                if (!lws_get_parent(wsi))
                        break;
-               // lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p: sock: %d, parent_wsi: %p, parent_sock:%d,  len %d\n",
-               //              wsi, lws_get_socket_fd(wsi),
-               //              lws_get_parent(wsi),
-               //              lws_get_socket_fd(lws_get_parent(wsi)), len);
                pss1 = lws_wsi_user(lws_get_parent(wsi));
                pss1->reason_bf |= 2;
                lws_callback_on_writable(lws_get_parent(wsi));
                break;
        case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
-               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", len);
+               //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", (int)len);
                assert(lws_get_parent(wsi));
                m = lws_write(lws_get_parent(wsi), (unsigned char *)in,
                                len, LWS_WRITE_HTTP);
index d6ddb9d..7c1f9ea 100644 (file)
@@ -191,6 +191,7 @@ static struct option options[] = {
 int main(int argc, char **argv)
 {
        struct lws_context_creation_info info;
+       struct lws_vhost *vhost;
        char interface_name[128] = "";
        unsigned int ms, oldms = 0;
        const char *iface = NULL;
@@ -382,7 +383,7 @@ int main(int argc, char **argv)
        info.gid = gid;
        info.uid = uid;
        info.max_http_header_pool = 16;
-       info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8;
+       info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
        info.extensions = exts;
        info.timeout_secs = 5;
        info.ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
@@ -409,6 +410,16 @@ int main(int argc, char **argv)
                return -1;
        }
 
+       vhost = lws_create_vhost(context, &info);
+       if (!vhost) {
+               lwsl_err("vhost creation failed\n");
+               return -1;
+       }
+
+#if !defined(LWS_NO_CLIENT) && defined(LWS_OPENSSL_SUPPORT)
+       lws_init_vhost_client_ssl(&info, vhost);
+#endif
+
        /* this shows how to override the lws file operations.  You don't need
         * to do any of this unless you have a reason (eg, want to serve
         * compressed files without decompressing the whole archive)