From e3d141dae9a816880bf826b710b1e9a36aaf1aa2 Mon Sep 17 00:00:00 2001
From: Andy Green <andy.green@linaro.org>
Date: Sat, 27 Feb 2016 11:42:22 +0800
Subject: [PATCH] adopt readbuf do service
Signed-off-by: Andy Green <andy.green@linaro.org>
---
lib/client-handshake.c | 6 ++---
lib/client.c | 2 +-
lib/libuv.c | 8 ++++---
lib/libwebsockets.c | 2 +-
lib/parsers.c | 29 +++++++++++++++++++-----
lib/private-libwebsockets.h | 6 ++---
lib/server.c | 44 ++++++++++++++++++++++++++++---------
lib/service.c | 5 ++++-
8 files changed, 74 insertions(+), 28 deletions(-)
diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index 96854afe..264cca98 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -303,7 +303,7 @@ lws_client_connect_2(struct lws *wsi)
oom4:
/* we're closing, losing some rx is OK */
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 0);
lws_free(wsi);
return NULL;
@@ -405,7 +405,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
}
#endif
- if (lws_header_table_attach(wsi))
+ if (lws_header_table_attach(wsi, 0))
goto bail;
/*
@@ -470,7 +470,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
bail1:
/* we're closing, losing some rx is OK */
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 0);
bail:
lws_free(wsi);
diff --git a/lib/client.c b/lib/client.c
index 33d990e4..94497e94 100644
--- a/lib/client.c
+++ b/lib/client.c
@@ -798,7 +798,7 @@ check_accept:
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
/* free up his parsing allocations */
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 0);
lws_union_transition(wsi, LWSCM_WS_CLIENT);
wsi->state = LWSS_ESTABLISHED;
diff --git a/lib/libuv.c b/lib/libuv.c
index ac1ab6de..5400f315 100644
--- a/lib/libuv.c
+++ b/lib/libuv.c
@@ -80,7 +80,7 @@ lws_uv_timeout_cb(uv_timer_t *timer)
struct lws_context_per_thread *pt = container_of(timer,
struct lws_context_per_thread, uv_timeout_watcher);
- lwsl_info("%s\n", __func__);
+ lwsl_debug("%s\n", __func__);
/* do timeout check only */
lws_service_fd_tsi(pt->context, NULL, pt->tid);
}
@@ -119,8 +119,10 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, uv_signal_cb cb,
*/
if (wsi) {
wsi->w_read.context = context;
- uv_poll_init(pt->io_loop_uv, &wsi->w_read.uv_watcher, pt->lserv_fd);
- uv_poll_start(&wsi->w_read.uv_watcher, UV_READABLE, lws_accept_cb);
+ uv_poll_init(pt->io_loop_uv, &wsi->w_read.uv_watcher,
+ pt->lserv_fd);
+ uv_poll_start(&wsi->w_read.uv_watcher, UV_READABLE,
+ lws_accept_cb);
}
uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 00217f76..257d6b41 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -63,7 +63,7 @@ lws_free_wsi(struct lws *wsi)
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
/* we may not have an ah, but may be on the waiting list... */
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 0);
wsi->context->count_wsi_allocated--;
lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi,
diff --git a/lib/parsers.c b/lib/parsers.c
index e802e8ce..cb025414 100644
--- a/lib/parsers.c
+++ b/lib/parsers.c
@@ -61,9 +61,11 @@ lextable_decode(int pos, char c)
}
void
-lws_header_table_reset(struct lws *wsi)
+lws_header_table_reset(struct lws *wsi, int autoservice)
{
struct allocated_headers *ah = wsi->u.hdr.ah;
+ struct lws_context_per_thread *pt;
+ struct lws_pollfd *pfd;
/* if we have the idea we're resetting 'our' ah, must be bound to one */
assert(ah);
@@ -87,14 +89,29 @@ lws_header_table_reset(struct lws *wsi)
* processing), apply and free it.
*/
if (wsi->u.hdr.preamble_rx) {
- memcpy(ah->rx, wsi->u.hdr.preamble_rx, wsi->u.hdr.preamble_rx_len);
+ memcpy(ah->rx, wsi->u.hdr.preamble_rx,
+ wsi->u.hdr.preamble_rx_len);
ah->rxlen = wsi->u.hdr.preamble_rx_len;
lws_free_set_NULL(wsi->u.hdr.preamble_rx);
+
+ if (autoservice) {
+ lwsl_notice("%s: calling service on readbuf ah\n", __func__);
+
+ pt = &wsi->context->pt[(int)wsi->tsi];
+
+ /* unlike a normal connect, we have the headers already
+ * (or the first part of them anyway)
+ */
+ pfd = &pt->fds[wsi->position_in_fds_table];
+ pfd->revents |= LWS_POLLIN;
+ lwsl_err("%s: calling service\n", __func__);
+ lws_service_fd_tsi(wsi->context, pfd, wsi->tsi);
+ }
}
}
int LWS_WARN_UNUSED_RESULT
-lws_header_table_attach(struct lws *wsi)
+lws_header_table_attach(struct lws *wsi, int autoservice)
{
struct lws_context *context = wsi->context;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@@ -165,7 +182,7 @@ lws_header_table_attach(struct lws *wsi)
lws_pt_unlock(pt);
reset:
- lws_header_table_reset(wsi);
+ lws_header_table_reset(wsi, autoservice);
time(&wsi->u.hdr.ah->assigned);
return 0;
@@ -176,7 +193,7 @@ bail:
return 1;
}
-int lws_header_table_detach(struct lws *wsi)
+int lws_header_table_detach(struct lws *wsi, int autoservice)
{
struct lws_context *context = wsi->context;
struct allocated_headers *ah = wsi->u.hdr.ah;
@@ -258,7 +275,7 @@ int lws_header_table_detach(struct lws *wsi)
wsi->u.hdr.ah = ah;
ah->wsi = wsi; /* new owner */
- lws_header_table_reset(wsi);
+ lws_header_table_reset(wsi, autoservice);
time(&wsi->u.hdr.ah->assigned);
assert(wsi->position_in_fds_table != -1);
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 5dd48178..d7a9389c 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1296,13 +1296,13 @@ LWS_EXTERN int
lws_plat_set_socket_options(struct lws_context *context, lws_sockfd_type fd);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_header_table_attach(struct lws *wsi);
+lws_header_table_attach(struct lws *wsi, int autoservice);
LWS_EXTERN int
-lws_header_table_detach(struct lws *wsi);
+lws_header_table_detach(struct lws *wsi, int autoservice);
LWS_EXTERN void
-lws_header_table_reset(struct lws *wsi);
+lws_header_table_reset(struct lws *wsi, int autoservice);
LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h);
diff --git a/lib/server.c b/lib/server.c
index bd57ad2e..eeb0b0d3 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -330,7 +330,7 @@ lws_http_action(struct lws *wsi)
bail_nuke_ah:
/* we're closing, losing some rx is OK */
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 1);
return 1;
}
@@ -628,7 +628,7 @@ bail_nuke_ah:
/* drop the header info */
/* we're closing, losing some rx is OK */
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 1);
return 1;
}
@@ -753,9 +753,9 @@ lws_http_transaction_completed(struct lws *wsi)
if (!wsi->more_rx_waiting) {
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 1);
} else
- lws_header_table_reset(wsi);
+ lws_header_table_reset(wsi, 1);
}
/* If we're (re)starting on headers, need other implied init */
@@ -861,7 +861,9 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
const char *readbuf, size_t len)
{
struct lws *wsi = lws_adopt_socket(context, accept_fd);
+ struct lws_context_per_thread *pt;
struct allocated_headers *ah;
+ struct lws_pollfd *pfd;
if (!wsi)
return NULL;
@@ -878,24 +880,42 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
*
* if one is available, get it and place the data in his ah rxbuf...
* wsi with ah that have pending rxbuf get auto-POLLIN service.
+ *
+ * no autoservice because we didn't get a chance to attach the
+ * readbuf data to wsi or ah yet, and we will do it next if we get
+ * the ah.
*/
- if (!lws_header_table_attach(wsi)) {
+ if (!lws_header_table_attach(wsi, 0)) {
ah = wsi->u.hdr.ah;
memcpy(ah->rx, readbuf, len);
ah->rxpos = 0;
ah->rxlen = len;
+ lwsl_notice("%s: calling service on readbuf ah\n", __func__);
+ pt = &context->pt[(int)wsi->tsi];
+
+ /* unlike a normal connect, we have the headers already
+ * (or the first part of them anyway).
+ * libuv won't come back and service us without a network
+ * event, so we need to do the header service right here.
+ */
+ pfd = &pt->fds[wsi->position_in_fds_table];
+ pfd->revents |= LWS_POLLIN;
+ lwsl_err("%s: calling service\n", __func__);
+ if (lws_service_fd_tsi(context, pfd, wsi->tsi))
+ /* service closed us */
+ return NULL;
+
return wsi;
}
-
+ lwsl_err("%s: deferring handling ah\n", __func__);
/*
* hum if no ah came, we are on the wait list and must defer
* dealing with this until the ah arrives.
*
* later successful lws_header_table_attach() will apply the
- * below to the rx buffer.
+ * below to the rx buffer (via lws_header_table_reset()).
*/
-
wsi->u.hdr.preamble_rx = lws_malloc(len);
memcpy(wsi->u.hdr.preamble_rx, readbuf, len);
wsi->u.hdr.preamble_rx_len = len;
@@ -958,7 +978,8 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
wsi->state == LWSS_HTTP_ISSUING_FILE ||
wsi->state == LWSS_HTTP_HEADERS) {
if (!wsi->u.hdr.ah)
- if (lws_header_table_attach(wsi))
+ /* no autoservice beacuse we will do it next */
+ if (lws_header_table_attach(wsi, 0))
goto try_pollout;
ah = wsi->u.hdr.ah;
@@ -1002,7 +1023,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
(wsi->mode != LWSCM_HTTP_SERVING &&
wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED &&
wsi->mode != LWSCM_HTTP2_SERVING))
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 1);
}
break;
}
@@ -1052,6 +1073,9 @@ try_pollout:
goto fail;
}
+ if (!wsi->hdr_parsing_completed)
+ break;
+
if (wsi->state != LWSS_HTTP_ISSUING_FILE) {
n = user_callback_handle_rxflow(wsi->protocol->callback,
wsi, LWS_CALLBACK_HTTP_WRITEABLE,
diff --git a/lib/service.c b/lib/service.c
index 6ebd562d..c665f117 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -237,6 +237,9 @@ user_service:
return 1;
}
+ if (!wsi->hdr_parsing_completed)
+ return 0;
+
#ifdef LWS_USE_HTTP2
/*
* we are the 'network wsi' for potentially many muxed child wsi with
@@ -789,7 +792,7 @@ drain:
/* we can run the normal ah detach flow despite
* being in ws union mode, since all union members
* start with hdr */
- lws_header_table_detach(wsi);
+ lws_header_table_detach(wsi, 0);
}
pending = lws_ssl_pending(wsi);
--
GitLab