lib/server.c: fix ipv6 support
[platform/upstream/libwebsockets.git] / lib / context.c
index c35cb13..23d218d 100644 (file)
@@ -49,46 +49,6 @@ static const char * const mount_protocols[] = {
        ">https://",
 };
 
-LWS_VISIBLE LWS_EXTERN int
-lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
-                    void *store, const char *mountpoint, const char *origin,
-                    const char *def)
-{
-       struct lws_http_mount *m;
-       void *orig = store;
-       unsigned long l = (unsigned long)store;
-       int n;
-
-       if (l & 15)
-               l += 16 - (l & 15);
-
-       store = (void *)l;
-       m = (struct lws_http_mount *)store;
-       *res = m;
-
-       m->def = def;
-       m->mountpoint = mountpoint;
-       m->mountpoint_len = (unsigned char)strlen(mountpoint);
-       m->mount_next = NULL;
-       if (next)
-               next->mount_next = m;
-
-       for (n = 0; n < ARRAY_SIZE(mount_protocols); n++)
-               if (!strncmp(origin, mount_protocols[n],
-                    strlen(mount_protocols[n]))) {
-                       m->origin_protocol = n;
-                       m->origin = origin + strlen(mount_protocols[n]);
-                       break;
-               }
-
-       if (n == ARRAY_SIZE(mount_protocols)) {
-               lwsl_err("unsupported protocol://\n");
-               return 0; /* ie, fail */
-       }
-
-       return ((char *)store + sizeof(*m)) - (char *)orig;
-}
-
 LWS_VISIBLE void *
 lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot,
                            int size)
@@ -132,10 +92,10 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *pr
        return vhost->protocol_vh_privs[n];
 }
 
-static struct lws_protocol_vhost_options *
+static const struct lws_protocol_vhost_options *
 lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
 {
-       struct lws_protocol_vhost_options *pvo = vh->pvo;
+       const struct lws_protocol_vhost_options *pvo = vh->pvo;
 
        while (pvo) {
                // lwsl_notice("%s: '%s' '%s'\n", __func__, pvo->name, name);
@@ -151,7 +111,7 @@ int
 lws_protocol_init(struct lws_context *context)
 {
        struct lws_vhost *vh = context->vhost_list;
-       struct lws_protocol_vhost_options *pvo;
+       const struct lws_protocol_vhost_options *pvo;
        struct lws wsi;
        int n;
 
@@ -183,7 +143,8 @@ lws_protocol_init(struct lws_context *context)
                         * protocol ptrs so lws_get_context(wsi) etc can work
                         */
                        vh->protocols[n].callback(&wsi,
-                               LWS_CALLBACK_PROTOCOL_INIT, NULL, pvo, 0);
+                               LWS_CALLBACK_PROTOCOL_INIT, NULL,
+                               (void *)pvo, 0);
                }
 
                vh = vh->vhost_next;
@@ -194,23 +155,50 @@ lws_protocol_init(struct lws_context *context)
        return 0;
 }
 
+static int callback_http_dummy(
+               struct lws *wsi, enum lws_callback_reasons reason, void *user,
+                 void *in, size_t len)
+{
+       return 0;
+}
+
+/* list of supported protocols and callbacks */
+
+static const struct lws_protocols protocols_dummy[] = {
+       /* first protocol must always be HTTP handler */
+
+       {
+               "http-only",            /* name */
+               callback_http_dummy,            /* callback */
+               0,      /* per_session_data_size */
+               0,                      /* max frame size / rx buffer */
+       },
+       /*
+        * the other protocols are provided by lws plugins
+        */
+       { NULL, NULL, 0, 0 } /* terminator */
+};
+
 LWS_VISIBLE struct lws_vhost *
 lws_create_vhost(struct lws_context *context,
-                struct lws_context_creation_info *info,
-                struct lws_http_mount *mounts)
+                struct lws_context_creation_info *info)
 {
        struct lws_vhost *vh = lws_zalloc(sizeof(*vh)),
                         **vh1 = &context->vhost_list;
+       const struct lws_http_mount *mounts;
 #ifdef LWS_WITH_PLUGINS
        struct lws_plugin *plugin = context->plugin_list;
        struct lws_protocols *lwsp;
-       int m, n;
+       int m, n, f = !info->pvo;
 #endif
        char *p;
 
        if (!vh)
                return NULL;
 
+       if (!info->protocols)
+               info->protocols = &protocols_dummy[0];
+
        vh->context = context;
        if (!info->vhost_name)
                vh->name = "default";
@@ -223,7 +211,9 @@ lws_create_vhost(struct lws_context *context,
             vh->count_protocols++)
                ;
 
+       vh->options = info->options;
        vh->pvo = info->pvo;
+       vh->keepalive_timeout = info->keepalive_timeout;
 
 #ifdef LWS_WITH_PLUGINS
        if (plugin) {
@@ -241,13 +231,21 @@ lws_create_vhost(struct lws_context *context,
                memcpy(lwsp, info->protocols,
                       sizeof(struct lws_protocols) * m);
 
+               /* for compatibility, all protocols enabled on vhost if only
+                * the default vhost exists.  Otherwise only vhosts who ask
+                * for a protocol get it enabled.
+                */
+
+               if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
+                       f = 0;
+
                while (plugin) {
                        for (n = 0; n < plugin->caps.count_protocols; n++) {
                                /*
                                 * for compatibility's sake, no pvo implies
                                 * allow all protocols
                                 */
-                               if (!info->pvo || lws_vhost_protocol_options(vh,
+                               if (f || lws_vhost_protocol_options(vh,
                                    plugin->caps.protocols[n].name)) {
                                        memcpy(&lwsp[m],
                                               &plugin->caps.protocols[n],
@@ -263,11 +261,21 @@ lws_create_vhost(struct lws_context *context,
 #endif
                vh->protocols = info->protocols;
 
-       vh->mount_list = mounts;
+       vh->same_vh_protocol_list = (struct lws **)
+                       lws_zalloc(sizeof(struct lws *) * vh->count_protocols);
+
+       vh->mount_list = info->mounts;
 
+#ifdef LWS_USE_UNIX_SOCK
+       if (LWS_UNIX_SOCK_ENABLED(context)) {
+               lwsl_notice("Creating Vhost '%s' path \"%s\", %d protocols\n",
+                               vh->name, info->iface, vh->count_protocols);
+       } else
+#endif
        lwsl_notice("Creating Vhost '%s' port %d, %d protocols\n",
                        vh->name, info->port, vh->count_protocols);
 
+       mounts = info->mounts;
        while (mounts) {
                lwsl_notice("   mounting %s%s to %s\n",
                                mount_protocols[mounts->origin_protocol],
@@ -295,8 +303,10 @@ lws_create_vhost(struct lws_context *context,
 
                memcpy((struct lws_extension *)vh->extensions, info->extensions,
                       sizeof(struct lws_extension) * m);
+               plugin = context->plugin_list;
                while (plugin) {
-                       memcpy((struct lws_extension *)&vh->extensions[m], plugin->caps.extensions,
+                       memcpy((struct lws_extension *)&vh->extensions[m],
+                               plugin->caps.extensions,
                               sizeof(struct lws_extension) *
                               plugin->caps.count_extensions);
                        m += plugin->caps.count_extensions;
@@ -330,6 +340,26 @@ lws_create_vhost(struct lws_context *context,
        vh->ka_interval = info->ka_interval;
        vh->ka_probes = info->ka_probes;
 
+       if (vh->options & LWS_SERVER_OPTION_STS)
+               lwsl_notice("   STS enabled\n");
+
+#ifdef LWS_WITH_ACCESS_LOG
+       if (info->log_filepath) {
+               vh->log_fd = open(info->log_filepath, O_CREAT | O_APPEND | O_RDWR, 0600);
+               if (vh->log_fd == LWS_INVALID_FILE) {
+                       lwsl_err("unable to open log filepath %s\n",
+                                info->log_filepath);
+                       goto bail;
+               }
+               if (context->uid != -1)
+                       if (chown(info->log_filepath, context->uid,
+                                 context->gid) == -1)
+                               lwsl_err("unable to chown log file %s\n",
+                                               info->log_filepath);
+       } else
+               vh->log_fd = LWS_INVALID_FILE;
+#endif
+
        if (lws_context_init_server_ssl(info, vh))
                goto bail;
 
@@ -397,7 +427,6 @@ lws_create_context(struct lws_context_creation_info *info)
        struct rlimit rt;
 #endif
 
-
        lwsl_notice("Initial logging level %d\n", log_level);
        lwsl_notice("Libwebsockets version: %s\n", library_version);
 #if LWS_POSIX
@@ -428,6 +457,8 @@ lws_create_context(struct lws_context_creation_info *info)
                lwsl_err("No memory for websocket context\n");
                return NULL;
        }
+
+       context->time_up = time(NULL);
 #ifndef LWS_NO_DAEMONIZE
        if (pid_daemon) {
                context->started_with_parent = pid_daemon;
@@ -565,6 +596,15 @@ lws_create_context(struct lws_context_creation_info *info)
        }
        lwsl_info(" mem: pollfd map:      %5u\n", n);
 
+       if (info->server_string) {
+               context->server_string = info->server_string;
+               context->server_string_len = (short)
+                               strlen(context->server_string);
+       } else {
+               context->server_string = "libwebsockets";
+               context->server_string_len = 13;
+       }
+
 #if LWS_MAX_SMP > 1
        /* each thread serves his own chunk of fds */
        for (n = 1; n < (int)info->count_threads; n++)
@@ -577,20 +617,20 @@ lws_create_context(struct lws_context_creation_info *info)
 
        lws_context_init_ssl_library(info);
 
+       context->user_space = info->user;
+
        /*
         * if he's not saying he'll make his own vhosts later then act
         * compatibly and make a default vhost using the data in the info
         */
        if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
-               if (!lws_create_vhost(context, info, NULL)) {
+               if (!lws_create_vhost(context, info)) {
                        lwsl_err("Failed to create default vhost\n");
                        return NULL;
                }
 
        lws_context_init_extensions(info, context);
 
-       context->user_space = info->user;
-
        lwsl_notice(" mem: per-conn:        %5u bytes + protocol rx buf\n",
                    sizeof(struct lws));
 
@@ -748,6 +788,7 @@ lws_context_destroy(struct lws_context *context)
                if (vh->protocol_vh_privs)
                        lws_free(vh->protocol_vh_privs);
                lws_ssl_SSL_CTX_destroy(vh);
+               lws_free(vh->same_vh_protocol_list);
 #ifdef LWS_WITH_PLUGINS
                if (context->plugin_list)
                        lws_free((void *)vh->protocols);
@@ -756,6 +797,11 @@ lws_context_destroy(struct lws_context *context)
                        lws_free((void *)vh->extensions);
 #endif
 #endif
+#ifdef LWS_WITH_ACCESS_LOG
+               if (vh->log_fd != LWS_INVALID_FILE)
+                       close(vh->log_fd);
+#endif
+
                vh1 = vh->vhost_next;
                lws_free(vh);
                vh = vh1;