diff --git a/changelog b/changelog index ecce0ced..35f51250 100644 --- a/changelog +++ b/changelog @@ -14,6 +14,13 @@ User api additions User api changes ---------------- + - libwebsocket_create_context() has changed from taking a ton of parameters + to just taking a pointer to a struct containing the parameters. The + struct lws_context_creation_info is in libwebsockets.h, the members + are in the same order as when they were parameters to the call + previously. The test apps are all updated accordingly so you can + see example code there. + - Header tokens are now deleted after the websocket connection is established. Not just the header data is saved, but the pointer and length array is also removed from (union) scope saving several hundred diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index c67ee928..31d6f679 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -1443,31 +1443,9 @@ int user_callback_handle_rxflow(callback_function callback_function, /** * libwebsocket_create_context() - Create the websocket handler - * @port: Port to listen on... you can use 0 to suppress listening on - * any port, that's what you want if you are not running a - * websocket server at all but just using it as a client - * @interf: NULL to bind the listen socket to all interfaces, or the - * interface name, eg, "eth2" - * @protocols: Array of structures listing supported protocols and a protocol- - * specific callback for each one. The list is ended with an - * entry that has a NULL callback pointer. - * It's not const because we write the owning_server member - * @extensions: NULL or array of libwebsocket_extension structs listing the - * extensions this context supports. If you configured with - * --without-extensions, you should give NULL here. - * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want - * to listen using SSL, set to the filepath to fetch the - * server cert from, otherwise NULL for unencrypted - * @ssl_private_key_filepath: filepath to private key if wanting SSL mode, - * else ignored - * @ssl_ca_filepath: CA certificate filepath or NULL - * @gid: group id to change to after setting listen socket, or -1. - * @uid: user id to change to after setting listen socket, or -1. - * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK - * @user: optional user pointer that can be recovered via the context - * pointer using libwebsocket_context_user + * @info: pointer to struct with parameters * - * This function creates the listening socket and takes care + * This function creates the listening socket (if serving) and takes care * of all initialization in one step. * * After initialization, it returns a struct libwebsocket_context * that @@ -1494,14 +1472,7 @@ int user_callback_handle_rxflow(callback_function callback_function, */ struct libwebsocket_context * -libwebsocket_create_context(int port, const char *interf, - struct libwebsocket_protocols *protocols, - struct libwebsocket_extension *extensions, - const char *ssl_cert_filepath, - const char *ssl_private_key_filepath, - const char *ssl_ca_filepath, - int gid, int uid, unsigned int options, - void *user) +libwebsocket_create_context(struct lws_context_creation_info *info) { int n; struct libwebsocket_context *context = NULL; @@ -1513,6 +1484,7 @@ libwebsocket_create_context(int port, const char *interf, #endif #ifndef LWS_NO_EXTENSIONS int m; + struct libwebsocket_extension *ext; #endif #ifdef LWS_OPENSSL_SUPPORT @@ -1587,11 +1559,11 @@ libwebsocket_create_context(int port, const char *interf, #endif context->listen_service_extraseen = 0; - context->protocols = protocols; - context->listen_port = port; + context->protocols = info->protocols; + context->listen_port = info->port; context->http_proxy_port = 0; context->http_proxy_address[0] = '\0'; - context->options = options; + context->options = info->options; /* to reduce this allocation, */ context->max_fds = getdtablesize(); lwsl_notice(" max fd tracked: %u\n", context->max_fds); @@ -1616,10 +1588,10 @@ libwebsocket_create_context(int port, const char *interf, context->fds_count = 0; #ifndef LWS_NO_EXTENSIONS - context->extensions = extensions; + context->extensions = info->extensions; #endif context->last_timeout_check_s = 0; - context->user_space = user; + context->user_space = info->user; #ifdef WIN32 context->fd_random = 0; @@ -1642,7 +1614,7 @@ libwebsocket_create_context(int port, const char *interf, strcpy(context->canonical_hostname, "unknown"); #ifndef LWS_NO_SERVER - if (!(options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) { + if (!(info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) { struct sockaddr sa; char hostname[1024] = ""; @@ -1699,11 +1671,11 @@ libwebsocket_create_context(int port, const char *interf, } #ifndef LWS_NO_SERVER - if (port) { + if (info->port) { #ifdef LWS_OPENSSL_SUPPORT - context->use_ssl = ssl_cert_filepath != NULL && - ssl_private_key_filepath != NULL; + 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 @@ -1775,7 +1747,7 @@ libwebsocket_create_context(int port, const char *interf, /* client context */ - if (port == CONTEXT_PORT_NO_LISTEN) { + if (info->port == CONTEXT_PORT_NO_LISTEN) { method = (SSL_METHOD *)SSLv23_client_method(); if (!method) { lwsl_err("problem creating ssl method: %s\n", @@ -1797,7 +1769,7 @@ libwebsocket_create_context(int port, const char *interf, SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING); /* openssl init for cert verification (for client sockets) */ - if (!ssl_ca_filepath) { + if (!info->ssl_ca_filepath) { if (!SSL_CTX_load_verify_locations( context->ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) @@ -1808,12 +1780,12 @@ libwebsocket_create_context(int port, const char *interf, LWS_OPENSSL_CLIENT_CERTS); } else if (!SSL_CTX_load_verify_locations( - context->ssl_client_ctx, ssl_ca_filepath, + context->ssl_client_ctx, info->ssl_ca_filepath, NULL)) lwsl_err( "Unable to load SSL Client certs " "file from %s -- client ssl isn't " - "going to work", ssl_ca_filepath); + "going to work", info->ssl_ca_filepath); /* * callback allowing user code to load extra verification certs @@ -1828,7 +1800,7 @@ libwebsocket_create_context(int port, const char *interf, /* as a server, are we requiring clients to identify themselves? */ - if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) { + if (info->options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) { /* absolutely require the client cert */ @@ -1852,18 +1824,19 @@ libwebsocket_create_context(int port, const char *interf, /* set the local certificate from CertFile */ n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx, - ssl_cert_filepath); + info->ssl_cert_filepath); if (n != 1) { lwsl_err("problem getting cert '%s': %s\n", - ssl_cert_filepath, + info->ssl_cert_filepath, ERR_error_string(ERR_get_error(), ssl_err_buf)); goto bail; } /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx, - ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) { + info->ssl_private_key_filepath, + SSL_FILETYPE_PEM) != 1) { lwsl_err("ssl problem getting key '%s': %s\n", - ssl_private_key_filepath, + info->ssl_private_key_filepath, ERR_error_string(ERR_get_error(), ssl_err_buf)); goto bail; } @@ -1885,7 +1858,7 @@ libwebsocket_create_context(int port, const char *interf, #ifndef LWS_NO_SERVER /* set up our external listening socket we serve on */ - if (port) { + if (info->port) { extern int interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen); int sockfd; @@ -1918,18 +1891,18 @@ libwebsocket_create_context(int port, const char *interf, bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; - if (interf == NULL) + if (info->interface == NULL) serv_addr.sin_addr.s_addr = INADDR_ANY; else - interface_to_sa(interf, &serv_addr, + interface_to_sa(info->interface, &serv_addr, sizeof(serv_addr)); - serv_addr.sin_port = htons(port); + serv_addr.sin_port = htons(info->port); n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); if (n < 0) { lwsl_err("ERROR on binding to port %d (%d %d)\n", - port, n, errno); + info->port, n, errno); close(sockfd); goto bail; } @@ -1954,7 +1927,7 @@ libwebsocket_create_context(int port, const char *interf, context->listen_service_fd = sockfd; listen(sockfd, LWS_SOMAXCONN); - lwsl_notice(" Listening on port %d\n", port); + lwsl_notice(" Listening on port %d\n", info->port); } #endif @@ -1965,25 +1938,26 @@ libwebsocket_create_context(int port, const char *interf, */ #ifdef WIN32 #else - if (gid != -1) - if (setgid(gid)) + if (info->gid != -1) + if (setgid(info->gid)) lwsl_warn("setgid: %s\n", strerror(errno)); - if (uid != -1) - if (setuid(uid)) + if (info->uid != -1) + if (setuid(info->uid)) lwsl_warn("setuid: %s\n", strerror(errno)); #endif /* initialize supported protocols */ for (context->count_protocols = 0; - protocols[context->count_protocols].callback; + info->protocols[context->count_protocols].callback; context->count_protocols++) { lwsl_parser(" Protocol: %s\n", - protocols[context->count_protocols].name); + info->protocols[context->count_protocols].name); - protocols[context->count_protocols].owning_server = context; - protocols[context->count_protocols].protocol_index = + info->protocols[context->count_protocols].owning_server = + context; + info->protocols[context->count_protocols].protocol_index = context->count_protocols; } @@ -1994,17 +1968,18 @@ libwebsocket_create_context(int port, const char *interf, */ m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT; - if (port) + if (info->port) m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT; - if (extensions) { - while (extensions->callback) { - lwsl_ext(" Extension: %s\n", extensions->name); - extensions->callback(context, extensions, NULL, + if (info->extensions) { + ext = info->extensions; + while (ext->callback) { + lwsl_ext(" Extension: %s\n", ext->name); + ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0); - extensions++; - } + ext++; + } } #endif return context; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 495d7393..210ecd4e 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -716,6 +716,48 @@ struct libwebsocket_extension { }; #endif +/** + * struct lws_context_creation_info: parameters to create context with + * + * @port: Port to listen on... you can use 0 to suppress listening on + * any port, that's what you want if you are not running a + * websocket server at all but just using it as a client + * @interface: NULL to bind the listen socket to all interfaces, or the + * interface name, eg, "eth2" + * @protocols: Array of structures listing supported protocols and a protocol- + * specific callback for each one. The list is ended with an + * entry that has a NULL callback pointer. + * It's not const because we write the owning_server member + * @extensions: NULL or array of libwebsocket_extension structs listing the + * extensions this context supports. If you configured with + * --without-extensions, you should give NULL here. + * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want + * to listen using SSL, set to the filepath to fetch the + * server cert from, otherwise NULL for unencrypted + * @ssl_private_key_filepath: filepath to private key if wanting SSL mode, + * else ignored + * @ssl_ca_filepath: CA certificate filepath or NULL + * @gid: group id to change to after setting listen socket, or -1. + * @uid: user id to change to after setting listen socket, or -1. + * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK + * @user: optional user pointer that can be recovered via the context + * pointer using libwebsocket_context_user + */ + +struct lws_context_creation_info { + int port; + const char *interface; + struct libwebsocket_protocols *protocols; + struct libwebsocket_extension *extensions; + const char *ssl_cert_filepath; + const char *ssl_private_key_filepath; + const char *ssl_ca_filepath; + int gid; + int uid; + unsigned int options; + void *user; +}; + LWS_EXTERN void lws_set_log_level(int level, void (*log_emit_function)(int level, const char *line)); @@ -723,14 +765,7 @@ LWS_EXTERN void lwsl_emit_syslog(int level, const char *line); LWS_EXTERN struct libwebsocket_context * -libwebsocket_create_context(int port, const char * interf, - struct libwebsocket_protocols *protocols, - struct libwebsocket_extension *extensions, - const char *ssl_cert_filepath, - const char *ssl_private_key_filepath, - const char *ssl_ca_filepath, - int gid, int uid, - unsigned int options, void *user); +libwebsocket_create_context(struct lws_context_creation_info *info); LWS_EXTERN void libwebsocket_context_destroy(struct libwebsocket_context *context); diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html index c7129c72..65a3da7a 100644 --- a/libwebsockets-api-doc.html +++ b/libwebsockets-api-doc.html @@ -344,57 +344,15 @@ has been created.
-This function creates the listening socket and takes care +This function creates the listening socket (if serving) and takes care of all initialization in one step.After initialization, it returns a struct libwebsocket_context * that @@ -997,3 +955,55 @@ is per-context, so it can track stuff across all sessions, etc, if it wants
+struct lws_context_creation_info -
+struct lws_context_creation_info {
+ int port;
+ const char * interface;
+ struct libwebsocket_protocols * protocols;
+ struct libwebsocket_extension * extensions;
+ const char * ssl_cert_filepath;
+ const char * ssl_private_key_filepath;
+ const char * ssl_ca_filepath;
+ int gid;
+ int uid;
+ unsigned int options;
+ void * user;
+};
+Members
++
+- port +
- Port to listen on... you can use 0 to suppress listening on +any port, that's what you want if you are not running a +websocket server at all but just using it as a client +
- interface +
- NULL to bind the listen socket to all interfaces, or the +interface name, eg, "eth2" +
- protocols +
- Array of structures listing supported protocols and a protocol- +specific callback for each one. The list is ended with an +entry that has a NULL callback pointer. +It's not const because we write the owning_server member +
- extensions +
- NULL or array of libwebsocket_extension structs listing the +extensions this context supports. If you configured with +--without-extensions, you should give NULL here. +
- ssl_cert_filepath +
- If libwebsockets was compiled to use ssl, and you want +to listen using SSL, set to the filepath to fetch the +server cert from, otherwise NULL for unencrypted +
- ssl_private_key_filepath +
- filepath to private key if wanting SSL mode, +else ignored +
- ssl_ca_filepath +
- CA certificate filepath or NULL +
- gid +
- group id to change to after setting listen socket, or -1. +
- uid +
- user id to change to after setting listen socket, or -1. +
- options +
- 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK +
- user +
- optional user pointer that can be recovered via the context +pointer using libwebsocket_context_user +
diff --git a/test-server/test-client.c b/test-server/test-client.c index 5d55928f..ab6f2f7d 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -201,6 +201,9 @@ int main(int argc, char **argv) int ietf_version = -1; /* latest */ int mirror_lifetime = 0; int longlived = 0; + struct lws_context_creation_info info; + + memset(&info, 0, sizeof info); fprintf(stderr, "libwebsockets test client\n" "(C) Copyright 2010-2013 Andy Green" @@ -253,14 +256,15 @@ int main(int argc, char **argv) * For this client-only demo, we tell it to not listen on any port. */ - context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL, - protocols, + info.port = CONTEXT_PORT_NO_LISTEN; + info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS - libwebsocket_internal_extensions, -#else - NULL, + info.extensions = libwebsocket_internal_extensions; #endif - NULL, NULL, NULL, -1, -1, 0, NULL); + info.gid = -1; + info.uid = -1; + + context = libwebsocket_create_context(&info); if (context == NULL) { fprintf(stderr, "Creating libwebsocket context failed\n"); return 1; diff --git a/test-server/test-echo.c b/test-server/test-echo.c index 6f96f33a..ec83de3a 100644 --- a/test-server/test-echo.c +++ b/test-server/test-echo.c @@ -147,10 +147,6 @@ static struct option options[] = { int main(int argc, char **argv) { int n = 0; - const char *cert_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; - const char *key_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; int port = 7681; int use_ssl = 0; struct libwebsocket_context *context; @@ -160,6 +156,7 @@ int main(int argc, char **argv) int syslog_options = LOG_PID | LOG_PERROR; int client = 0; int listen_port; + struct lws_context_creation_info info; #ifndef LWS_NO_CLIENT char address[256]; int rate_us = 250000; @@ -172,6 +169,8 @@ int main(int argc, char **argv) int daemonize = 0; #endif + memset(&info, 0, sizeof info); + #ifndef LWS_NO_CLIENT lwsl_notice("Built to support client operations\n"); #endif @@ -254,9 +253,6 @@ int main(int argc, char **argv) lwsl_notice("libwebsockets echo test - " "(C) Copyright 2010-2013 Andy Green - " "licensed under LGPL2.1\n"); - if (!use_ssl || client) - cert_path = key_path = NULL; - #ifndef LWS_NO_CLIENT if (client) { lwsl_notice("Running in client mode\n"); @@ -272,13 +268,22 @@ int main(int argc, char **argv) #ifndef LWS_NO_CLIENT } #endif - context = libwebsocket_create_context(listen_port, interface, protocols, + + info.port = listen_port; + info.interface = interface; + info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS - libwebsocket_internal_extensions, -#else - NULL, + info.extensions = libwebsocket_internal_extensions; #endif - cert_path, key_path, NULL, -1, -1, opts, NULL); + if (use_ssl && !client) { + info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; + info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; + } + info.gid = -1; + info.uid = -1; + info.options = opts; + + context = libwebsocket_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n"); diff --git a/test-server/test-fraggle.c b/test-server/test-fraggle.c index f2c8d7c2..cfd0f7a0 100644 --- a/test-server/test-fraggle.c +++ b/test-server/test-fraggle.c @@ -239,10 +239,6 @@ static struct option options[] = { int main(int argc, char **argv) { int n = 0; - const char *cert_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; - const char *key_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; int port = 7681; int use_ssl = 0; struct libwebsocket_context *context; @@ -252,6 +248,9 @@ int main(int argc, char **argv) struct libwebsocket *wsi; const char *address; int server_port = port; + struct lws_context_creation_info info; + + memset(&info, 0, sizeof info); fprintf(stderr, "libwebsockets test fraggle\n" "(C) Copyright 2010-2013 Andy Green " @@ -298,16 +297,21 @@ int main(int argc, char **argv) } } - if (!use_ssl) - cert_path = key_path = NULL; - - context = libwebsocket_create_context(server_port, interface, protocols, + info.port = server_port; + info.interface = interface; + info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS - libwebsocket_internal_extensions, -#else - NULL, + info.extensions = libwebsocket_internal_extensions; #endif - cert_path, key_path, NULL, -1, -1, opts, NULL); + if (use_ssl) { + info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; + info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; + } + info.gid = -1; + info.uid = -1; + info.options = opts; + + context = libwebsocket_create_context(&info); if (context == NULL) { fprintf(stderr, "libwebsocket init failed\n"); return -1; diff --git a/test-server/test-ping.c b/test-server/test-ping.c index ee390ceb..b195280c 100644 --- a/test-server/test-ping.c +++ b/test-server/test-ping.c @@ -333,6 +333,9 @@ int main(int argc, char **argv) unsigned long oldus = 0; unsigned long l; int ietf_version = -1; + struct lws_context_creation_info info; + + memset(&info, 0, sizeof info); if (argc < 2) goto usage; @@ -412,14 +415,15 @@ int main(int argc, char **argv) screen_width = w.ws_col; #endif - context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL, - protocols, + info.port = CONTEXT_PORT_NO_LISTEN; + info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS - libwebsocket_internal_extensions, -#else - NULL, + info.extensions = libwebsocket_internal_extensions; #endif - NULL, NULL, NULL, -1, -1, 0, NULL); + info.gid = -1; + info.uid = -1; + + context = libwebsocket_create_context(&info); if (context == NULL) { fprintf(stderr, "Creating libwebsocket context failed\n"); return 1; diff --git a/test-server/test-server.c b/test-server/test-server.c index 89696707..be019668 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -492,11 +492,6 @@ static struct option options[] = { int main(int argc, char **argv) { int n = 0; - const char *cert_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; - const char *key_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; - int port = 7681; int use_ssl = 0; struct libwebsocket_context *context; int opts = 0; @@ -506,12 +501,16 @@ int main(int argc, char **argv) int syslog_options = LOG_PID | LOG_PERROR; #endif unsigned int oldus = 0; + struct lws_context_creation_info info; int debug_level = 7; #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif + memset(&info, 0, sizeof info); + info.port = 7681; + while (n >= 0) { n = getopt_long(argc, argv, "ci:hsp:d:D", options, NULL); if (n < 0) @@ -532,7 +531,7 @@ int main(int argc, char **argv) use_ssl = 1; break; case 'p': - port = atoi(optarg); + info.port = atoi(optarg); break; case 'i': strncpy(interface_name, optarg, sizeof interface_name); @@ -579,8 +578,6 @@ int main(int argc, char **argv) lwsl_notice("libwebsockets test server - " "(C) Copyright 2010-2013 Andy Green - " "licensed under LGPL2.1\n"); - if (!use_ssl) - cert_path = key_path = NULL; #ifdef EXTERNAL_POLL max_poll_elements = getdtablesize(); pollfds = malloc(max_poll_elements * sizeof (struct pollfd)); @@ -591,13 +588,23 @@ int main(int argc, char **argv) } #endif - context = libwebsocket_create_context(port, interface, protocols, + info.interface = interface; + info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS - libwebsocket_internal_extensions, -#else - NULL, + info.extensions = libwebsocket_internal_extensions; #endif - cert_path, key_path, NULL, -1, -1, opts, NULL); + if (!use_ssl) { + info.ssl_cert_filepath = NULL; + info.ssl_private_key_filepath = NULL; + } else { + info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; + info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; + } + info.gid = -1; + info.uid = -1; + info.options = opts; + + context = libwebsocket_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n"); return -1;