blob: df866fd10e66b921a7b11d123217c7e14981f96f [file] [log] [blame]
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <net/http.h>
#include <misc/printk.h>
#include <net/nbuf.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 uint16_t http_strlen(const char *str)
{
if (str) {
return strlen(str);
}
return 0;
}
static int http_add_header(struct net_buf *tx, int32_t timeout, const char *str)
{
if (net_nbuf_append(tx, strlen(str), (uint8_t *)str, timeout)) {
return 0;
}
return -ENOMEM;
}
static int http_add_chunk(struct net_buf *tx, int32_t timeout, const char *str)
{
char chunk_header[16];
char *rn = "\r\n";
uint16_t str_len;
str_len = http_strlen(str);
snprintk(chunk_header, sizeof(chunk_header), "%x\r\n", str_len);
if (!net_nbuf_append(tx, strlen(chunk_header), chunk_header, timeout)) {
return -ENOMEM;
}
if (str_len > 0) {
if (!net_nbuf_append(tx, str_len, (uint8_t *)str, timeout)) {
return -ENOMEM;
}
}
if (!net_nbuf_append(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_buf *tx;
int rc = -EINVAL;
tx = net_nbuf_get_tx(ctx->net_ctx, ctx->timeout);
if (!tx) {
goto exit_routine;
}
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:
/* unref can handle NULL buffers, so we are covered */
net_nbuf_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);
}