LWS_VISIBLE struct libwebsocket_context * libwebsocket_create_context(struct lws_context_creation_info *info) { struct libwebsocket_context *context = NULL; char *p; #ifndef LWS_NO_DAEMONIZE int pid_daemon = get_daemonize_pid(); #endif lwsl_notice("Initial logging level %d\n", log_level); lwsl_notice("Library version: %s\n", library_version); #ifdef LWS_USE_IPV6 if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6)) lwsl_notice("IPV6 compiled in and enabled\n"); else lwsl_notice("IPV6 compiled in but disabled\n"); #else lwsl_notice("IPV6 not compiled in\n"); #endif #ifdef LWS_USE_LIBEV if (info->options & LWS_SERVER_OPTION_LIBEV) lwsl_notice("libev support compiled in and enabled\n"); else lwsl_notice("libev support compiled in but disabled\n"); #else lwsl_notice("libev support not compiled in\n"); #endif lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN); lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS); #ifndef LWS_NO_EXTENSIONS lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE); #else lwsl_notice(" Configured without extension support\n"); #endif lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED); lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT); lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER); if (lws_plat_context_early_init()) return NULL; context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context)); if (!context) { lwsl_err("No memory for websocket context\n"); return NULL; } memset(context, 0, sizeof(*context)); #ifndef LWS_NO_DAEMONIZE context->started_with_parent = pid_daemon; lwsl_notice(" Started with daemon pid %d\n", pid_daemon); #endif context->listen_service_extraseen = 0; context->protocols = info->protocols; context->listen_port = info->port; context->http_proxy_port = 0; context->http_proxy_address[0] = '\0'; context->options = info->options; context->iface = info->iface; /* to reduce this allocation, */ context->max_fds = getdtablesize(); lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n", sizeof(struct libwebsocket_context), sizeof(struct libwebsocket_pollfd) + sizeof(struct libwebsocket *), context->max_fds, sizeof(struct libwebsocket_context) + ((sizeof(struct libwebsocket_pollfd) + sizeof(struct libwebsocket *)) * context->max_fds)); context->fds = (struct libwebsocket_pollfd *) malloc(sizeof(struct libwebsocket_pollfd) * context->max_fds); if (context->fds == NULL) { lwsl_err("Unable to allocate fds array for %d connections\n", context->max_fds); free(context); return NULL; } context->lws_lookup = (struct libwebsocket **) malloc(sizeof(struct libwebsocket *) * context->max_fds); if (context->lws_lookup == NULL) { lwsl_err( "Unable to allocate lws_lookup array for %d connections\n", context->max_fds); free(context->fds); free(context); return NULL; } memset(context->lws_lookup, 0, sizeof(struct libwebsocket *) * context->max_fds); if (lws_plat_init_fd_tables(context)) { free(context->lws_lookup); free(context->fds); free(context); return NULL; } #ifndef LWS_NO_EXTENSIONS context->extensions = info->extensions; #endif context->user_space = info->user; strcpy(context->canonical_hostname, "unknown"); #ifndef LWS_NO_SERVER if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) { /* find canonical hostname */ gethostname((char *)context->canonical_hostname, sizeof(context->canonical_hostname) - 1); lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname); } #endif /* split the proxy ads:port if given */ if (info->http_proxy_address) { strncpy(context->http_proxy_address, info->http_proxy_address, sizeof(context->http_proxy_address) - 1); context->http_proxy_address[ sizeof(context->http_proxy_address) - 1] = '\0'; context->http_proxy_port = info->http_proxy_port; } else { #ifdef HAVE_GETENV p = getenv("http_proxy"); if (p) { strncpy(context->http_proxy_address, p, sizeof(context->http_proxy_address) - 1); context->http_proxy_address[ sizeof(context->http_proxy_address) - 1] = '\0'; p = strchr(context->http_proxy_address, ':'); if (p == NULL) { lwsl_err("http_proxy needs to be ads:port\n"); goto bail; } *p = '\0'; context->http_proxy_port = atoi(p + 1); } #endif } if (context->http_proxy_address[0]) lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address, context->http_proxy_port); lwsl_notice( " per-conn mem: %u + %u headers + protocol rx buf\n", sizeof(struct libwebsocket), sizeof(struct allocated_headers)); if (lws_context_init_server_ssl(info, context)) goto bail; if (lws_context_init_client_ssl(info, context)) goto bail; if (lws_context_init_server(info, context)) goto bail; /* * drop any root privs for this process * to listen on port < 1023 we would have needed root, but now we are * listening, we don't want the power for anything else */ lws_plat_drop_app_privileges(info); /* initialize supported protocols */ for (context->count_protocols = 0; info->protocols[context->count_protocols].callback; context->count_protocols++) { lwsl_parser(" Protocol: %s\n", info->protocols[context->count_protocols].name); info->protocols[context->count_protocols].owning_server = context; info->protocols[context->count_protocols].protocol_index = context->count_protocols; /* * inform all the protocols that they are doing their one-time * initialization if they want to */ info->protocols[context->count_protocols].callback(context, NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0); } /* * give all extensions a chance to create any per-context * allocations they need */ if (info->port != CONTEXT_PORT_NO_LISTEN) { if (lws_ext_callback_for_each_extension_type(context, NULL, LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; } else if (lws_ext_callback_for_each_extension_type(context, NULL, LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; return context; bail: libwebsocket_context_destroy(context); return NULL; }
LWS_VISIBLE struct lws_vhost * lws_create_vhost(struct lws_context *context, struct lws_context_creation_info *info) { struct lws_vhost *vh = lws_zalloc(sizeof(*vh)), **vh1 = &context->vhost_list; const struct lws_http_mount *mounts; const struct lws_protocol_vhost_options *pvo; #ifdef LWS_WITH_PLUGINS struct lws_plugin *plugin = context->plugin_list; struct lws_protocols *lwsp; int m, f = !info->pvo; #endif #ifdef LWS_HAVE_GETENV char *p; #endif int n; if (!vh) return NULL; if (!info->protocols) info->protocols = &protocols_dummy[0]; vh->context = context; if (!info->vhost_name) vh->name = "default"; else vh->name = info->vhost_name; vh->iface = info->iface; for (vh->count_protocols = 0; info->protocols[vh->count_protocols].callback; vh->count_protocols++) ; vh->options = info->options; vh->pvo = info->pvo; vh->headers = info->headers; if (info->keepalive_timeout) vh->keepalive_timeout = info->keepalive_timeout; else vh->keepalive_timeout = 5; #ifdef LWS_WITH_PLUGINS if (plugin) { /* * give the vhost a unified list of protocols including the * ones that came from plugins */ lwsp = lws_zalloc(sizeof(struct lws_protocols) * (vh->count_protocols + context->plugin_protocol_count + 1)); if (!lwsp) return NULL; m = vh->count_protocols; 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 (f || lws_vhost_protocol_options(vh, plugin->caps.protocols[n].name)) { memcpy(&lwsp[m], &plugin->caps.protocols[n], sizeof(struct lws_protocols)); m++; vh->count_protocols++; } } plugin = plugin->list; } vh->protocols = lwsp; } else #endif vh->protocols = info->protocols; 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, IPv6 %s\n", vh->name, info->port, vh->count_protocols, LWS_IPV6_ENABLED(vh) ? "on" : "off"); mounts = info->mounts; while (mounts) { lwsl_notice(" mounting %s%s to %s\n", mount_protocols[mounts->origin_protocol], mounts->origin, mounts->mountpoint); /* convert interpreter protocol names to pointers */ pvo = mounts->interpret; while (pvo) { for (n = 0; n < vh->count_protocols; n++) if (!strcmp(pvo->value, vh->protocols[n].name)) { ((struct lws_protocol_vhost_options *)pvo)->value = (const char *)(long)n; break; } if (n == vh->count_protocols) lwsl_err("ignoring unknown interpret protocol %s\n", pvo->value); pvo = pvo->next; } mounts = mounts->mount_next; } #ifndef LWS_NO_EXTENSIONS #ifdef LWS_WITH_PLUGINS if (context->plugin_extension_count) { m = 0; while (info->extensions && info->extensions[m].callback) m++; /* * give the vhost a unified list of extensions including the * ones that came from plugins */ vh->extensions = lws_zalloc(sizeof(struct lws_extension) * (m + context->plugin_extension_count + 1)); if (!vh->extensions) return NULL; 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, sizeof(struct lws_extension) * plugin->caps.count_extensions); m += plugin->caps.count_extensions; plugin = plugin->list; } } else #endif vh->extensions = info->extensions; #endif vh->listen_port = info->port; #if !defined(LWS_WITH_ESP8266) vh->http_proxy_port = 0; vh->http_proxy_address[0] = '\0'; /* either use proxy from info, or try get it from env var */ if (info->http_proxy_address) { /* override for backwards compatibility */ if (info->http_proxy_port) vh->http_proxy_port = info->http_proxy_port; lws_set_proxy(vh, info->http_proxy_address); } else { #ifdef LWS_HAVE_GETENV p = getenv("http_proxy"); if (p) lws_set_proxy(vh, p); #endif } #endif vh->ka_time = info->ka_time; 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 == (int)LWS_INVALID_FILE) { lwsl_err("unable to open log filepath %s\n", info->log_filepath); goto bail; } #ifndef WIN32 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); #endif } else vh->log_fd = (int)LWS_INVALID_FILE; #endif if (lws_context_init_server_ssl(info, vh)) goto bail; if (lws_context_init_client_ssl(info, vh)) goto bail; if (lws_context_init_server(info, vh)) goto bail; while (1) { if (!(*vh1)) { *vh1 = vh; break; } vh1 = &(*vh1)->vhost_next; }; return vh; bail: lws_free(vh); return NULL; }
LWS_VISIBLE struct lws_context * lws_create_context(struct lws_context_creation_info *info) { struct lws_context *context = NULL; struct lws wsi; #ifndef LWS_NO_DAEMONIZE int pid_daemon = get_daemonize_pid(); #endif char *p; int n; lwsl_notice("Initial logging level %d\n", log_level); lwsl_notice("Libwebsockets version: %s\n", library_version); #if LWS_POSIX #ifdef LWS_USE_IPV6 if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6)) lwsl_notice("IPV6 compiled in and enabled\n"); else lwsl_notice("IPV6 compiled in but disabled\n"); #else lwsl_notice("IPV6 not compiled in\n"); #endif lws_feature_status_libev(info); #endif lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN); lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS); lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED); lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT); lwsl_info(" sizeof (*info): %u\n", sizeof(*info)); #if LWS_POSIX lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER); #endif if (lws_plat_context_early_init()) return NULL; context = lws_zalloc(sizeof(struct lws_context)); if (!context) { lwsl_err("No memory for websocket context\n"); return NULL; } #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { context->started_with_parent = pid_daemon; lwsl_notice(" Started with daemon pid %d\n", pid_daemon); } #endif context->lserv_seen = 0; context->protocols = info->protocols; context->token_limits = info->token_limits; context->listen_port = info->port; context->http_proxy_port = 0; context->http_proxy_address[0] = '\0'; context->options = info->options; context->iface = info->iface; context->ka_time = info->ka_time; context->ka_interval = info->ka_interval; context->ka_probes = info->ka_probes; memset(&wsi, 0, sizeof(wsi)); wsi.context = context; if (!info->ka_interval && info->ka_time > 0) { lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); return NULL; } #ifdef LWS_USE_LIBEV /* (Issue #264) In order to *avoid breaking backwards compatibility*, we * enable libev mediated SIGINT handling with a default handler of * lws_sigint_cb. The handler can be overridden or disabled * by invoking lws_sigint_cfg after creating the context, but * before invoking lws_initloop: */ context->use_ev_sigint = 1; context->lws_ev_sigint_cb = &lws_sigint_cb; #endif /* LWS_USE_LIBEV */ lwsl_info(" mem: context: %5u bytes\n", sizeof(struct lws_context)); /* * allocate and initialize the pool of * allocated_header structs + data */ if (info->max_http_header_data) context->max_http_header_data = info->max_http_header_data; else context->max_http_header_data = LWS_MAX_HEADER_LEN; if (info->max_http_header_pool) context->max_http_header_pool = info->max_http_header_pool; else context->max_http_header_pool = LWS_MAX_HEADER_POOL; context->http_header_data = lws_malloc(context->max_http_header_data * context->max_http_header_pool); if (!context->http_header_data) goto bail; context->ah_pool = lws_zalloc(sizeof(struct allocated_headers) * context->max_http_header_pool); if (!context->ah_pool) goto bail; for (n = 0; n < context->max_http_header_pool; n++) context->ah_pool[n].data = (char *)context->http_header_data + (n * context->max_http_header_data); /* this is per context */ lwsl_info(" mem: http hdr rsvd: %5u bytes ((%u + %u) x %u)\n", (context->max_http_header_data + sizeof(struct allocated_headers)) * context->max_http_header_pool, context->max_http_header_data, sizeof(struct allocated_headers), context->max_http_header_pool); context->max_fds = getdtablesize(); context->fds = lws_zalloc(sizeof(struct lws_pollfd) * context->max_fds); if (context->fds == NULL) { lwsl_err("OOM allocating %d fds\n", context->max_fds); goto bail; } lwsl_info(" mem: pollfd map: %5u\n", sizeof(struct lws_pollfd) * context->max_fds); if (lws_plat_init(context, info)) goto bail; 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)); strcpy(context->canonical_hostname, "unknown"); lws_server_get_canonical_hostname(context, info); /* either use proxy from info, or try get it from env var */ if (info->http_proxy_address) { /* override for backwards compatibility */ if (info->http_proxy_port) context->http_proxy_port = info->http_proxy_port; lws_set_proxy(context, info->http_proxy_address); } else { #ifdef LWS_HAVE_GETENV p = getenv("http_proxy"); if (p) lws_set_proxy(context, p); #endif } if (lws_context_init_server_ssl(info, context)) goto bail; if (lws_context_init_client_ssl(info, context)) goto bail; if (lws_context_init_server(info, context)) goto bail; /* * drop any root privs for this process * to listen on port < 1023 we would have needed root, but now we are * listening, we don't want the power for anything else */ lws_plat_drop_app_privileges(info); /* initialize supported protocols */ for (context->count_protocols = 0; info->protocols[context->count_protocols].callback; context->count_protocols++) /* * inform all the protocols that they are doing their one-time * initialization if they want to. * * NOTE the wsi is all zeros except for the context pointer * so lws_get_context(wsi) can work in the callback. */ info->protocols[context->count_protocols].callback(&wsi, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0); /* * give all extensions a chance to create any per-context * allocations they need */ if (info->port != CONTEXT_PORT_NO_LISTEN) { if (lws_ext_cb_all_exts(context, NULL, LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; } else if (lws_ext_cb_all_exts(context, NULL, LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; return context; bail: lws_context_destroy(context); return NULL; }
LWS_VISIBLE struct libwebsocket_context * libwebsocket_create_context(struct lws_context_creation_info *info) { struct libwebsocket_context *context = NULL; char *p; #ifdef _WIN32 int i; #endif int pid_daemon = get_daemonize_pid(); lwsl_notice("Initial logging level %d\n", log_level); lwsl_notice("Library version: %s\n", library_version); #ifdef LWS_USE_IPV6 if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6)) lwsl_notice("IPV6 compiled in and enabled\n"); else lwsl_notice("IPV6 compiled in but disabled\n"); #else lwsl_notice("IPV6 not compiled in\n"); #endif lws_feature_status_libev(info); lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN); lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS); lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED); lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT); lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER); if (lws_plat_context_early_init()) return NULL; context = lws_zalloc(sizeof(struct libwebsocket_context)); if (!context) { lwsl_err("No memory for websocket context\n"); return NULL; } if (pid_daemon) { context->started_with_parent = pid_daemon; lwsl_notice(" Started with daemon pid %d\n", pid_daemon); } context->listen_service_extraseen = 0; context->protocols = info->protocols; context->token_limits = info->token_limits; context->listen_port = info->port; context->http_proxy_port = 0; context->http_proxy_address[0] = '\0'; context->options = info->options; context->iface = info->iface; context->ka_time = info->ka_time; context->ka_interval = info->ka_interval; context->ka_probes = info->ka_probes; if (!info->ka_interval && info->ka_time > 0) { lwsl_err("info->ka_interval can't be 0 if ka_time used\n"); return NULL; } #ifdef LWS_USE_LIBEV /* (Issue #264) In order to *avoid breaking backwards compatibility*, we * enable libev mediated SIGINT handling with a default handler of * libwebsocket_sigint_cb. The handler can be overridden or disabled * by invoking libwebsocket_sigint_cfg after creating the context, but * before invoking libwebsocket_initloop: */ context->use_ev_sigint = 1; context->lws_ev_sigint_cb = &libwebsocket_sigint_cb; #endif /* LWS_USE_LIBEV */ /* to reduce this allocation, */ context->max_fds = getdtablesize(); lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n", sizeof(struct libwebsocket_context), sizeof(struct libwebsocket_pollfd) + sizeof(struct libwebsocket *), context->max_fds, sizeof(struct libwebsocket_context) + ((sizeof(struct libwebsocket_pollfd) + sizeof(struct libwebsocket *)) * context->max_fds)); context->fds = lws_zalloc(sizeof(struct libwebsocket_pollfd) * context->max_fds); if (context->fds == NULL) { lwsl_err("Unable to allocate fds array for %d connections\n", context->max_fds); goto bail; } if (lws_plat_init_lookup(context)) { goto bail; } if (lws_plat_init_fd_tables(context)) { goto bail; } lws_context_init_extensions(info, context); context->user_space = info->user; strcpy(context->canonical_hostname, "unknown"); lws_server_get_canonical_hostname(context, info); /* split the proxy ads:port if given */ if (info->http_proxy_address) { strncpy(context->http_proxy_address, info->http_proxy_address, sizeof(context->http_proxy_address) - 1); context->http_proxy_address[ sizeof(context->http_proxy_address) - 1] = '\0'; context->http_proxy_port = info->http_proxy_port; } else { #ifdef LWS_HAVE_GETENV p = getenv("http_proxy"); if (p) { strncpy(context->http_proxy_address, p, sizeof(context->http_proxy_address) - 1); context->http_proxy_address[ sizeof(context->http_proxy_address) - 1] = '\0'; p = strchr(context->http_proxy_address, ':'); if (p == NULL) { lwsl_err("http_proxy needs to be ads:port\n"); goto bail; } *p = '\0'; context->http_proxy_port = atoi(p + 1); } #endif } if (context->http_proxy_address[0]) lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address, context->http_proxy_port); lwsl_notice( " per-conn mem: %u + %u headers + protocol rx buf\n", sizeof(struct libwebsocket), sizeof(struct allocated_headers)); if (lws_context_init_server_ssl(info, context)) goto bail; if (lws_context_init_client_ssl(info, context)) goto bail; if (lws_context_init_server(info, context)) goto bail; /* * drop any root privs for this process * to listen on port < 1023 we would have needed root, but now we are * listening, we don't want the power for anything else */ lws_plat_drop_app_privileges(info); /* initialize supported protocols */ for (context->count_protocols = 0; info->protocols[context->count_protocols].callback; context->count_protocols++) { lwsl_parser(" Protocol: %s\n", info->protocols[context->count_protocols].name); info->protocols[context->count_protocols].owning_server = context; info->protocols[context->count_protocols].protocol_index = context->count_protocols; /* * inform all the protocols that they are doing their one-time * initialization if they want to */ info->protocols[context->count_protocols].callback(context, NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0); } /* * give all extensions a chance to create any per-context * allocations they need */ if (info->port != CONTEXT_PORT_NO_LISTEN) { if (lws_ext_callback_for_each_extension_type(context, NULL, LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; } else if (lws_ext_callback_for_each_extension_type(context, NULL, LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT, NULL, 0) < 0) goto bail; return context; bail: libwebsocket_context_destroy(context); return NULL; }