Skip to content

Commit caa3779

Browse files
Michael ScottAnas Nashif
authored andcommitted
net: http: fix avoiding timeout on HTTP requests w/o body
The original commit 8ebaf29 ("net: http: dont timeout on HTTP requests w/o body") was intended to handle a case where an HTTP response had been retrieved from the server but the HTTP parser couldn't meet the criteria for calling "on_message_complete". For example, a POST to a REST API where the server doesn't return anything but an HTTP status code. It was a really bad idea to check a semaphore count. There is a lot of kernel logic built into semaphores and how the count is adjusted. The assumption that the value is 0 after the k_sem_give() is incorrect. It's STILL 0 if something is pending with a k_sem_take(). By the time k_sem_give() is done executing the other thread has now been kicked and the count is back to 0. This caused the original check to always pass and in turn breakage was noticed in the http_client sample. Let's do this the right way by setting a flag when on_message_complete is called and if that flag is not set by the time we reach recv_cb, let's give back the semaphore to avoid a timeout. Jira: ZEP-2561 Signed-off-by: Michael Scott <[email protected]>
1 parent 3d48ce8 commit caa3779

File tree

2 files changed

+7
-3
lines changed

2 files changed

+7
-3
lines changed

include/net/http.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ struct http_client_ctx {
324324

325325
u8_t cl_present:1;
326326
u8_t body_found:1;
327+
u8_t message_complete:1;
327328
} rsp;
328329

329330
#if defined(CONFIG_HTTPS)

subsys/net/lib/http/http_client.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ static int on_message_complete(struct http_parser *parser)
367367
ctx->req.user_data);
368368
}
369369

370+
ctx->rsp.message_complete = 1;
370371
k_sem_give(&ctx->req.wait);
371372

372373
return 0;
@@ -464,6 +465,7 @@ int client_reset(struct http_client_ctx *ctx)
464465
ctx->rsp.content_length = 0;
465466
ctx->rsp.processed = 0;
466467
ctx->rsp.body_found = 0;
468+
ctx->rsp.message_complete = 0;
467469
ctx->rsp.body_start = NULL;
468470

469471
memset(ctx->rsp.response_buf, 0, ctx->rsp.response_buf_len);
@@ -495,14 +497,15 @@ static void recv_cb(struct net_context *net_ctx, struct net_pkt *pkt,
495497
/*
496498
* This block most likely handles a TCP_FIN message.
497499
* (this means the connection is now closed)
498-
* If we get here, and req.wait.count is still 0 this means
499-
* http client is still waiting to parse a response body.
500+
* If we get here, and rsp.message_complete is still 0
501+
* this means the HTTP client is still waiting to parse a
502+
* response body.
500503
* This will will never happen now. Instead of generating
501504
* an ETIMEDOUT error in the future, let's unlock the
502505
* req.wait semaphore and let the app deal with whatever
503506
* data was parsed in the header (IE: http status, etc).
504507
*/
505-
if (ctx->req.wait.count == 0) {
508+
if (ctx->rsp.message_complete == 0) {
506509
k_sem_give(&ctx->req.wait);
507510
}
508511

0 commit comments

Comments
 (0)