diff --git a/README.esp8266.md b/README.esp8266.md new file mode 100644 index 00000000..ffcf7578 --- /dev/null +++ b/README.esp8266.md @@ -0,0 +1,34 @@ +ESP8266 lws port +---------------- + +lws can now work well on the ESP8266. + +You should get the ESP8266 Espressif SDK-based project here + +https://github.com/lws-team/esplws + +which includes lws as an "app" in the build. The project provides full AP-based setup over the web, and once the device has been configured to associate to a local AP, a separate station vhost with the lws test protocols. + +Instructions for building that are here + +https://github.com/lws-team/esplws/blob/master/README.md + +There are also instructions there for how to remove the test apps from the build and customize your own station content. + + +Information about lws integration on ESP8266 +-------------------------------------------- + +The following existing lws features are used to make a nice integration: + + - vhosts: there are separate vhosts for the configuration AP mode and the normal station mode. + + - file_ops: the lws file operations are overridden and handled by a ROMFS parser + + - mounts: mounts are used to serve files automatically from the ROMFS + + - plugins: standalone protocol plugins are included into the build, so there are clean individual implementations for each protocol, while everything is statically linked + + - lws stability and security features like bytewise parsers, sophisticated timeouts, http/1.1 keepalive support + + diff --git a/README.md b/README.md index d640c61d..7320af6b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ libwebsockets ------------- +| News | +------ +| ESP8266 is now supported in lws! See https://github.com/warmcat/libwebsockets/blob/master/README.esp8266.md | + + This is the libwebsockets C library for lightweight websocket clients and servers. For support, visit @@ -15,10 +20,6 @@ and consider joining the project mailing list at https://libwebsockets.org/mailman/listinfo/libwebsockets -| News | ------- -| We have updated https://libwebsockets.org, if you would like your project using lws featured in the image carousel, send an image, project URL and brief summary to andy@warmcat.com | - You can get the latest version of the library from git: - https://github.com/warmcat/libwebsockets diff --git a/lib/client-handshake.c b/lib/client-handshake.c index 678979fb..5f915bfa 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -175,6 +175,8 @@ lws_client_connect_2(struct lws *wsi) goto oom4; } + lws_change_pollfd(wsi, 0, LWS_POLLIN); + /* * past here, we can't simply free the structs as error * handling as oom4 does. We have to run the whole close flow. @@ -485,6 +487,9 @@ lws_client_connect_via_info(struct lws_client_connect_info *i) if (i->context->requested_kill) return NULL; + if (!i->context->protocol_init_done) + lws_protocol_init(i->context); + wsi = lws_zalloc(sizeof(struct lws)); if (wsi == NULL) goto bail; diff --git a/lib/parsers.c b/lib/parsers.c index 4e03394a..ecb7bc3b 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -119,7 +119,7 @@ lws_header_table_attach(struct lws *wsi, int autoservice) struct lws **pwsi; int n; - lwsl_notice("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__, (void *)wsi, + lwsl_info("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__, (void *)wsi, (void *)wsi->u.hdr.ah, wsi->tsi, pt->ah_count_in_use); /* if we are already bound to one, just clear it down */ @@ -291,14 +291,15 @@ int lws_header_table_detach(struct lws *wsi, int autoservice) lws_header_table_reset(wsi, autoservice); time(&wsi->u.hdr.ah->assigned); - assert(wsi->position_in_fds_table != -1); + /* clients acquire the ah and then insert themselves in fds table... */ + if (wsi->position_in_fds_table != -1) { + lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi); - lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi); - - /* he has been stuck waiting for an ah, but now his wait is over, - * let him progress - */ - _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa); + /* he has been stuck waiting for an ah, but now his wait is over, + * let him progress + */ + _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa); + } /* point prev guy to next guy in list instead */ *pwsi = wsi->u.hdr.ah_wait_list; diff --git a/lib/pollfd.c b/lib/pollfd.c index cafa0bef..a56908b8 100644 --- a/lib/pollfd.c +++ b/lib/pollfd.c @@ -43,6 +43,8 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) pa->prev_events = pfd->events; pa->events = pfd->events = (pfd->events & ~_and) | _or; + //lwsl_notice("%s: wsi %p, posin %d. from %d -> %d\n", __func__, wsi, wsi->position_in_fds_table, pa->prev_events, pa->events); + if (wsi->http2_substream) return 0; @@ -147,6 +149,9 @@ insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi) if (wsi->position_in_fds_table == -1) #endif wsi->position_in_fds_table = pt->fds_count; + + // lwsl_notice("%s: %p: setting posinfds %d\n", __func__, wsi, wsi->position_in_fds_table); + pt->fds[wsi->position_in_fds_table].fd = wsi->sock; #if LWS_POSIX pt->fds[wsi->position_in_fds_table].events = LWS_POLLIN; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 93d340ac..e7075028 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -701,6 +701,7 @@ struct lws_context_per_thread { short ah_count_in_use; unsigned char tid; + unsigned char lock_depth; }; /* @@ -1752,13 +1753,15 @@ lws_pt_mutex_destroy(struct lws_context_per_thread *pt) static LWS_INLINE void lws_pt_lock(struct lws_context_per_thread *pt) { - pthread_mutex_lock(&pt->lock); + if (!pt->lock_depth++) + pthread_mutex_lock(&pt->lock); } static LWS_INLINE void lws_pt_unlock(struct lws_context_per_thread *pt) { - pthread_mutex_unlock(&pt->lock); + if (!(--pt->lock_depth)) + pthread_mutex_unlock(&pt->lock); } #else #define lws_pt_mutex_init(_a) (void)(_a) diff --git a/test-server/test-client.c b/test-server/test-client.c index a06deb5f..a6ffe297 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -39,8 +39,9 @@ static int deny_deflate, longlived, mirror_lifetime; static struct lws *wsi_dumb, *wsi_mirror; +static struct lws *wsi_multi[3]; static volatile int force_exit; -static unsigned int opts; +static unsigned int opts, rl_multi[3]; static int flag_no_mirror_traffic; #if defined(LWS_USE_POLARSSL) #else @@ -87,6 +88,8 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { const char *which = "http"; + char which_wsi[10]; + int n; switch (reason) { @@ -116,6 +119,13 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, wsi_mirror = NULL; } + for (n = 0; n < ARRAY_SIZE(wsi_multi); n++) + if (wsi == wsi_multi[n]) { + sprintf(which_wsi, "multi %d", n); + which = which_wsi; + wsi_multi[n] = NULL; + } + lwsl_err("CLIENT_CONNECTION_ERROR: %s: %s %p\n", which, in); break; @@ -152,6 +162,10 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, } break; + case LWS_CALLBACK_CLIENT_WRITEABLE: + lwsl_notice("Client wsi %p writable\n", wsi); + break; + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: wsi_dumb = NULL; force_exit = 1; @@ -322,6 +336,7 @@ static struct option options[] = { { "strict-ssl", no_argument, NULL, 'S' }, { "version", required_argument, NULL, 'v' }, { "undeflated", no_argument, NULL, 'u' }, + { "multi-test", no_argument, NULL, 'm' }, { "nomirror", no_argument, NULL, 'n' }, { "longlived", no_argument, NULL, 'l' }, { "pingpong-secs", required_argument, NULL, 'P' }, @@ -350,8 +365,8 @@ static int ratelimit_connects(unsigned int *last, unsigned int secs) int main(int argc, char **argv) { - int n = 0, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1; - unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, pp_secs = 0; + int n = 0, m, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1; + unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, pp_secs = 0, do_multi = 0; struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; @@ -370,7 +385,7 @@ int main(int argc, char **argv) goto usage; while (n >= 0) { - n = getopt_long(argc, argv, "Snuv:hsp:d:lC:K:A:P:", options, NULL); + n = getopt_long(argc, argv, "Snuv:hsp:d:lC:K:A:P:m", options, NULL); if (n < 0) continue; switch (n) { @@ -401,6 +416,9 @@ int main(int argc, char **argv) case 'u': deny_deflate = 1; break; + case 'm': + do_multi = 1; + break; case 'n': flag_no_mirror_traffic = 1; lwsl_notice("Disabled sending mirror data (for pingpong testing)\n"); @@ -544,30 +562,52 @@ int main(int argc, char **argv) * asynchronously. */ + m = 0; while (!force_exit) { - if (do_ws) { - if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) { - lwsl_notice("dumb: connecting\n"); - i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name; - i.pwsi = &wsi_dumb; - lws_client_connect_via_info(&i); + if (do_multi) { + for (n = 0; n < ARRAY_SIZE(wsi_multi); n++) { + if (!wsi_multi[n] && ratelimit_connects(&rl_multi[n], 2u)) { + lwsl_notice("dumb %d: connecting\n", n); + i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name; + i.pwsi = &wsi_multi[n]; + lws_client_connect_via_info(&i); + } } + } else { - if (!wsi_mirror && ratelimit_connects(&rl_mirror, 2u)) { - lwsl_notice("mirror: connecting\n"); - i.protocol = protocols[PROTOCOL_LWS_MIRROR].name; - i.pwsi = &wsi_mirror; - wsi_mirror = lws_client_connect_via_info(&i); - } - } else - if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) { - lwsl_notice("http: connecting\n"); - i.pwsi = &wsi_dumb; - lws_client_connect_via_info(&i); - } + if (do_ws) { + if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) { + lwsl_notice("dumb: connecting\n"); + i.protocol = protocols[PROTOCOL_DUMB_INCREMENT].name; + i.pwsi = &wsi_dumb; + lws_client_connect_via_info(&i); + } + + if (!wsi_mirror && ratelimit_connects(&rl_mirror, 2u)) { + lwsl_notice("mirror: connecting\n"); + i.protocol = protocols[PROTOCOL_LWS_MIRROR].name; + i.pwsi = &wsi_mirror; + wsi_mirror = lws_client_connect_via_info(&i); + } + } else + if (!wsi_dumb && ratelimit_connects(&rl_dumb, 2u)) { + lwsl_notice("http: connecting\n"); + i.pwsi = &wsi_dumb; + lws_client_connect_via_info(&i); + } + } lws_service(context, 500); + + if (do_multi) { + m++; + if (m == 10) { + m = 0; + lwsl_notice("doing lws_callback_on_writable_all_protocol\n"); + lws_callback_on_writable_all_protocol(context, &protocols[PROTOCOL_DUMB_INCREMENT]); + } + } } lwsl_err("Exiting\n");