lws-vhost-destroy
[platform/upstream/libwebsockets.git] / test-server / test-server-v2.0.c
index b6feafe..9623df2 100644 (file)
  */
 
 #include <libwebsockets.h>
+#include <string.h>
 #include <getopt.h>
 #ifndef WIN32
 #include <syslog.h>
 #endif
 
+/* windows has no SIGUSR1 */
+#if !defined(WIN32) && !defined(_WIN32)
+#define TEST_DYNAMIC_VHOST
+#endif
+
+struct lws_context_creation_info info;
 int debug_level = 7;
 struct lws_context *context;
 
+#if defined(TEST_DYNAMIC_VHOST)
+volatile int dynamic_vhost_enable = 0;
+struct lws_vhost *dynamic_vhost;
+uv_timer_t timeout_watcher;
+#endif
+
 /* http server gets files from this path */
 #define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"
 char *resource_path = LOCAL_RESOURCE_PATH;
-#if defined(LWS_USE_POLARSSL)
-#else
-#if defined(LWS_USE_MBEDTLS)
-#else
+
 #if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
 char crl_path[1024] = "";
 #endif
-#endif
-#endif
 
 /*
  * This test server is ONLY this .c file, it's radically simpler than the
@@ -52,6 +60,44 @@ char crl_path[1024] = "";
  * You can find the individual protocol plugin sources in ../plugins
  */
 
+#if defined(TEST_DYNAMIC_VHOST)
+
+/*
+ *  to test dynamic vhost creation, fire a SIGUSR1 at the test server.
+ * It will toggle the existence of a second identical vhost at port + 1
+ *
+ * To synchronize with the event loop, it uses a libuv timer with 0 delay
+ * to get the business end called as the next event.
+ */
+
+static void
+uv_timeout_dynamic_vhost_toggle(uv_timer_t *w
+#if UV_VERSION_MAJOR == 0
+               , int status
+#endif
+)
+{
+       if (dynamic_vhost_enable && !dynamic_vhost) {
+               lwsl_notice("creating dynamic vhost...\n");
+               dynamic_vhost = lws_create_vhost(context, &info);
+       } else
+               if (!dynamic_vhost_enable && dynamic_vhost) {
+                       lwsl_notice("destroying dynamic vhost...\n");
+                       lws_vhost_destroy(dynamic_vhost);
+                       dynamic_vhost = NULL;
+               }
+}
+
+void sighandler_USR1(int sig)
+{
+       dynamic_vhost_enable ^= 1;
+       lwsl_notice("SIGUSR1: dynamic_vhost_enable: %d\n",
+                       dynamic_vhost_enable);
+       uv_timer_start(&timeout_watcher,
+                      uv_timeout_dynamic_vhost_toggle, 0, 0);
+}
+#endif
+
 void sighandler(int sig)
 {
        lws_cancel_service(context);
@@ -72,16 +118,41 @@ static const struct lws_extension exts[] = {
 };
 
 /*
- * mount a handler for a section of the URL space
+ * mount handlers for sections of the URL space
  */
 
+static const struct lws_http_mount mount_ziptest = {
+       NULL,                   /* linked-list pointer to next*/
+       "/ziptest",             /* mountpoint in URL namespace on this vhost */
+       LOCAL_RESOURCE_PATH"/candide.zip",      /* handler */
+       NULL,   /* default filename if none given */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       LWSMPRO_FILE,   /* origin points to a callback */
+       8,                      /* strlen("/ziptest"), ie length of the mountpoint */
+       NULL,
+
+       { NULL, NULL } // sentinel
+};
+
 static const struct lws_http_mount mount_post = {
-       NULL,           /* linked-list pointer to next*/
+       (struct lws_http_mount *)&mount_ziptest, /* linked-list pointer to next*/
        "/formtest",            /* mountpoint in URL namespace on this vhost */
        "protocol-post-demo",   /* handler */
        NULL,   /* default filename if none given */
        NULL,
        NULL,
+       NULL,
+       NULL,
+       0,
        0,
        0,
        0,
@@ -89,6 +160,9 @@ static const struct lws_http_mount mount_post = {
        0,
        LWSMPRO_CALLBACK,       /* origin points to a callback */
        9,                      /* strlen("/formtest"), ie length of the mountpoint */
+       NULL,
+
+       { NULL, NULL } // sentinel
 };
 
 /*
@@ -98,12 +172,15 @@ static const struct lws_http_mount mount_post = {
  */
 
 static const struct lws_http_mount mount = {
-       (struct lws_http_mount *)&mount_post,           /* linked-list pointer to next*/
+       (struct lws_http_mount *)&mount_post,   /* linked-list pointer to next*/
        "/",            /* mountpoint in URL namespace on this vhost */
        LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */
        "test.html",    /* default filename if none given */
        NULL,
        NULL,
+       NULL,
+       NULL,
+       0,
        0,
        0,
        0,
@@ -111,6 +188,9 @@ static const struct lws_http_mount mount = {
        0,
        LWSMPRO_FILE,   /* mount type is a directory in a filesystem */
        1,              /* strlen("/"), ie length of the mountpoint */
+       NULL,
+
+       { NULL, NULL } // sentinel
 };
 
 /*
@@ -118,21 +198,43 @@ static const struct lws_http_mount mount = {
  * the effect is to set this protocol to be the default one for the vhost,
  * ie, selected if no Protocol: header is sent with the ws upgrade.
  */
-
+#if 0
 static const struct lws_protocol_vhost_options pvo_opt = {
        NULL,
        NULL,
        "default",
        "1"
 };
+#endif
+
+static const struct lws_protocol_vhost_options pvo_opt4a = {
+       NULL,
+       NULL,
+       "raw", /* indicate we are the protocol that gets raw connections */
+       "1"
+};
+
+static const struct lws_protocol_vhost_options pvo_opt4 = {
+       &pvo_opt4a,
+       NULL,
+       "fifo-path", /* tell the raw test plugin to open a raw file here */
+       "/tmp/lws-test-raw"
+};
 
 /*
  * We must enable the plugin protocols we want into our vhost with a
  * linked-list.  We can also give the plugin per-vhost options here.
  */
 
-static const struct lws_protocol_vhost_options pvo_3 = {
+static const struct lws_protocol_vhost_options pvo_4 = {
        NULL,
+       &pvo_opt4, /* set us as the protocol who gets raw connections */
+       "protocol-lws-raw-test",
+       "" /* ignored, just matches the protocol name above */
+};
+
+static const struct lws_protocol_vhost_options pvo_3 = {
+       &pvo_4,
        NULL,
        "protocol-post-demo",
        "" /* ignored, just matches the protocol name above */
@@ -154,7 +256,7 @@ static const struct lws_protocol_vhost_options pvo_1 = {
 
 static const struct lws_protocol_vhost_options pvo = {
        &pvo_1,
-       &pvo_opt,
+       NULL, // &pvo_opt,
        "dumb-increment-protocol",
        ""
 };
@@ -179,6 +281,7 @@ static const struct option options[] = {
        { "debug",      required_argument,      NULL, 'd' },
        { "port",       required_argument,      NULL, 'p' },
        { "ssl",        no_argument,            NULL, 's' },
+       { "ssl-alerts", no_argument,            NULL, 'S' },
        { "allow-non-ssl",      no_argument,    NULL, 'a' },
        { "interface",  required_argument,      NULL, 'i' },
        { "ssl-cert",  required_argument,       NULL, 'C' },
@@ -204,7 +307,7 @@ static const char * const plugin_dirs[] = {
 
 int main(int argc, char **argv)
 {
-       struct lws_context_creation_info info;
+       struct lws_vhost *vhost;
        char interface_name[128] = "";
        const char *iface = NULL;
        char cert_path[1024] = "";
@@ -229,7 +332,7 @@ int main(int argc, char **argv)
        info.port = 7681;
 
        while (n >= 0) {
-               n = getopt_long(argc, argv, "i:hsap:d:Dr:C:K:A:R:vu:g:",
+               n = getopt_long(argc, argv, "i:hsap:d:Dr:C:K:A:R:vu:g:S",
                                (struct option *)options, NULL);
                if (n < 0)
                        continue;
@@ -254,6 +357,11 @@ int main(int argc, char **argv)
                case 's':
                        use_ssl = 1;
                        break;
+               case 'S':
+#if defined(LWS_OPENSSL_SUPPORT)
+                       info.ssl_info_event_mask |= SSL_CB_ALERT;
+#endif
+                       break;
                case 'a':
                        opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
                        break;
@@ -286,10 +394,7 @@ int main(int argc, char **argv)
                        use_ssl = 1;
                        opts |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
                        break;
-#if defined(LWS_USE_POLARSSL)
-#else
-#if defined(LWS_USE_MBEDTLS)
-#else
+
 #if defined(LWS_HAVE_SSL_CTX_set1_param)
                case 'R':
                        strncpy(crl_path, optarg, sizeof(crl_path) - 1);
@@ -297,8 +402,6 @@ int main(int argc, char **argv)
                        break;
 #endif
 #endif
-#endif
-#endif
                case 'h':
                        fprintf(stderr, "Usage: test-server "
                                        "[--port=<p>] [--ssl] "
@@ -321,6 +424,9 @@ int main(int argc, char **argv)
 #endif
 
        signal(SIGINT, sighandler);
+#if defined(TEST_DYNAMIC_VHOST)
+       signal(SIGUSR1, sighandler_USR1);
+#endif
 
 #ifndef _WIN32
        /* we will only try to log things according to our debug_level */
@@ -332,7 +438,7 @@ int main(int argc, char **argv)
        lws_set_log_level(debug_level, lwsl_emit_syslog);
 
        lwsl_notice("libwebsockets test server - license LGPL2.1+SLE\n");
-       lwsl_notice("(C) Copyright 2010-2016 Andy Green <andy@warmcat.com>\n");
+       lwsl_notice("(C) Copyright 2010-2017 Andy Green <andy@warmcat.com>\n");
 
        lwsl_notice(" Using resource path \"%s\"\n", resource_path);
 
@@ -343,7 +449,8 @@ int main(int argc, char **argv)
        info.gid = gid;
        info.uid = uid;
        info.max_http_header_pool = 16;
-       info.options = opts |
+       info.options = opts | LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
+                       LWS_SERVER_OPTION_FALLBACK_TO_RAW |
                        LWS_SERVER_OPTION_VALIDATE_UTF8 |
                        LWS_SERVER_OPTION_LIBUV; /* plugins require this */
 
@@ -394,17 +501,16 @@ int main(int argc, char **argv)
        /* tell lws about our mount we want */
        info.mounts = &mount;
        /*
-        *  give it our linked-list of Per-Vhost Options, these control
+        * give it our linked-list of Per-Vhost Options, these control
         * which protocols (from plugins) are allowed to be enabled on
         * our vhost
         */
        info.pvo = &pvo;
 
        /*
-        * As it is, this creates the context and a single Vhost at the same
-        * time.  You can use LWS_SERVER_OPTION_EXPLICIT_VHOSTS option above
-        * to just create the context, and call lws_create_vhost() afterwards
-        * multiple times with different info to get multiple listening vhosts.
+        * Since we used LWS_SERVER_OPTION_EXPLICIT_VHOSTS, this only creates
+        * the context.  We can modify info and create as many vhosts as we
+        * like subsequently.
         */
        context = lws_create_context(&info);
        if (context == NULL) {
@@ -412,15 +518,42 @@ int main(int argc, char **argv)
                return -1;
        }
 
+       /*
+        *  normally we would adapt at least info.name to reflect the
+        * external hostname for this server.
+        */
+       vhost = lws_create_vhost(context, &info);
+       if (!vhost) {
+               lwsl_err("vhost creation failed\n");
+               return -1;
+       }
+
+#if defined(TEST_DYNAMIC_VHOST)
+       /* our dynamic vhost is on port + 1 */
+       info.port++;
+#endif
+
        /* libuv event loop */
        lws_uv_sigint_cfg(context, 1, signal_cb);
-       if (lws_uv_initloop(context, NULL, 0))
+       if (lws_uv_initloop(context, NULL, 0)) {
                lwsl_err("lws_uv_initloop failed\n");
-       else
-               lws_libuv_run(context, 0);
+               goto bail;
+       }
+
+#if defined(TEST_DYNAMIC_VHOST)
+       uv_timer_init(lws_uv_getloop(context, 0), &timeout_watcher);
+#endif
+       lws_libuv_run(context, 0);
+
+#if defined(TEST_DYNAMIC_VHOST)
+       uv_timer_stop(&timeout_watcher);
+       uv_close((uv_handle_t *)&timeout_watcher, NULL);
+#endif
 
+bail:
        /* when we decided to exit the event loop */
        lws_context_destroy(context);
+       lws_context_destroy2(context);
        lwsl_notice("libwebsockets-test-server exited cleanly\n");
 
 #ifndef _WIN32