net: http: Add timeout to HTTP server response
Allow the caller to delay the closing of the HTTP connection for a number of milliseconds. The purpose for this is that the client can send still some data back to us for a short period of time. This is needed for example for Basic authentication so that server is able to receive authentication values back. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
5315ee3122
commit
31faeca511
2 changed files with 86 additions and 5 deletions
|
@ -567,6 +567,13 @@ struct http_server_ctx {
|
|||
/** From which net_context the request came from */
|
||||
struct net_context *net_ctx;
|
||||
|
||||
/** HTTP request timer. After sending a response to the
|
||||
* client, it is possible to wait for any request back via
|
||||
* the same socket. If no response is received, then this
|
||||
* timeout is activated and connection is tore down.
|
||||
*/
|
||||
struct k_delayed_work timer;
|
||||
|
||||
/** HTTP parser */
|
||||
struct http_parser parser;
|
||||
|
||||
|
@ -596,6 +603,9 @@ struct http_server_ctx {
|
|||
|
||||
/** URL's length */
|
||||
u16_t url_len;
|
||||
|
||||
/** Has the request timer been cancelled. */
|
||||
u8_t timer_cancelled;
|
||||
} req;
|
||||
|
||||
#if defined(CONFIG_HTTPS)
|
||||
|
@ -833,6 +843,25 @@ int http_server_del_default(struct http_server_urls *urls);
|
|||
/**
|
||||
* @brief Send HTTP response to client.
|
||||
*
|
||||
* @detail After sending a response, an optional timeout is started
|
||||
* which will wait for any new requests from the peer.
|
||||
*
|
||||
* @param ctx HTTP context.
|
||||
* @param http_header HTTP headers to send.
|
||||
* @param html_payload HTML payload to send.
|
||||
* @param timeout Timeout to wait until the connection is shutdown.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int http_response_wait(struct http_server_ctx *ctx, const char *http_header,
|
||||
const char *html_payload, s32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Send HTTP response to client.
|
||||
*
|
||||
* @detail The connection to peer is torn down right after the response
|
||||
* is sent.
|
||||
*
|
||||
* @param ctx HTTP context.
|
||||
* @param http_header HTTP headers to send.
|
||||
* @param html_payload HTML payload to send.
|
||||
|
|
|
@ -107,17 +107,57 @@ static int http_add_chunk(struct net_pkt *pkt, s32_t timeout, const char *str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void req_timer_cancel(struct http_server_ctx *ctx)
|
||||
{
|
||||
ctx->req.timer_cancelled = true;
|
||||
k_delayed_work_cancel(&ctx->req.timer);
|
||||
|
||||
NET_DBG("Context %p request timer cancelled", ctx);
|
||||
}
|
||||
|
||||
static void req_timeout(struct k_work *work)
|
||||
{
|
||||
struct http_server_ctx *ctx = CONTAINER_OF(work,
|
||||
struct http_server_ctx,
|
||||
req.timer);
|
||||
|
||||
if (ctx->req.timer_cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("Context %p request timeout", ctx);
|
||||
|
||||
net_context_unref(ctx->req.net_ctx);
|
||||
}
|
||||
|
||||
static void pkt_sent(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
/* We can just close the context after the packet is sent. */
|
||||
net_context_unref(context);
|
||||
s32_t timeout = POINTER_TO_INT(token);
|
||||
struct http_server_ctx *ctx = user_data;
|
||||
|
||||
req_timer_cancel(ctx);
|
||||
|
||||
if (timeout == K_NO_WAIT) {
|
||||
/* We can just close the context after the packet is sent. */
|
||||
net_context_unref(context);
|
||||
} else if (timeout > 0) {
|
||||
NET_DBG("Context %p starting timer", ctx);
|
||||
|
||||
k_delayed_work_submit(&ctx->req.timer, timeout);
|
||||
|
||||
ctx->req.timer_cancelled = false;
|
||||
}
|
||||
|
||||
/* Note that if the timeout is K_FOREVER, we do not close
|
||||
* the connection.
|
||||
*/
|
||||
}
|
||||
|
||||
int http_response(struct http_server_ctx *ctx, const char *http_header,
|
||||
const char *html_payload)
|
||||
int http_response_wait(struct http_server_ctx *ctx, const char *http_header,
|
||||
const char *html_payload, s32_t timeout)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
int ret = -EINVAL;
|
||||
|
@ -147,7 +187,7 @@ int http_response(struct http_server_ctx *ctx, const char *http_header,
|
|||
|
||||
net_pkt_set_appdatalen(pkt, net_buf_frags_len(pkt->frags));
|
||||
|
||||
ret = ctx->send_data(pkt, pkt_sent, 0, NULL, ctx);
|
||||
ret = ctx->send_data(pkt, pkt_sent, 0, INT_TO_POINTER(timeout), ctx);
|
||||
if (ret != 0) {
|
||||
goto exit_routine;
|
||||
}
|
||||
|
@ -162,6 +202,12 @@ exit_routine:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int http_response(struct http_server_ctx *ctx, const char *http_header,
|
||||
const char *html_payload)
|
||||
{
|
||||
return http_response_wait(ctx, http_header, html_payload, K_NO_WAIT);
|
||||
}
|
||||
|
||||
int http_response_400(struct http_server_ctx *ctx, const char *html_payload)
|
||||
{
|
||||
return http_response(ctx, HTTP_STATUS_400_BR, html_payload);
|
||||
|
@ -818,6 +864,8 @@ bool http_server_disable(struct http_server_ctx *http_ctx)
|
|||
|
||||
NET_ASSERT(http_ctx);
|
||||
|
||||
req_timer_cancel(http_ctx);
|
||||
|
||||
old = http_ctx->enabled;
|
||||
|
||||
http_ctx->enabled = false;
|
||||
|
@ -865,6 +913,8 @@ int http_server_init(struct http_server_ctx *http_ctx,
|
|||
http_ctx->recv_cb = http_recv;
|
||||
http_ctx->send_data = net_context_send;
|
||||
|
||||
k_delayed_work_init(&http_ctx->req.timer, req_timeout);
|
||||
|
||||
parser_init(http_ctx);
|
||||
|
||||
return 0;
|
||||
|
@ -1509,6 +1559,8 @@ int https_server_init(struct http_server_ctx *ctx,
|
|||
ctx->send_data = https_send;
|
||||
ctx->recv_cb = ssl_received;
|
||||
|
||||
k_delayed_work_init(&ctx->req.timer, req_timeout);
|
||||
|
||||
parser_init(ctx);
|
||||
|
||||
/* Then mbedtls specific initialization */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue