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 */
|
/** From which net_context the request came from */
|
||||||
struct net_context *net_ctx;
|
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 */
|
/** HTTP parser */
|
||||||
struct http_parser parser;
|
struct http_parser parser;
|
||||||
|
|
||||||
|
@ -596,6 +603,9 @@ struct http_server_ctx {
|
||||||
|
|
||||||
/** URL's length */
|
/** URL's length */
|
||||||
u16_t url_len;
|
u16_t url_len;
|
||||||
|
|
||||||
|
/** Has the request timer been cancelled. */
|
||||||
|
u8_t timer_cancelled;
|
||||||
} req;
|
} req;
|
||||||
|
|
||||||
#if defined(CONFIG_HTTPS)
|
#if defined(CONFIG_HTTPS)
|
||||||
|
@ -833,6 +843,25 @@ int http_server_del_default(struct http_server_urls *urls);
|
||||||
/**
|
/**
|
||||||
* @brief Send HTTP response to client.
|
* @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 ctx HTTP context.
|
||||||
* @param http_header HTTP headers to send.
|
* @param http_header HTTP headers to send.
|
||||||
* @param html_payload HTML payload 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;
|
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,
|
static void pkt_sent(struct net_context *context,
|
||||||
int status,
|
int status,
|
||||||
void *token,
|
void *token,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
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. */
|
/* We can just close the context after the packet is sent. */
|
||||||
net_context_unref(context);
|
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,
|
int http_response_wait(struct http_server_ctx *ctx, const char *http_header,
|
||||||
const char *html_payload)
|
const char *html_payload, s32_t timeout)
|
||||||
{
|
{
|
||||||
struct net_pkt *pkt;
|
struct net_pkt *pkt;
|
||||||
int ret = -EINVAL;
|
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));
|
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) {
|
if (ret != 0) {
|
||||||
goto exit_routine;
|
goto exit_routine;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +202,12 @@ exit_routine:
|
||||||
return ret;
|
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)
|
int http_response_400(struct http_server_ctx *ctx, const char *html_payload)
|
||||||
{
|
{
|
||||||
return http_response(ctx, HTTP_STATUS_400_BR, 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);
|
NET_ASSERT(http_ctx);
|
||||||
|
|
||||||
|
req_timer_cancel(http_ctx);
|
||||||
|
|
||||||
old = http_ctx->enabled;
|
old = http_ctx->enabled;
|
||||||
|
|
||||||
http_ctx->enabled = false;
|
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->recv_cb = http_recv;
|
||||||
http_ctx->send_data = net_context_send;
|
http_ctx->send_data = net_context_send;
|
||||||
|
|
||||||
|
k_delayed_work_init(&http_ctx->req.timer, req_timeout);
|
||||||
|
|
||||||
parser_init(http_ctx);
|
parser_init(http_ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1509,6 +1559,8 @@ int https_server_init(struct http_server_ctx *ctx,
|
||||||
ctx->send_data = https_send;
|
ctx->send_data = https_send;
|
||||||
ctx->recv_cb = ssl_received;
|
ctx->recv_cb = ssl_received;
|
||||||
|
|
||||||
|
k_delayed_work_init(&ctx->req.timer, req_timeout);
|
||||||
|
|
||||||
parser_init(ctx);
|
parser_init(ctx);
|
||||||
|
|
||||||
/* Then mbedtls specific initialization */
|
/* Then mbedtls specific initialization */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue