LRS_DOING_TRANSACTION
diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c
index 8afd626..d3b16f4 100644
--- a/lib/roles/h1/ops-h1.c
+++ b/lib/roles/h1/ops-h1.c
@@ -308,9 +308,9 @@
lwsi_state(wsi) == LRS_ISSUING_FILE ||
lwsi_state(wsi) == LRS_HEADERS ||
lwsi_state(wsi) == LRS_BODY)) {
- if (!wsi->http.ah &&
- lws_header_table_attach(wsi, 0)) {
- lwsl_info("wsi %p: ah get fail\n", wsi);
+
+ if (!wsi->http.ah && lws_header_table_attach(wsi, 0)) {
+ lwsl_info("%s: wsi %p: ah not available\n", __func__, wsi);
goto try_pollout;
}
@@ -319,6 +319,9 @@
* regardless of our buflist state, we need to get it,
* and either use it, or append to the buflist and use
* buflist head material.
+ *
+ * We will not notice a connection close until the buflist is
+ * exhausted and we tried to do a read of some kind.
*/
buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
@@ -327,8 +330,20 @@
lwsl_info("%s: read 0 len a\n", __func__);
wsi->seen_zero_length_recv = 1;
lws_change_pollfd(wsi, LWS_POLLIN, 0);
- goto try_pollout;
- //goto fail;
+#if !defined(LWS_WITHOUT_EXTENSIONS)
+ /*
+ * autobahn requires us to win the race between close
+ * and draining the extensions
+ */
+ if (wsi->ws &&
+ (wsi->ws->rx_draining_ext || wsi->ws->tx_draining_ext))
+ goto try_pollout;
+#endif
+ /*
+ * normally, we respond to close with logically closing
+ * our side immediately
+ */
+ goto fail;
case LWS_SSL_CAPABLE_ERROR:
goto fail;
@@ -469,7 +484,8 @@
fail:
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "server socket svc fail");
+ lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
+ "server socket svc fail");
return LWS_HPI_RET_WSI_ALREADY_DIED;
}
diff --git a/lib/roles/http/server/parsers.c b/lib/roles/http/server/parsers.c
index 5754f90..054a839 100644
--- a/lib/roles/http/server/parsers.c
+++ b/lib/roles/http/server/parsers.c
@@ -81,6 +81,8 @@
ah->nfrag = 0;
ah->pos = 0;
ah->http_response = 0;
+ ah->parser_state = WSI_TOKEN_NAME_PART;
+ ah->lextable_pos = 0;
}
// doesn't scrub the ah rxbuffer by default, parent must do if needed
@@ -99,9 +101,6 @@
_lws_header_table_reset(ah);
- ah->parser_state = WSI_TOKEN_NAME_PART;
- ah->lextable_pos = 0;
-
/* since we will restart the ah, our new headers are not completed */
wsi->hdr_parsing_completed = 0;
@@ -353,7 +352,7 @@
if (!wsi) /* everybody waiting already has too many ah... */
goto nobody_usable_waiting;
- lwsl_info("%s: last eligible wsi in wait list %p\n", __func__, wsi);
+ lwsl_info("%s: transferring ah to last eligible wsi in wait list %p (wsistate 0x%x)\n", __func__, wsi, wsi->wsistate);
wsi->http.ah = ah;
ah->wsi = wsi; /* new owner */
diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c
index a308683..f55a137 100644
--- a/lib/roles/http/server/server.c
+++ b/lib/roles/http/server/server.c
@@ -330,8 +330,8 @@
vhost = context->vhost_list;
while (vhost) {
if (port == vhost->listen_port) {
- lwsl_info("vhost match to %s based on port %d\n",
- vhost->name, port);
+ lwsl_info("%s: vhost match to %s based on port %d\n",
+ __func__, vhost->name, port);
return vhost;
}
vhost = vhost->vhost_next;
@@ -991,6 +991,8 @@
if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
return 1;
+ lwsi_set_state(wsi, LRS_DOING_TRANSACTION);
+
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
wsi->user_space, uri_ptr, uri_len);
@@ -1547,7 +1549,7 @@
/* no upgrade ack... he remained as HTTP */
- lwsl_info("No upgrade\n");
+ lwsl_info("%s: %p: No upgrade\n", __func__, wsi);
lwsi_set_state(wsi, LRS_ESTABLISHED);
wsi->http.fop_fd = NULL;
@@ -1742,7 +1744,8 @@
* until we can verify POLLOUT. The part of this that confirms POLLOUT
* with no partials is in lws_server_socket_service() below.
*/
- lwsl_debug("%s: setting DEF_ACT from 0x%x\n", __func__, wsi->wsistate);
+ lwsl_debug("%s: %p: setting DEF_ACT from 0x%x\n", __func__,
+ wsi, wsi->wsistate);
lwsi_set_state(wsi, LRS_DEFERRING_ACTION);
wsi->http.tx_content_length = 0;
wsi->http.tx_content_remain = 0;
@@ -1770,7 +1773,8 @@
if (wsi->http.ah) {
// lws_buflist_describe(&wsi->buflist, wsi);
if (!lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
- lwsl_debug("%s: nothing in buflist so detaching ah\n", __func__);
+ lwsl_info("%s: %p: nothing in buflist so detaching ah\n",
+ __func__, wsi);
lws_header_table_detach(wsi, 1);
#ifdef LWS_WITH_TLS
/*
@@ -1789,8 +1793,8 @@
}
#endif
} else {
- lwsl_debug("%s: resetting and keeping ah as pipeline\n",
- __func__);
+ lwsl_info("%s: %p: resetting and keeping ah as pipeline\n",
+ __func__, wsi);
lws_header_table_reset(wsi, 0);
/*
* If we kept the ah, we should restrict the amount
diff --git a/lib/roles/private.h b/lib/roles/private.h
index 4e0b312..ae4278b 100644
--- a/lib/roles/private.h
+++ b/lib/roles/private.h
@@ -122,18 +122,27 @@
LRS_HEADERS = 21,
LRS_BODY = 22,
LRS_ESTABLISHED = LWSIFS_POCB | 23,
+ /* we are established, but we have embarked on serving a single
+ * transaction. Other transaction input may be pending, but we will
+ * not service it while we are busy dealing with the current
+ * transaction.
+ *
+ * When we complete the current transaction, we would reset our state
+ * back to ESTABLISHED and start to process the next transaction.
+ */
+ LRS_DOING_TRANSACTION = LWSIFS_POCB | 24,
/* Phase 6: finishing */
- LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 24,
- LRS_RETURNED_CLOSE = LWSIFS_POCB | 25,
- LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 26,
- LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 27,
- LRS_SHUTDOWN = 28,
+ LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 25,
+ LRS_RETURNED_CLOSE = LWSIFS_POCB | 26,
+ LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 27,
+ LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 28,
+ LRS_SHUTDOWN = 29,
/* Phase 7: dead */
- LRS_DEAD_SOCKET = 29,
+ LRS_DEAD_SOCKET = 30,
LRS_MASK = 0xffff
};
diff --git a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c
index 2b7fa4c..b7bdaac 100644
--- a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c
+++ b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c
@@ -177,6 +177,10 @@
info.protocols = protocols;
info.mounts = &mount;
+ /* for testing ah queue, not useful in real world */
+ if (lws_cmdline_option(argc, argv, "--ah1"))
+ info.max_http_header_pool = 1;
+
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws init failed\n");
diff --git a/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c b/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c
index faffaa5..5bdf1be 100644
--- a/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c
+++ b/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c
@@ -31,6 +31,7 @@
static uint8_t buf[LWS_PRE + 4096];
static int waiting, interrupted;
static struct lws_context *context;
+static int us_wait_after_input_close = LWS_USEC_PER_SEC / 10;
static int
callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
@@ -50,7 +51,7 @@
/* stdin close, wait 1s then close the raw skt */
stdin_wsi = NULL; /* invalid now we close */
if (raw_wsi)
- lws_set_timer_usecs(raw_wsi, LWS_USEC_PER_SEC / 10);
+ lws_set_timer_usecs(raw_wsi, us_wait_after_input_close);
else {
interrupted = 1;
lws_cancel_service(context);
@@ -153,7 +154,7 @@
logs = atoi(p);
lws_set_log_level(logs, NULL);
- lwsl_user("LWS minimal raw netcat [--server ip] [--port port]\n");
+ lwsl_user("LWS minimal raw netcat [--server ip] [--port port] [-w ms]\n");
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
@@ -193,6 +194,9 @@
if ((p = lws_cmdline_option(argc, argv, "--server")))
server = p;
+ if ((p = lws_cmdline_option(argc, argv, "-w")))
+ us_wait_after_input_close = 1000 * atoi(p);
+
n = getaddrinfo(server, port, &h, &r);
if (n) {
lwsl_err("%s: problem resolving %s: %s\n", __func__,