int *fd_lookup;
int count_pollfds;
#endif
-volatile int force_exit = 0;
+volatile int force_exit = 0, dynamic_vhost_enable = 0;
+struct lws_vhost *dynamic_vhost;
struct lws_context *context;
struct lws_plat_file_ops fops_plat;
char crl_path[1024] = "";
#endif
+/*
+ * This demonstrates how to use the clean protocol service separation of
+ * plugins, but with static inclusion instead of runtime dynamic loading
+ * (which requires libuv).
+ *
+ * dumb-increment doesn't use the plugin, both to demonstrate how to
+ * do the protocols directly, and because it wants libuv for a timer.
+ *
+ * Please consider using test-server-v2.0.c instead of this: it has the
+ * same functionality but
+ *
+ * 1) uses lws built-in http handling so you don't need to deal with it in
+ * your callback
+ *
+ * 2) Links with libuv and uses the plugins at runtime
+ *
+ * 3) Uses advanced lws features like mounts to bind parts of the filesystem
+ * to the served URL space
+ *
+ * Another option is lwsws, this operates like test-server-v2,0.c but is
+ * configured using JSON, do you do not need to provide any code for the
+ * serving action at all, just implement your protocols in plugins.
+ */
+
+#define LWS_PLUGIN_STATIC
+#include "../plugins/protocol_lws_mirror.c"
+#include "../plugins/protocol_lws_status.c"
+
/* singlethreaded version --> no locks */
void test_server_lock(int care)
*
* lws-mirror-protocol: copies any received packet to every connection also
* using this protocol, including the sender
+ *
+ * lws-status: informs connected browsers of who else is
+ * connected.
*/
enum demo_protocols {
PROTOCOL_DUMB_INCREMENT,
PROTOCOL_LWS_MIRROR,
- PROTOCOL_LWS_ECHOGEN,
PROTOCOL_LWS_STATUS,
/* always last */
"dumb-increment-protocol",
callback_dumb_increment,
sizeof(struct per_session_data__dumb_increment),
- 10, /* rx buf size must be >= permessage-deflate rx size */
- },
- {
- "lws-mirror-protocol",
- callback_lws_mirror,
- sizeof(struct per_session_data__lws_mirror),
- 128, /* rx buf size must be >= permessage-deflate rx size */
- },
- {
- "lws-echogen",
- callback_lws_echogen,
- sizeof(struct per_session_data__echogen),
- 128, /* rx buf size must be >= permessage-deflate rx size */
- },
- {
- "lws-status",
- callback_lws_status,
- sizeof(struct per_session_data__lws_status),
- 128, /* rx buf size must be >= permessage-deflate rx size */
+ 10, /* rx buf size must be >= permessage-deflate rx size
+ * dumb-increment only sends very small packets, so we set
+ * this accordingly. If your protocol will send bigger
+ * things, adjust this to match */
},
+ LWS_PLUGIN_PROTOCOL_MIRROR,
+ LWS_PLUGIN_PROTOCOL_LWS_STATUS,
{ NULL, NULL, 0, 0 } /* terminator */
};
void sighandler(int sig)
{
+#if !defined(WIN32) && !defined(_WIN32)
+ /* because windows is too dumb to have SIGUSR1... */
+ if (sig == SIGUSR1) {
+ /*
+ * For testing, you can fire a SIGUSR1 at the test server
+ * to toggle the existence of an identical server on
+ * port + 1
+ */
+ dynamic_vhost_enable ^= 1;
+ lwsl_notice("SIGUSR1: dynamic_vhost_enable: %d\n",
+ dynamic_vhost_enable);
+ return;
+ }
+#endif
force_exit = 1;
lws_cancel_service(context);
}
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;
info.port = 7681;
while (n >= 0) {
- n = getopt_long(argc, argv, "eci:hsap:d:Dr:C:K:A:R:vu:g:P:", options, NULL);
+ n = getopt_long(argc, argv, "eci:hsap:d:Dr:C:K:A:R:vu:g:P:k", options, NULL);
if (n < 0)
continue;
switch (n) {
break;
case 's':
use_ssl = 1;
+ opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
break;
case 'a':
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
interface_name[(sizeof interface_name) - 1] = '\0';
iface = interface_name;
break;
+ case 'k':
+ info.bind_iface = 1;
+#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
+ info.caps[0] = CAP_NET_RAW;
+ info.count_caps = 1;
+#endif
+ break;
case 'c':
close_testing = 1;
fprintf(stderr, " Close testing mode -- closes on "
#endif
signal(SIGINT, sighandler);
+#if !defined(WIN32) && !defined(_WIN32)
+ /* because windows is too dumb to have SIGUSR1... */
+ /* dynamic vhost create / destroy toggle (on port + 1) */
+ signal(SIGUSR1, sighandler);
+#endif
#ifndef _WIN32
/* we will only try to log things according to our debug_level */
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;
info.extensions = exts;
info.timeout_secs = 5;
info.ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
return -1;
}
+ vhost = lws_create_vhost(context, &info);
+ if (!vhost) {
+ lwsl_err("vhost creation failed\n");
+ return -1;
+ }
+
+ /*
+ * For testing dynamic vhost create / destroy later, we use port + 1
+ * Normally if you were creating more vhosts, you would set info.name
+ * for each to be the hostname external clients use to reach it
+ */
+
+ info.port++;
+
+#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)
n = lws_service(context, 50);
#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;
+ }
+
}
#ifdef EXTERNAL_POLL