net: http: Remove HTTP client and server APIs

The old legacy APIs use net-app library and as that is being
removed, then the dependencies need to be removed also.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2019-01-24 12:50:14 +02:00 committed by Anas Nashif
commit 4043909d69
31 changed files with 0 additions and 5166 deletions

View file

@ -6,11 +6,3 @@ endif()
zephyr_library_sources_if_kconfig(http_parser.c)
zephyr_library_sources_if_kconfig(http_parser_url.c)
zephyr_library_sources_if_kconfig(http.c)
zephyr_library_sources_ifdef(CONFIG_HTTP_SERVER http_server.c)
zephyr_library_sources_ifdef(CONFIG_HTTP_CLIENT http_client.c)
zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS)
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)

View file

@ -3,84 +3,6 @@
# SPDX-License-Identifier: Apache-2.0
#
config HTTP
bool "HTTP support"
help
This option enables the HTTP library
if HTTP
config HTTP_SERVER
bool "HTTP server support"
select HTTP_PARSER
select HTTP_PARSER_URL
select NET_APP_SERVER
help
Enables HTTP server routines.
config HTTP_CLIENT
bool "HTTP client support"
select HTTP_PARSER
select HTTP_PARSER_URL
select NET_APP_CLIENT
help
Enables HTTP client routines.
config HTTP_HEADERS
int "HTTP header field max number of items"
depends on HTTP_SERVER
default 20 if WEBSOCKET
default 8
help
Number of HTTP header field items that an HTTP server
application will handle. If websocket is enabled, then the
default needs to be much bigger.
config HTTPS
bool "HTTPS support"
select NET_APP_TLS
help
Enables HTTPS support.
config HTTP_SERVER_CONNECTIONS
int "Max number of concurrent HTTP server connections"
default NET_APP_SERVER_NUM_CONN
depends on HTTP_SERVER
help
This value determines how many simultaneous HTTP connections the
HTTP server can serve. Note that only 1 HTTPS connection can be
served at a time, so set CONFIG_NET_APP_SERVER_NUM_CONN and
CONFIG_NET_TCP_BACKLOG_SIZE to 1 in that case.
config HTTP_SERVER_NUM_URLS
int "Max number of URLs that the HTTP server will handle"
default 8
depends on HTTP_SERVER
help
This value determines how many URLs this HTTP server can handle.
config HTTP_CLIENT_NETWORK_TIMEOUT
int "Default network activity timeout in seconds"
default 20
depends on HTTP_CLIENT
help
Default network activity timeout in seconds. This setting is used
for TCP connection timeout.
module = HTTP
module-dep = NET_LOG
module-str = Log level for HTTP
module-help = Enables routing engine debug messages.
source "subsys/net/Kconfig.template.log_config.net"
config NET_DEBUG_HTTP_CONN
bool "Debug HTTP connections"
depends on HTTP && NET_LOG
help
Enables HTTP connection tracking.
endif # HTTP
config HTTP_PARSER
bool "HTTP Parser support"
select HTTP_PARSER_URL

View file

@ -1,290 +0,0 @@
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_REGISTER(net_http, CONFIG_HTTP_LOG_LEVEL);
#include <zephyr.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#include <version.h>
#include <misc/printk.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/http.h>
int http_set_cb(struct http_ctx *ctx,
http_connect_cb_t connect_cb,
http_recv_cb_t recv_cb,
http_send_cb_t send_cb,
http_close_cb_t close_cb)
{
if (!ctx) {
return -EINVAL;
}
if (!ctx->is_init) {
return -ENOENT;
}
ctx->cb.connect = connect_cb;
ctx->cb.recv = recv_cb;
ctx->cb.send = send_cb;
ctx->cb.close = close_cb;
return 0;
}
int http_close(struct http_ctx *ctx)
{
if (!ctx) {
return -EINVAL;
}
if (!ctx->is_init) {
return -ENOENT;
}
http_send_flush(ctx, NULL);
if (ctx->pending) {
net_pkt_unref(ctx->pending);
ctx->pending = NULL;
}
#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_NET_DEBUG_HTTP_CONN)
if (!ctx->is_client) {
http_server_conn_del(ctx);
}
#endif
#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_WEBSOCKET)
if (ctx->websocket.pending) {
net_pkt_unref(ctx->websocket.pending);
ctx->websocket.pending = NULL;
}
ctx->websocket.data_waiting = 0;
#endif
return net_app_close(&ctx->app_ctx);
}
int http_release(struct http_ctx *ctx)
{
if (!ctx) {
return -EINVAL;
}
if (!ctx->is_init) {
return -ENOENT;
}
ctx->is_tls = false;
#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_NET_DEBUG_HTTP_CONN)
if (!ctx->is_client) {
http_server_conn_del(ctx);
http_server_disable(ctx);
}
#endif
if (ctx->pending) {
net_pkt_unref(ctx->pending);
ctx->pending = NULL;
}
ctx->is_init = false;
return net_app_release(&ctx->app_ctx);
}
int http_send_msg_raw(struct http_ctx *ctx, struct net_pkt *pkt,
void *user_send_data)
{
int ret;
NET_DBG("[%p] Sending %zd bytes data", ctx, net_pkt_get_len(pkt));
ret = net_app_send_pkt(&ctx->app_ctx, pkt, NULL, 0, 0,
user_send_data);
if (!ret) {
/* We must let the system to send the packet, otherwise TCP
* might timeout before the packet is actually sent. This is
* easily seen if the application calls this functions many
* times in a row.
*/
k_yield();
}
return ret;
}
static inline struct net_pkt *get_net_pkt(struct http_ctx *ctx,
const struct sockaddr *dst)
{
if (!dst) {
return net_app_get_net_pkt(&ctx->app_ctx, AF_UNSPEC,
ctx->timeout);
}
return net_app_get_net_pkt_with_dst(&ctx->app_ctx, dst, ctx->timeout);
}
int http_prepare_and_send(struct http_ctx *ctx,
const char *payload,
size_t payload_len,
const struct sockaddr *dst,
void *user_send_data)
{
size_t added;
int ret;
do {
if (!ctx->pending) {
ctx->pending = get_net_pkt(ctx, dst);
if (!ctx->pending) {
return -ENOMEM;
}
}
ret = net_pkt_append(ctx->pending, payload_len, payload,
ctx->timeout);
if (!ret || ret > payload_len) {
ret = -EINVAL;
goto error;
}
added = ret;
payload_len -= added;
if (payload_len) {
payload += added;
/* Not all data could be added, send what we have now
* and allocate new stuff to be sent.
*/
ret = http_send_flush(ctx, user_send_data);
if (ret < 0) {
goto error;
}
}
} while (payload_len);
return 0;
error:
if (ctx->pending) {
net_pkt_unref(ctx->pending);
ctx->pending = NULL;
}
return ret;
}
int http_send_flush(struct http_ctx *ctx, void *user_send_data)
{
int ret;
if (!ctx->pending) {
return 0;
}
ret = http_send_msg_raw(ctx, ctx->pending, user_send_data);
if (ret < 0) {
return ret;
}
ctx->pending = NULL;
return ret;
}
int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
const struct sockaddr *dst, void *user_send_data)
{
char chunk_header[16];
int ret;
if (!buf) {
len = 0;
}
snprintk(chunk_header, sizeof(chunk_header), "%x" HTTP_CRLF,
(unsigned int)len);
ret = http_prepare_and_send(ctx, chunk_header, strlen(chunk_header),
dst, user_send_data);
if (ret < 0) {
return ret;
}
if (len) {
ret = http_prepare_and_send(ctx, buf, len, dst, user_send_data);
if (ret < 0) {
return ret;
}
}
ret = http_prepare_and_send(ctx, HTTP_CRLF, sizeof(HTTP_CRLF) - 1, dst,
user_send_data);
if (ret < 0) {
return ret;
}
return 0;
}
static int _http_add_header(struct http_ctx *ctx, s32_t timeout,
const char *name, const char *value,
const struct sockaddr *dst,
void *user_send_data)
{
int ret;
ret = http_prepare_and_send(ctx, name, strlen(name), dst,
user_send_data);
if (value && ret >= 0) {
ret = http_prepare_and_send(ctx, ": ", strlen(": "), dst,
user_send_data);
if (ret < 0) {
goto out;
}
ret = http_prepare_and_send(ctx, value, strlen(value), dst,
user_send_data);
if (ret < 0) {
goto out;
}
ret = http_prepare_and_send(ctx, HTTP_CRLF, strlen(HTTP_CRLF),
dst, user_send_data);
if (ret < 0) {
goto out;
}
}
out:
return ret;
}
int http_add_header(struct http_ctx *ctx, const char *field,
const struct sockaddr *dst,
void *user_send_data)
{
return _http_add_header(ctx, ctx->timeout, field, NULL, dst,
user_send_data);
}
int http_add_header_field(struct http_ctx *ctx, const char *name,
const char *value,
const struct sockaddr *dst,
void *user_send_data)
{
return _http_add_header(ctx, ctx->timeout, name, value, dst,
user_send_data);
}

View file

@ -1,739 +0,0 @@
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_DECLARE(net_http, CONFIG_HTTP_LOG_LEVEL);
#include <zephyr.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#include <version.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/http.h>
#include "../../ip/net_private.h"
#define BUF_ALLOC_TIMEOUT 100
#define RC_STR(rc) (rc == 0 ? "OK" : "ERROR")
#define HTTP_EOF "\r\n\r\n"
#define HTTP_HOST "Host"
#define HTTP_CONTENT_TYPE "Content-Type"
#define HTTP_CONTENT_LEN "Content-Length"
#define HTTP_CONT_LEN_SIZE 6
/* Default network activity timeout in seconds */
#define HTTP_NETWORK_TIMEOUT K_SECONDS(CONFIG_HTTP_CLIENT_NETWORK_TIMEOUT)
int client_reset(struct http_ctx *ctx)
{
http_parser_init(&ctx->http.parser, HTTP_RESPONSE);
(void)memset(ctx->http.rsp.http_status, 0,
sizeof(ctx->http.rsp.http_status));
ctx->http.rsp.cl_present = 0;
ctx->http.rsp.content_length = 0;
ctx->http.rsp.processed = 0;
ctx->http.rsp.body_found = 0;
ctx->http.rsp.message_complete = 0;
ctx->http.rsp.body_start = NULL;
(void)memset(ctx->http.rsp.response_buf, 0,
ctx->http.rsp.response_buf_len);
ctx->http.rsp.data_len = 0;
return 0;
}
int http_request(struct http_ctx *ctx, struct http_request *req, s32_t timeout,
void *user_data)
{
const char *method = http_method_str(req->method);
int ret;
if (ctx->pending) {
net_pkt_unref(ctx->pending);
ctx->pending = NULL;
}
ret = http_add_header(ctx, method, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, " ", NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, req->url, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, req->protocol, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, HTTP_CRLF, NULL, user_data);
if (ret < 0) {
goto out;
}
if (req->host) {
ret = http_add_header_field(ctx, HTTP_HOST, req->host,
NULL, user_data);
if (ret < 0) {
goto out;
}
}
if (req->header_fields) {
ret = http_add_header(ctx, req->header_fields, NULL, user_data);
if (ret < 0) {
goto out;
}
}
if (req->content_type_value) {
ret = http_add_header_field(ctx, HTTP_CONTENT_TYPE,
req->content_type_value,
NULL, user_data);
if (ret < 0) {
goto out;
}
}
if (req->payload && req->payload_size) {
char content_len_str[HTTP_CONT_LEN_SIZE];
ret = snprintk(content_len_str, HTTP_CONT_LEN_SIZE,
"%u", req->payload_size);
if (ret <= 0 || ret >= HTTP_CONT_LEN_SIZE) {
ret = -ENOMEM;
goto out;
}
ret = http_add_header_field(ctx, HTTP_CONTENT_LEN,
content_len_str,
NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, HTTP_CRLF, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_prepare_and_send(ctx, req->payload,
req->payload_size,
NULL, user_data);
if (ret < 0) {
goto out;
}
} else {
ret = http_add_header(ctx, HTTP_EOF, NULL, user_data);
if (ret < 0) {
goto out;
}
}
http_send_flush(ctx, user_data);
out:
if (ctx->pending) {
net_pkt_unref(ctx->pending);
ctx->pending = NULL;
}
return ret;
}
static void sprint_addr(char *buf, int len,
sa_family_t family,
struct sockaddr *addr)
{
if (family == AF_INET6) {
net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr, buf, len);
} else if (family == AF_INET) {
net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr, buf, len);
} else {
NET_DBG("Invalid protocol family");
}
}
static inline void print_info(struct http_ctx *ctx,
enum http_method method)
{
if (CONFIG_HTTP_LOG_LEVEL >= LOG_LEVEL_INF) {
char local[NET_IPV6_ADDR_LEN];
char remote[NET_IPV6_ADDR_LEN];
sprint_addr(local, NET_IPV6_ADDR_LEN,
ctx->app_ctx.default_ctx->local.sa_family,
&ctx->app_ctx.default_ctx->local);
sprint_addr(remote, NET_IPV6_ADDR_LEN,
ctx->app_ctx.default_ctx->remote.sa_family,
&ctx->app_ctx.default_ctx->remote);
NET_DBG("HTTP %s (%s) %s -> %s port %d",
http_method_str(method),
log_strdup(ctx->http.req.host), log_strdup(local),
log_strdup(remote),
ntohs(net_sin(&ctx->app_ctx.default_ctx->remote)->
sin_port));
}
}
int http_client_send_req(struct http_ctx *ctx,
struct http_request *req,
http_response_cb_t cb,
u8_t *response_buf,
size_t response_buf_len,
void *user_data,
s32_t timeout)
{
int ret;
if (!response_buf || response_buf_len == 0) {
return -EINVAL;
}
ctx->http.rsp.response_buf = response_buf;
ctx->http.rsp.response_buf_len = response_buf_len;
client_reset(ctx);
if (!req->host) {
req->host = ctx->server;
}
ctx->http.req.host = req->host;
ctx->http.req.method = req->method;
ctx->http.req.user_data = user_data;
ctx->http.rsp.cb = cb;
ret = net_app_connect(&ctx->app_ctx, HTTP_NETWORK_TIMEOUT);
if (ret < 0) {
NET_DBG("Cannot connect to server (%d)", ret);
return ret;
}
/* We might wait longer than timeout if the first connection
* establishment takes long time (like with HTTPS)
*/
if (k_sem_take(&ctx->http.connect_wait, HTTP_NETWORK_TIMEOUT)) {
NET_DBG("Connection timed out");
ret = -ETIMEDOUT;
goto out;
}
print_info(ctx, ctx->http.req.method);
ret = http_request(ctx, req, timeout, user_data);
if (ret < 0) {
NET_DBG("Send error (%d)", ret);
goto out;
}
if (timeout != 0 && k_sem_take(&ctx->http.req.wait, timeout)) {
ret = -ETIMEDOUT;
goto out;
}
if (timeout == 0) {
return -EINPROGRESS;
}
return 0;
out:
return ret;
}
static void print_header_field(size_t len, const char *str)
{
if (CONFIG_HTTP_LOG_LEVEL >= LOG_LEVEL_INF) {
#define MAX_OUTPUT_LEN 128
char output[MAX_OUTPUT_LEN];
/* The value of len does not count \0 so we need to increase it
* by one.
*/
if ((len + 1) > sizeof(output)) {
len = sizeof(output) - 1;
}
snprintk(output, len + 1, "%s", str);
NET_DBG("[%zd] %s", len, log_strdup(output));
}
}
static int on_url(struct http_parser *parser, const char *at, size_t length)
{
ARG_UNUSED(parser);
print_header_field(length, at);
return 0;
}
static int on_status(struct http_parser *parser, const char *at, size_t length)
{
u16_t len;
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
len = min(length, sizeof(ctx->http.rsp.http_status) - 1);
memcpy(ctx->http.rsp.http_status, at, len);
ctx->http.rsp.http_status[len] = 0;
NET_DBG("HTTP response status %s",
log_strdup(ctx->http.rsp.http_status));
return 0;
}
static int on_header_field(struct http_parser *parser, const char *at,
size_t length)
{
const char *content_len = HTTP_CONTENT_LEN;
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
u16_t len;
len = strlen(content_len);
if (length >= len && memcmp(at, content_len, len) == 0) {
ctx->http.rsp.cl_present = true;
}
print_header_field(length, at);
return 0;
}
#define MAX_NUM_DIGITS 16
static int on_header_value(struct http_parser *parser, const char *at,
size_t length)
{
char str[MAX_NUM_DIGITS];
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
if (ctx->http.rsp.cl_present) {
if (length <= MAX_NUM_DIGITS - 1) {
long int num;
memcpy(str, at, length);
str[length] = 0;
num = strtol(str, NULL, 10);
if (num == LONG_MIN || num == LONG_MAX) {
return -EINVAL;
}
ctx->http.rsp.content_length = num;
}
ctx->http.rsp.cl_present = false;
}
print_header_field(length, at);
return 0;
}
static int on_body(struct http_parser *parser, const char *at, size_t length)
{
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
ctx->http.rsp.body_found = 1;
ctx->http.rsp.processed += length;
NET_DBG("Processed %zd length %zd", ctx->http.rsp.processed, length);
if (!ctx->http.rsp.body_start &&
(u8_t *)at != (u8_t *)ctx->http.rsp.response_buf) {
ctx->http.rsp.body_start = (u8_t *)at;
}
if (ctx->http.rsp.cb) {
NET_DBG("Calling callback for partitioned %zd len data",
ctx->http.rsp.data_len);
ctx->http.rsp.cb(ctx,
ctx->http.rsp.response_buf,
ctx->http.rsp.response_buf_len,
ctx->http.rsp.data_len,
HTTP_DATA_MORE,
ctx->http.req.user_data);
/* Re-use the result buffer and start to fill it again */
ctx->http.rsp.data_len = 0;
ctx->http.rsp.body_start = NULL;
}
return 0;
}
static int on_headers_complete(struct http_parser *parser)
{
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
if (parser->status_code >= 500 && parser->status_code < 600) {
NET_DBG("Status %d, skipping body", parser->status_code);
return 1;
}
if ((ctx->http.req.method == HTTP_HEAD ||
ctx->http.req.method == HTTP_OPTIONS)
&& ctx->http.rsp.content_length > 0) {
NET_DBG("No body expected");
return 1;
}
if ((ctx->http.req.method == HTTP_PUT ||
ctx->http.req.method == HTTP_POST)
&& ctx->http.rsp.content_length == 0) {
NET_DBG("No body expected");
return 1;
}
NET_DBG("Headers complete");
return 0;
}
static int on_message_begin(struct http_parser *parser)
{
if (CONFIG_HTTP_LOG_LEVEL >= LOG_LEVEL_INF) {
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
NET_DBG("-- HTTP %s response (headers) --",
http_method_str(ctx->http.req.method));
}
return 0;
}
static int on_message_complete(struct http_parser *parser)
{
struct http_ctx *ctx = CONTAINER_OF(parser,
struct http_ctx,
http.parser);
NET_DBG("-- HTTP %s response (complete) --",
http_method_str(ctx->http.req.method));
if (ctx->http.rsp.cb) {
ctx->http.rsp.cb(ctx,
ctx->http.rsp.response_buf,
ctx->http.rsp.response_buf_len,
ctx->http.rsp.data_len,
HTTP_DATA_FINAL,
ctx->http.req.user_data);
}
ctx->http.rsp.message_complete = 1;
k_sem_give(&ctx->http.req.wait);
return 0;
}
static int on_chunk_header(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}
static int on_chunk_complete(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}
static void http_received(struct net_app_ctx *app_ctx,
struct net_pkt *pkt,
int status,
void *user_data)
{
struct http_ctx *ctx = user_data;
size_t start = ctx->http.rsp.data_len;
u16_t len = 0U;
struct net_buf *frag, *prev_frag = NULL;
size_t recv_len;
size_t pkt_len;
recv_len = net_pkt_appdatalen(pkt);
if (recv_len == 0) {
/* don't print info about zero-length app data buffers */
goto quit;
}
if (status) {
NET_DBG("[%p] Status %d <%s>", ctx, status, RC_STR(status));
goto out;
}
/* Get rid of possible IP headers in the first fragment. */
frag = pkt->frags;
pkt_len = net_pkt_get_len(pkt);
if (recv_len < pkt_len) {
net_buf_pull(frag, pkt_len - recv_len);
net_pkt_set_appdata(pkt, frag->data);
}
NET_DBG("[%p] Received %zd bytes http data", ctx, recv_len);
while (frag) {
/* If this fragment cannot be copied to result buf,
* then parse what we have which will cause the callback to be
* called in function on_body(), and continue copying.
*/
if ((ctx->http.rsp.data_len + frag->len) >
ctx->http.rsp.response_buf_len) {
/* If the caller has not supplied a callback, then
* we cannot really continue if the request buffer
* overflows. Set the data_len to mark how many bytes
* should be needed in the response_buf.
*/
if (!ctx->cb.recv) {
ctx->http.rsp.data_len = recv_len;
goto out;
}
http_parser_execute(&ctx->http.parser,
&ctx->http.parser_settings,
ctx->http.rsp.response_buf + start,
len);
ctx->http.rsp.data_len = 0;
len = 0U;
start = 0;
}
memcpy(ctx->http.rsp.response_buf + ctx->http.rsp.data_len,
frag->data, frag->len);
ctx->http.rsp.data_len += frag->len;
len += frag->len;
prev_frag = frag;
frag = frag->frags;
pkt->frags = frag;
prev_frag->frags = NULL;
net_pkt_frag_unref(prev_frag);
}
out:
http_parser_execute(&ctx->http.parser,
&ctx->http.parser_settings,
ctx->http.rsp.response_buf + start,
len);
net_pkt_unref(pkt);
return;
quit:
http_parser_init(&ctx->http.parser, HTTP_RESPONSE);
ctx->http.rsp.data_len = 0;
net_pkt_unref(pkt);
}
static void http_data_sent(struct net_app_ctx *app_ctx,
int status,
void *user_data_send,
void *user_data)
{
struct http_ctx *ctx = user_data;
if (!user_data_send) {
/* This is the token field in the net_context_send().
* If this is not set, then it is TCP ACK messages
* that are generated by the stack. We just ignore those.
*/
return;
}
if (ctx->cb.send) {
ctx->cb.send(ctx, status, user_data_send, ctx->user_data);
}
}
static void http_connected(struct net_app_ctx *app_ctx,
int status,
void *user_data)
{
struct http_ctx *ctx = user_data;
if (status < 0) {
return;
}
if (ctx->cb.connect && app_ctx->default_ctx) {
ctx->cb.connect(ctx, HTTP_CONNECTION,
&app_ctx->default_ctx->remote,
ctx->user_data);
}
if (ctx->is_connected) {
return;
}
ctx->is_connected = true;
k_sem_give(&ctx->http.connect_wait);
}
static void http_closed(struct net_app_ctx *app_ctx,
int status,
void *user_data)
{
struct http_ctx *ctx = user_data;
ARG_UNUSED(app_ctx);
ARG_UNUSED(status);
NET_DBG("[%p] connection closed", ctx);
ctx->is_connected = false;
if (ctx->cb.close) {
ctx->cb.close(ctx, 0, ctx->user_data);
}
}
int http_client_init(struct http_ctx *ctx,
const char *server,
u16_t server_port,
struct sockaddr *server_addr,
s32_t timeout)
{
int ret;
(void)memset(ctx, 0, sizeof(*ctx));
ret = net_app_init_tcp_client(&ctx->app_ctx,
NULL, /* use any local address */
server_addr,
server,
server_port,
timeout,
ctx);
if (ret < 0) {
NET_DBG("Cannot init HTTP client (%d)", ret);
return ret;
}
ret = net_app_set_cb(&ctx->app_ctx, http_connected, http_received,
http_data_sent, http_closed);
if (ret < 0) {
NET_ERR("Cannot set callbacks (%d)", ret);
return ret;
}
ctx->http.parser_settings.on_body = on_body;
ctx->http.parser_settings.on_chunk_complete = on_chunk_complete;
ctx->http.parser_settings.on_chunk_header = on_chunk_header;
ctx->http.parser_settings.on_headers_complete = on_headers_complete;
ctx->http.parser_settings.on_header_field = on_header_field;
ctx->http.parser_settings.on_header_value = on_header_value;
ctx->http.parser_settings.on_message_begin = on_message_begin;
ctx->http.parser_settings.on_message_complete = on_message_complete;
ctx->http.parser_settings.on_status = on_status;
ctx->http.parser_settings.on_url = on_url;
k_sem_init(&ctx->http.req.wait, 0, 1);
k_sem_init(&ctx->http.connect_wait, 0, 1);
ctx->server = server;
ctx->is_init = true;
ctx->is_client = true;
return 0;
}
int http_request_cancel(struct http_ctx *ctx)
{
if (!ctx->is_init) {
return -EINVAL;
}
if (!ctx->is_client) {
return -EINVAL;
}
client_reset(ctx);
return 0;
}
#if defined(CONFIG_HTTPS)
int http_client_set_tls(struct http_ctx *ctx,
u8_t *request_buf,
size_t request_buf_len,
u8_t *personalization_data,
size_t personalization_data_len,
net_app_ca_cert_cb_t cert_cb,
const char *cert_host,
net_app_entropy_src_cb_t entropy_src_cb,
struct k_mem_pool *pool,
k_thread_stack_t *https_stack,
size_t https_stack_size)
{
int ret;
ret = net_app_client_tls(&ctx->app_ctx,
request_buf,
request_buf_len,
personalization_data,
personalization_data_len,
cert_cb,
cert_host,
entropy_src_cb,
pool,
https_stack,
https_stack_size);
if (ret < 0) {
NET_DBG("Cannot init TLS (%d)", ret);
return ret;
}
ctx->is_tls = true;
return 0;
}
#endif /* CONFIG_HTTPS */

File diff suppressed because it is too large Load diff