net: http: Provide destination address in http replies

net_app_ctx maintains multiple net contexts(net_ctx). But when http
api's wants to reply or send some data, its always choose the first
net_context in the array, which is not correct always.

net_app_get_net_pkt_with_dst() api will select proper context
based on destination address. So with the help of new api in
net_app, http can select proper context and send packets. To
achieve this, desination address is provided in http_recv_cb_t
and http_connect_cb_t callbacks. Also chaged relevant API's to
provide destination address in http message preparation methods.

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
Ravi kumar Veeramally 2018-02-13 11:19:14 +02:00 committed by Carles Cufí
commit ebc81bdf8d
8 changed files with 133 additions and 73 deletions

View file

@ -119,9 +119,21 @@ int http_send_msg_raw(struct http_ctx *ctx, struct net_pkt *pkt,
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;
@ -129,9 +141,7 @@ int http_prepare_and_send(struct http_ctx *ctx,
do {
if (!ctx->pending) {
ctx->pending = net_app_get_net_pkt(&ctx->app_ctx,
AF_UNSPEC,
ctx->timeout);
ctx->pending = get_net_pkt(ctx, dst);
if (!ctx->pending) {
return -ENOMEM;
}
@ -189,7 +199,7 @@ int http_send_flush(struct http_ctx *ctx, void *user_send_data)
}
int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
void *user_send_data)
const struct sockaddr *dst, void *user_send_data)
{
char chunk_header[16];
int ret;
@ -202,19 +212,19 @@ int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
(unsigned int)len);
ret = http_prepare_and_send(ctx, chunk_header, strlen(chunk_header),
user_send_data);
dst, user_send_data);
if (ret < 0) {
return ret;
}
if (len) {
ret = http_prepare_and_send(ctx, buf, len, user_send_data);
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),
ret = http_prepare_and_send(ctx, HTTP_CRLF, sizeof(HTTP_CRLF), dst,
user_send_data);
if (ret < 0) {
return ret;
@ -225,26 +235,28 @@ int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
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), user_send_data);
ret = http_prepare_and_send(ctx, name, strlen(name), dst,
user_send_data);
if (value && ret >= 0) {
ret = http_prepare_and_send(ctx, ": ", strlen(": "),
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),
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),
user_send_data);
dst, user_send_data);
if (ret < 0) {
goto out;
}
@ -255,13 +267,18 @@ out:
}
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, 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, void *user_send_data)
const char *value,
const struct sockaddr *dst,
void *user_send_data)
{
return _http_add_header(ctx, ctx->timeout, name, value, user_send_data);
return _http_add_header(ctx, ctx->timeout, name, value, dst,
user_send_data);
}

View file

@ -72,41 +72,41 @@ int http_request(struct http_ctx *ctx, struct http_request *req, s32_t timeout,
ctx->pending = NULL;
}
ret = http_add_header(ctx, method, user_data);
ret = http_add_header(ctx, method, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, " ", user_data);
ret = http_add_header(ctx, " ", NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, req->url, user_data);
ret = http_add_header(ctx, req->url, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, req->protocol, user_data);
ret = http_add_header(ctx, req->protocol, NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, HTTP_CRLF, user_data);
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,
user_data);
NULL, user_data);
if (ret < 0) {
goto out;
}
}
if (req->header_fields) {
ret = http_add_header(ctx, req->header_fields, user_data);
ret = http_add_header(ctx, req->header_fields, NULL, user_data);
if (ret < 0) {
goto out;
}
@ -115,7 +115,7 @@ int http_request(struct http_ctx *ctx, struct http_request *req, s32_t timeout,
if (req->content_type_value) {
ret = http_add_header_field(ctx, HTTP_CONTENT_TYPE,
req->content_type_value,
user_data);
NULL, user_data);
if (ret < 0) {
goto out;
}
@ -132,23 +132,25 @@ int http_request(struct http_ctx *ctx, struct http_request *req, s32_t timeout,
}
ret = http_add_header_field(ctx, HTTP_CONTENT_LEN,
content_len_str, user_data);
content_len_str,
NULL, user_data);
if (ret < 0) {
goto out;
}
ret = http_add_header(ctx, HTTP_CRLF, user_data);
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, user_data);
req->payload_size,
NULL, user_data);
if (ret < 0) {
goto out;
}
} else {
ret = http_add_header(ctx, HTTP_EOF, user_data);
ret = http_add_header(ctx, HTTP_EOF, NULL, user_data);
if (ret < 0) {
goto out;
}
@ -606,8 +608,10 @@ static void http_connected(struct net_app_ctx *app_ctx,
return;
}
if (ctx->cb.connect) {
ctx->cb.connect(ctx, HTTP_CONNECTION, ctx->user_data);
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) {

View file

@ -168,7 +168,8 @@ static void http_data_sent(struct net_app_ctx *app_ctx,
}
int http_send_error(struct http_ctx *ctx, int code,
u8_t *html_payload, size_t html_len)
u8_t *html_payload, size_t html_len,
const struct sockaddr *dst)
{
const char *msg;
int ret;
@ -187,13 +188,14 @@ int http_send_error(struct http_ctx *ctx, int code,
break;
}
ret = http_add_header(ctx, msg, NULL);
ret = http_add_header(ctx, msg, dst, NULL);
if (ret < 0) {
goto quit;
}
if (html_payload) {
ret = http_prepare_and_send(ctx, html_payload, html_len, NULL);
ret = http_prepare_and_send(ctx, html_payload, html_len, dst,
NULL);
if (ret < 0) {
goto quit;
}
@ -297,7 +299,8 @@ static struct net_context *get_server_ctx(struct net_app_ctx *ctx,
static inline void new_client(struct http_ctx *ctx,
enum http_connection_type type,
struct net_app_ctx *app_ctx)
struct net_app_ctx *app_ctx,
const struct sockaddr *dst)
{
#if defined(CONFIG_NET_DEBUG_HTTP) && (CONFIG_SYS_LOG_NET_LEVEL > 2)
#if defined(CONFIG_NET_IPV6)
@ -311,7 +314,7 @@ static inline void new_client(struct http_ctx *ctx,
struct net_context *net_ctx;
const char *type_str = "HTTP";
net_ctx = get_server_ctx(app_ctx, ctx->addr);
net_ctx = get_server_ctx(app_ctx, dst);
if (net_ctx) {
NET_INFO("[%p] %s connection from %s (%p)", ctx, type_str,
sprint_ipaddr(buf, sizeof(buf), &net_ctx->remote),
@ -323,12 +326,13 @@ static inline void new_client(struct http_ctx *ctx,
}
static void url_connected(struct http_ctx *ctx,
enum http_connection_type type)
enum http_connection_type type,
const struct sockaddr *dst)
{
new_client(ctx, type, &ctx->app_ctx);
new_client(ctx, type, &ctx->app_ctx, dst);
if (ctx->cb.connect) {
ctx->cb.connect(ctx, type, ctx->user_data);
ctx->cb.connect(ctx, type, dst, ctx->user_data);
}
}
@ -471,7 +475,8 @@ struct http_root_url *http_url_find(struct http_ctx *ctx,
return NULL;
}
static int http_process_recv(struct http_ctx *ctx)
static int http_process_recv(struct http_ctx *ctx,
const struct sockaddr *dst)
{
struct http_root_url *root_url;
int ret;
@ -493,7 +498,8 @@ static int http_process_recv(struct http_ctx *ctx)
if (ctx->http.urls->default_cb) {
ret = ctx->http.urls->default_cb(ctx,
HTTP_CONNECTION);
HTTP_CONNECTION,
dst);
if (ret != HTTP_VERDICT_ACCEPT) {
ret = -ECONNREFUSED;
goto out;
@ -502,7 +508,7 @@ static int http_process_recv(struct http_ctx *ctx)
}
http_change_state(ctx, HTTP_STATE_OPEN);
url_connected(ctx, HTTP_CONNECTION);
url_connected(ctx, HTTP_CONNECTION, dst);
ret = 0;
@ -538,6 +544,7 @@ static void http_received(struct net_app_ctx *app_ctx,
struct http_ctx *ctx = user_data;
size_t start = ctx->http.data_len;
u16_t len = 0;
const struct sockaddr *dst = NULL;
struct net_buf *frag;
int parsed_len;
size_t recv_len;
@ -566,6 +573,11 @@ static void http_received(struct net_app_ctx *app_ctx,
NET_DBG("[%p] Received %zd bytes http data", ctx, recv_len);
if (net_pkt_context(pkt)) {
ctx->http.parser.addr = &net_pkt_context(pkt)->remote;
dst = &net_pkt_context(pkt)->remote;
}
if (ctx->state == HTTP_STATE_OPEN) {
/* We have active websocket session and there is no longer
* any HTTP traffic in the connection. Give the data to
@ -591,7 +603,7 @@ static void http_received(struct net_app_ctx *app_ctx,
* overflows. Set the data_len to mark how many bytes
* should be needed in the response_buf.
*/
if (http_process_recv(ctx) < 0) {
if (http_process_recv(ctx, dst) < 0) {
ctx->http.data_len = recv_len;
goto out;
}
@ -635,13 +647,13 @@ fail:
}
if (ctx->http.parser.http_errno != HPE_OK) {
http_send_error(ctx, 400, NULL, 0);
http_send_error(ctx, 400, NULL, 0, dst);
} else {
if (ctx->state == HTTP_STATE_HEADER_RECEIVED) {
goto http_ready;
}
http_process_recv(ctx);
http_process_recv(ctx, dst);
}
quit:
@ -654,14 +666,14 @@ quit:
http_only:
if (ctx->cb.recv) {
ctx->cb.recv(ctx, pkt, 0, 0, ctx->user_data);
ctx->cb.recv(ctx, pkt, 0, 0, dst, ctx->user_data);
}
return;
http_ready:
http_change_state(ctx, HTTP_STATE_OPEN);
url_connected(ctx, HTTP_CONNECT);
url_connected(ctx, HTTP_CONNECT, dst);
net_pkt_unref(pkt);
}