For stream-based protocols (TCP), adding less data than requested
("short write") is generally not a problem - the rest of data can
be sent in the next packet. So, make net_pkt_append() return length
of written data instead of just bool flag, which makes it closer
to the behavior of POSIX send()/write() calls.
There're many users of older net_pkt_append() in the codebase
however, so net_pkt_append_all() convenience function is added which
keeps returning a boolean flag. All current users were converted to
this function, except for two:
samples/net/http_server/src/ssl_utils.c
samples/net/mbedtls_sslclient/src/tcp.c
Both are related to TLS and implement mbedTLS "tx callback", which
follows POSIX short-write semantics. Both cases also had a code to
workaround previous boolean-only behavior of net_pkt_append() - after
calling it, they measured length of the actual data added (but only
in case of successful return of net_pkt_append(), so that didn't
really help). So, these 2 cases are already improved.
Jira: ZEP-1984
Change-Id: Ibaf7c029b15e91b516d73dab3612eed190ee982b
Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
128 lines
2.5 KiB
C
128 lines
2.5 KiB
C
/*
|
|
* Copyright (c) 2017 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <net/http.h>
|
|
#include <misc/printk.h>
|
|
#include <net/net_pkt.h>
|
|
#include <net/net_context.h>
|
|
|
|
#define HTTP_STATUS_200_OK "HTTP/1.1 200 OK\r\n" \
|
|
"Content-Type: text/html\r\n" \
|
|
"Transfer-Encoding: chunked\r\n" \
|
|
"\r\n"
|
|
|
|
#define HTTP_STATUS_400_BR "HTTP/1.1 400 Bad Request\r\n" \
|
|
"\r\n"
|
|
|
|
#define HTTP_STATUS_403_FBD "HTTP/1.1 403 Forbidden\r\n" \
|
|
"\r\n"
|
|
|
|
#define HTTP_STATUS_404_NF "HTTP/1.1 404 Not Found\r\n" \
|
|
"\r\n"
|
|
|
|
static inline u16_t http_strlen(const char *str)
|
|
{
|
|
if (str) {
|
|
return strlen(str);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int http_add_header(struct net_pkt *tx, s32_t timeout, const char *str)
|
|
{
|
|
if (net_pkt_append_all(tx, strlen(str), (u8_t *)str, timeout)) {
|
|
return 0;
|
|
}
|
|
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static int http_add_chunk(struct net_pkt *tx, s32_t timeout, const char *str)
|
|
{
|
|
char chunk_header[16];
|
|
char *rn = "\r\n";
|
|
u16_t str_len;
|
|
|
|
str_len = http_strlen(str);
|
|
|
|
snprintk(chunk_header, sizeof(chunk_header), "%x\r\n", str_len);
|
|
|
|
if (!net_pkt_append_all(tx, strlen(chunk_header), chunk_header,
|
|
timeout)) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (str_len > 0) {
|
|
if (!net_pkt_append_all(tx, str_len, (u8_t *)str, timeout)) {
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
if (!net_pkt_append_all(tx, strlen(rn), rn, timeout)) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int http_response(struct http_server_ctx *ctx, const char *http_header,
|
|
const char *html_payload)
|
|
{
|
|
struct net_pkt *tx;
|
|
int rc = -EINVAL;
|
|
|
|
tx = net_pkt_get_tx(ctx->net_ctx, ctx->timeout);
|
|
if (!tx) {
|
|
return rc;
|
|
}
|
|
|
|
rc = http_add_header(tx, ctx->timeout, http_header);
|
|
if (rc != 0) {
|
|
goto exit_routine;
|
|
}
|
|
|
|
if (html_payload) {
|
|
rc = http_add_chunk(tx, ctx->timeout, html_payload);
|
|
if (rc != 0) {
|
|
goto exit_routine;
|
|
}
|
|
|
|
/* like EOF */
|
|
rc = http_add_chunk(tx, ctx->timeout, NULL);
|
|
if (rc != 0) {
|
|
goto exit_routine;
|
|
}
|
|
}
|
|
|
|
rc = net_context_send(tx, NULL, 0, NULL, NULL);
|
|
if (rc != 0) {
|
|
goto exit_routine;
|
|
}
|
|
|
|
tx = NULL;
|
|
|
|
exit_routine:
|
|
net_pkt_unref(tx);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int http_response_400(struct http_server_ctx *ctx, const char *html_payload)
|
|
{
|
|
return http_response(ctx, HTTP_STATUS_400_BR, html_payload);
|
|
}
|
|
|
|
int http_response_403(struct http_server_ctx *ctx, const char *html_payload)
|
|
{
|
|
return http_response(ctx, HTTP_STATUS_403_FBD, html_payload);
|
|
}
|
|
|
|
int http_response_404(struct http_server_ctx *ctx, const char *html_payload)
|
|
{
|
|
return http_response(ctx, HTTP_STATUS_404_NF, html_payload);
|
|
}
|