libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 005d1f25b2a8b2db5bc81f7134f3ca9e75fafa06
parent 8140b9e73792afc38ac8b6b4b0bd1a55ef1561a7
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Sat, 25 Dec 2021 18:30:28 +0300

test_client_put_stop: ensure that some data will be received by MHD before closing

Simplified and unified code, improved readability.

Diffstat:
Msrc/microhttpd/test_client_put_stop.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 54 insertions(+), 12 deletions(-)

diff --git a/src/microhttpd/test_client_put_stop.c b/src/microhttpd/test_client_put_stop.c @@ -1376,6 +1376,7 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) int client_accepted; int full_req_recieved; int full_req_sent; + int some_data_recieved; di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD); if (NULL == di) @@ -1388,6 +1389,7 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) _MHD_dumbClient_start_connect (clnt); full_req_recieved = 0; + some_data_recieved = 0; start = time (NULL); do { @@ -1396,6 +1398,7 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) fd_set es; MHD_socket maxMhdSk; int num_ready; + int do_client; /**< Process data in client */ maxMhdSk = MHD_INVALID_SOCKET; FD_ZERO (&rs); @@ -1407,6 +1410,7 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) * processing any connections */ unsigned long long to; full_req_sent = 1; + do_client = 0; if (client_accepted && (MHD_YES != MHD_get_timeout (d, &to))) { ret = 0; @@ -1416,12 +1420,36 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) else { full_req_sent = _MHD_dumbClient_is_req_sent (clnt); - if ((! full_req_sent) || full_req_recieved || (0 == rate_limiter)) + if (! full_req_sent) + do_client = 1; /* Request hasn't been sent yet, send the data */ + else + { + /* All request data has been sent. + * Client will close the socket as the next step. */ + if (full_req_recieved) + do_client = 1; /* All data has been received by the MHD */ + else if ((0 == rate_limiter) && some_data_recieved) + { + /* No RST rate limiter, no need to avoid extra RST + * and at least something was received by the MHD */ + do_client = 1; + } + else + { + /* When rate limiter is enabled, all sent packets must be received + * before client close connection to avoid RST for every ACK. + * When rate limiter is not enabled, the MHD must receive at + * least something before closing the connection. */ + do_client = 0; + } + } + + if (do_client) _MHD_dumbClient_get_fdsets (clnt, &maxMhdSk, &rs, &ws, &es); } if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxMhdSk)) mhdErrorExitDesc ("MHD_get_fdset() failed"); - if ((! full_req_sent) || full_req_recieved || (0 == rate_limiter)) + if (do_client) { tv.tv_sec = 1; tv.tv_usec = 250 * 1000; @@ -1447,6 +1475,8 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) } if (0 == num_ready) { /* select() finished by timeout, looks like no more packets are pending */ + if (do_client) + externalErrorExitDesc ("Timeout waiting for sockets"); if (full_req_sent && (! full_req_recieved)) full_req_recieved = 1; } @@ -1454,21 +1484,33 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt) mhdErrorExitDesc ("MHD_run_from_select() failed"); if (! client_accepted) client_accepted = FD_ISSET (lstn_sk, &rs); - if (NULL != clnt) - { - /* Do not close the socket on client side until - * MHD is accepted and processed the socket. */ - if (! full_req_sent || (client_accepted && ! FD_ISSET (lstn_sk, &rs))) + else + { /* Client connection was already accepted by MHD */ + if (! some_data_recieved) { - if ((! full_req_sent) || full_req_recieved || (0 == rate_limiter)) + if (! do_client) { - /* When rate limiter is enabled, all sent packets must be received - * before client close connection to avoid RST for every ACK. */ - if (_MHD_dumbClient_process_from_fdsets (clnt, &rs, &ws, &es)) - clnt = NULL; + if (0 != num_ready) + { /* Connection was accepted before, "ready" socket means data */ + some_data_recieved = 1; + } + } + else + { + if (2 == num_ready) + some_data_recieved = 1; + else if ((1 == num_ready) && + ((MHD_INVALID_SOCKET == clnt->sckt) || + ! FD_ISSET (clnt->sckt, &ws))) + some_data_recieved = 1; } } } + if (do_client) + { + if (_MHD_dumbClient_process_from_fdsets (clnt, &rs, &ws, &es)) + clnt = NULL; + } /* Use double timeout value here so MHD would be able to catch timeout * internally */ } while (time (NULL) - start <= (TIMEOUTS_VAL * 2));