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:
parent
d0ba9d9493
commit
ebc81bdf8d
8 changed files with 133 additions and 73 deletions
|
@ -114,12 +114,14 @@ enum http_verdict {
|
||||||
*
|
*
|
||||||
* @param ctx The context to use.
|
* @param ctx The context to use.
|
||||||
* @param type Connection type (websocket or HTTP)
|
* @param type Connection type (websocket or HTTP)
|
||||||
|
* @param dst Remote socket address
|
||||||
*
|
*
|
||||||
* @return HTTP_VERDICT_DROP if connection is to be dropped,
|
* @return HTTP_VERDICT_DROP if connection is to be dropped,
|
||||||
* HTTP_VERDICT_ACCEPT if the application wants to accept the unknown URL.
|
* HTTP_VERDICT_ACCEPT if the application wants to accept the unknown URL.
|
||||||
*/
|
*/
|
||||||
typedef enum http_verdict (*http_url_cb_t)(struct http_ctx *ctx,
|
typedef enum http_verdict (*http_url_cb_t)(struct http_ctx *ctx,
|
||||||
enum http_connection_type type);
|
enum http_connection_type type,
|
||||||
|
const struct sockaddr *dst);
|
||||||
|
|
||||||
/* Collection of URLs that this server will handle */
|
/* Collection of URLs that this server will handle */
|
||||||
struct http_server_urls {
|
struct http_server_urls {
|
||||||
|
@ -149,12 +151,14 @@ struct http_server_urls {
|
||||||
* pkt parameter is set to NULL.
|
* pkt parameter is set to NULL.
|
||||||
* @param flags Flags related to http. For example contains information
|
* @param flags Flags related to http. For example contains information
|
||||||
* if the data is text or binary etc.
|
* if the data is text or binary etc.
|
||||||
|
* @param dst Remote socket address from where HTTP packet is received.
|
||||||
* @param user_data The user data given in init call.
|
* @param user_data The user data given in init call.
|
||||||
*/
|
*/
|
||||||
typedef void (*http_recv_cb_t)(struct http_ctx *ctx,
|
typedef void (*http_recv_cb_t)(struct http_ctx *ctx,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
int status,
|
int status,
|
||||||
u32_t flags,
|
u32_t flags,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,10 +170,12 @@ typedef void (*http_recv_cb_t)(struct http_ctx *ctx,
|
||||||
*
|
*
|
||||||
* @param ctx The context to use.
|
* @param ctx The context to use.
|
||||||
* @param type Connection type (websocket or HTTP)
|
* @param type Connection type (websocket or HTTP)
|
||||||
|
* @param dst Remote socket address where the connection is established.
|
||||||
* @param user_data The user data given in init call.
|
* @param user_data The user data given in init call.
|
||||||
*/
|
*/
|
||||||
typedef void (*http_connect_cb_t)(struct http_ctx *ctx,
|
typedef void (*http_connect_cb_t)(struct http_ctx *ctx,
|
||||||
enum http_connection_type type,
|
enum http_connection_type type,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,12 +451,6 @@ struct http_ctx {
|
||||||
/** Network buffer allocation timeout */
|
/** Network buffer allocation timeout */
|
||||||
s32_t timeout;
|
s32_t timeout;
|
||||||
|
|
||||||
/** Websocket endpoint address */
|
|
||||||
struct sockaddr *addr;
|
|
||||||
|
|
||||||
/** Websocket endpoint port */
|
|
||||||
u16_t port;
|
|
||||||
|
|
||||||
/** Is this context setup or not */
|
/** Is this context setup or not */
|
||||||
u8_t is_init : 1;
|
u8_t is_init : 1;
|
||||||
|
|
||||||
|
@ -906,13 +906,16 @@ int http_send_msg_raw(struct http_ctx *ctx, struct net_pkt *pkt,
|
||||||
* @param ctx Http context.
|
* @param ctx Http context.
|
||||||
* @param payload Application data to send
|
* @param payload Application data to send
|
||||||
* @param payload_len Length of application data
|
* @param payload_len Length of application data
|
||||||
|
* @param dst Remote socket address
|
||||||
* @param user_send_data User specific data to this connection. This is passed
|
* @param user_send_data User specific data to this connection. This is passed
|
||||||
* as a parameter to sent cb after the packet has been sent.
|
* as a parameter to sent cb after the packet has been sent.
|
||||||
*
|
*
|
||||||
* @return 0 if ok, <0 if error.
|
* @return 0 if ok, <0 if error.
|
||||||
*/
|
*/
|
||||||
int http_prepare_and_send(struct http_ctx *ctx, const char *payload,
|
int http_prepare_and_send(struct http_ctx *ctx, const char *payload,
|
||||||
size_t payload_len, void *user_send_data);
|
size_t payload_len,
|
||||||
|
const struct sockaddr *dst,
|
||||||
|
void *user_send_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send HTTP data chunk to peer.
|
* @brief Send HTTP data chunk to peer.
|
||||||
|
@ -920,13 +923,16 @@ int http_prepare_and_send(struct http_ctx *ctx, const char *payload,
|
||||||
* @param ctx Http context.
|
* @param ctx Http context.
|
||||||
* @param payload Application data to send
|
* @param payload Application data to send
|
||||||
* @param payload_len Length of application data
|
* @param payload_len Length of application data
|
||||||
|
* @param dst Remote socket address
|
||||||
* @param user_send_data User specific data to this connection. This is passed
|
* @param user_send_data User specific data to this connection. This is passed
|
||||||
* as a parameter to sent cb after the packet has been sent.
|
* as a parameter to sent cb after the packet has been sent.
|
||||||
*
|
*
|
||||||
* @return 0 if ok, <0 if error.
|
* @return 0 if ok, <0 if error.
|
||||||
*/
|
*/
|
||||||
int http_send_chunk(struct http_ctx *ctx, const char *payload,
|
int http_send_chunk(struct http_ctx *ctx, const char *payload,
|
||||||
size_t payload_len, void *user_send_data);
|
size_t payload_len,
|
||||||
|
const struct sockaddr *dst,
|
||||||
|
void *user_send_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send any pending data immediately.
|
* @brief Send any pending data immediately.
|
||||||
|
@ -946,11 +952,13 @@ int http_send_flush(struct http_ctx *ctx, void *user_send_data);
|
||||||
* @param code HTTP error code
|
* @param code HTTP error code
|
||||||
* @param html_payload Extra payload, can be null
|
* @param html_payload Extra payload, can be null
|
||||||
* @param html_len Payload length
|
* @param html_len Payload length
|
||||||
|
* @param dst Remote socket address
|
||||||
*
|
*
|
||||||
* @return 0 if ok, <0 if error.
|
* @return 0 if ok, <0 if error.
|
||||||
*/
|
*/
|
||||||
int http_send_error(struct http_ctx *ctx, int code, u8_t *html_payload,
|
int http_send_error(struct http_ctx *ctx, int code,
|
||||||
size_t html_len);
|
u8_t *html_payload, size_t html_len,
|
||||||
|
const struct sockaddr *dst);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add HTTP header field to the message.
|
* @brief Add HTTP header field to the message.
|
||||||
|
@ -961,6 +969,7 @@ int http_send_error(struct http_ctx *ctx, int code, u8_t *html_payload,
|
||||||
*
|
*
|
||||||
* @param ctx Http context.
|
* @param ctx Http context.
|
||||||
* @param http_header_field All or part of HTTP header to be added.
|
* @param http_header_field All or part of HTTP header to be added.
|
||||||
|
* @param dst Remote socket address.
|
||||||
* @param user_send_data User data value that is used in send callback.
|
* @param user_send_data User data value that is used in send callback.
|
||||||
* Note that this value is only used if this function call causes a HTTP
|
* Note that this value is only used if this function call causes a HTTP
|
||||||
* message to be sent.
|
* message to be sent.
|
||||||
|
@ -968,6 +977,7 @@ int http_send_error(struct http_ctx *ctx, int code, u8_t *html_payload,
|
||||||
* @return <0 if error, other value tells how many bytes were added
|
* @return <0 if error, other value tells how many bytes were added
|
||||||
*/
|
*/
|
||||||
int http_add_header(struct http_ctx *ctx, const char *http_header_field,
|
int http_add_header(struct http_ctx *ctx, const char *http_header_field,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_send_data);
|
void *user_send_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -980,6 +990,7 @@ int http_add_header(struct http_ctx *ctx, const char *http_header_field,
|
||||||
* @param ctx Http context.
|
* @param ctx Http context.
|
||||||
* @param name Name of the header field
|
* @param name Name of the header field
|
||||||
* @param value Value of the header field
|
* @param value Value of the header field
|
||||||
|
* @param dst Remote socket address
|
||||||
* @param user_send_data User data value that is used in send callback.
|
* @param user_send_data User data value that is used in send callback.
|
||||||
* Note that this value is only used if this function call causes a HTTP
|
* Note that this value is only used if this function call causes a HTTP
|
||||||
* message to be sent.
|
* message to be sent.
|
||||||
|
@ -987,7 +998,9 @@ int http_add_header(struct http_ctx *ctx, const char *http_header_field,
|
||||||
* @return <0 if error, other value tells how many bytes were added
|
* @return <0 if error, other value tells how many bytes were added
|
||||||
*/
|
*/
|
||||||
int http_add_header_field(struct http_ctx *ctx, const char *name,
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Find a handler function for a given URL.
|
* @brief Find a handler function for a given URL.
|
||||||
|
|
|
@ -211,6 +211,11 @@ struct http_parser {
|
||||||
void *data; /* A pointer to get hook to the "connection" or "socket"
|
void *data; /* A pointer to get hook to the "connection" or "socket"
|
||||||
* object
|
* object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Remote socket address of http connection, where parser can initiate
|
||||||
|
* replies if necessary.
|
||||||
|
*/
|
||||||
|
const struct sockaddr *addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ CONFIG_NET_MAX_CONTEXTS=16
|
||||||
|
|
||||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||||
CONFIG_SYS_LOG_NET_LEVEL=4
|
CONFIG_SYS_LOG_NET_LEVEL=4
|
||||||
CONFIG_NET_DEBUG_HTTP=y
|
CONFIG_NET_DEBUG_HTTP=n
|
||||||
CONFIG_NET_DEBUG_APP=n
|
CONFIG_NET_DEBUG_APP=n
|
||||||
CONFIG_NET_DEBUG_CORE=n
|
CONFIG_NET_DEBUG_CORE=n
|
||||||
CONFIG_NET_DEBUG_IF=n
|
CONFIG_NET_DEBUG_IF=n
|
||||||
|
@ -50,3 +50,5 @@ CONFIG_NET_STATISTICS=y
|
||||||
|
|
||||||
CONFIG_NET_MGMT=y
|
CONFIG_NET_MGMT=y
|
||||||
CONFIG_NET_MGMT_EVENT=y
|
CONFIG_NET_MGMT_EVENT=y
|
||||||
|
|
||||||
|
CONFIG_MAIN_STACK_SIZE=2048
|
||||||
|
|
|
@ -424,6 +424,7 @@ static void http_received(struct http_ctx *ctx,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
int status,
|
int status,
|
||||||
u32_t flags,
|
u32_t flags,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
|
|
@ -108,22 +108,22 @@ void panic(const char *msg)
|
||||||
|
|
||||||
static int http_response(struct http_ctx *ctx, const char *header,
|
static int http_response(struct http_ctx *ctx, const char *header,
|
||||||
const char *payload, size_t payload_len,
|
const char *payload, size_t payload_len,
|
||||||
char *str)
|
char *str, const struct sockaddr *dst)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = http_add_header(ctx, header, str);
|
ret = http_add_header(ctx, header, dst, str);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
NET_ERR("Cannot add HTTP header (%d)", ret);
|
NET_ERR("Cannot add HTTP header (%d)", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, HTTP_CRLF, str);
|
ret = http_add_header(ctx, HTTP_CRLF, dst, str);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_send_chunk(ctx, payload, payload_len, str);
|
ret = http_send_chunk(ctx, payload, payload_len, dst, str);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
NET_ERR("Cannot send data to peer (%d)", ret);
|
NET_ERR("Cannot send data to peer (%d)", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -132,7 +132,8 @@ static int http_response(struct http_ctx *ctx, const char *header,
|
||||||
return http_send_flush(ctx, str);
|
return http_send_flush(ctx, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_response_soft_404(struct http_ctx *ctx)
|
static int http_response_soft_404(struct http_ctx *ctx,
|
||||||
|
const struct sockaddr *dst)
|
||||||
{
|
{
|
||||||
static const char *not_found =
|
static const char *not_found =
|
||||||
HTML_HEADER
|
HTML_HEADER
|
||||||
|
@ -140,7 +141,7 @@ static int http_response_soft_404(struct http_ctx *ctx)
|
||||||
HTML_FOOTER;
|
HTML_FOOTER;
|
||||||
|
|
||||||
return http_response(ctx, HTTP_STATUS_200_OK, not_found,
|
return http_response(ctx, HTTP_STATUS_200_OK, not_found,
|
||||||
strlen(not_found), "Error");
|
strlen(not_found), "Error", dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prints the received HTTP header fields as an HTML list */
|
/* Prints the received HTTP header fields as an HTML list */
|
||||||
|
@ -202,7 +203,8 @@ static void print_http_headers(struct http_ctx *ctx,
|
||||||
"<h2>Server: %s</h2>"HTML_FOOTER, CONFIG_ARCH);
|
"<h2>Server: %s</h2>"HTML_FOOTER, CONFIG_ARCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_serve_headers(struct http_ctx *ctx)
|
int http_serve_headers(struct http_ctx *ctx,
|
||||||
|
const struct sockaddr *dst)
|
||||||
{
|
{
|
||||||
#define HTTP_MAX_BODY_STR_SIZE 1024
|
#define HTTP_MAX_BODY_STR_SIZE 1024
|
||||||
static char html_body[HTTP_MAX_BODY_STR_SIZE];
|
static char html_body[HTTP_MAX_BODY_STR_SIZE];
|
||||||
|
@ -210,10 +212,11 @@ int http_serve_headers(struct http_ctx *ctx)
|
||||||
print_http_headers(ctx, html_body, HTTP_MAX_BODY_STR_SIZE);
|
print_http_headers(ctx, html_body, HTTP_MAX_BODY_STR_SIZE);
|
||||||
|
|
||||||
return http_response(ctx, HTTP_STATUS_200_OK, html_body,
|
return http_response(ctx, HTTP_STATUS_200_OK, html_body,
|
||||||
strlen(html_body), "Headers");
|
strlen(html_body), "Headers", dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_serve_index_html(struct http_ctx *ctx)
|
static int http_serve_index_html(struct http_ctx *ctx,
|
||||||
|
const struct sockaddr *dst)
|
||||||
{
|
{
|
||||||
static const char index_html[] = {
|
static const char index_html[] = {
|
||||||
#include "index.html.inc"
|
#include "index.html.inc"
|
||||||
|
@ -223,11 +226,12 @@ static int http_serve_index_html(struct http_ctx *ctx)
|
||||||
sizeof(index_html));
|
sizeof(index_html));
|
||||||
|
|
||||||
return http_response(ctx, HTTP_STATUS_200_OK, index_html,
|
return http_response(ctx, HTTP_STATUS_200_OK, index_html,
|
||||||
sizeof(index_html), "Index");
|
sizeof(index_html), "Index", dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_connected(struct http_ctx *ctx,
|
static void http_connected(struct http_ctx *ctx,
|
||||||
enum http_connection_type type,
|
enum http_connection_type type,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
char url[32];
|
char url[32];
|
||||||
|
@ -242,21 +246,21 @@ static void http_connected(struct http_ctx *ctx,
|
||||||
if (type == HTTP_CONNECTION) {
|
if (type == HTTP_CONNECTION) {
|
||||||
if (strncmp(ctx->http.url, "/",
|
if (strncmp(ctx->http.url, "/",
|
||||||
ctx->http.url_len) == 0) {
|
ctx->http.url_len) == 0) {
|
||||||
http_serve_index_html(ctx);
|
http_serve_index_html(ctx, dst);
|
||||||
http_close(ctx);
|
http_close(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(ctx->http.url, "/index.html",
|
if (strncmp(ctx->http.url, "/index.html",
|
||||||
ctx->http.url_len) == 0) {
|
ctx->http.url_len) == 0) {
|
||||||
http_serve_index_html(ctx);
|
http_serve_index_html(ctx, dst);
|
||||||
http_close(ctx);
|
http_close(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(ctx->http.url, "/headers",
|
if (strncmp(ctx->http.url, "/headers",
|
||||||
ctx->http.url_len) == 0) {
|
ctx->http.url_len) == 0) {
|
||||||
http_serve_headers(ctx);
|
http_serve_headers(ctx, dst);
|
||||||
http_close(ctx);
|
http_close(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +269,7 @@ static void http_connected(struct http_ctx *ctx,
|
||||||
/* Give 404 error for all the other URLs we do not want to handle
|
/* Give 404 error for all the other URLs we do not want to handle
|
||||||
* right now.
|
* right now.
|
||||||
*/
|
*/
|
||||||
http_response_soft_404(ctx);
|
http_response_soft_404(ctx, dst);
|
||||||
http_close(ctx);
|
http_close(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +277,7 @@ static void http_received(struct http_ctx *ctx,
|
||||||
struct net_pkt *pkt,
|
struct net_pkt *pkt,
|
||||||
int status,
|
int status,
|
||||||
u32_t flags,
|
u32_t flags,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
@ -317,14 +322,15 @@ static const char *get_string(int str_len, const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum http_verdict default_handler(struct http_ctx *ctx,
|
static enum http_verdict default_handler(struct http_ctx *ctx,
|
||||||
enum http_connection_type type)
|
enum http_connection_type type,
|
||||||
|
const struct sockaddr *dst)
|
||||||
{
|
{
|
||||||
NET_DBG("No handler for %s URL %s",
|
NET_DBG("No handler for %s URL %s",
|
||||||
type == HTTP_CONNECTION ? "HTTP" : "WS",
|
type == HTTP_CONNECTION ? "HTTP" : "WS",
|
||||||
get_string(ctx->http.url_len, ctx->http.url));
|
get_string(ctx->http.url_len, ctx->http.url));
|
||||||
|
|
||||||
if (type == HTTP_CONNECTION) {
|
if (type == HTTP_CONNECTION) {
|
||||||
http_response_soft_404(ctx);
|
http_response_soft_404(ctx, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return HTTP_VERDICT_DROP;
|
return HTTP_VERDICT_DROP;
|
||||||
|
|
|
@ -119,9 +119,21 @@ int http_send_msg_raw(struct http_ctx *ctx, struct net_pkt *pkt,
|
||||||
return ret;
|
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,
|
int http_prepare_and_send(struct http_ctx *ctx,
|
||||||
const char *payload,
|
const char *payload,
|
||||||
size_t payload_len,
|
size_t payload_len,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_send_data)
|
void *user_send_data)
|
||||||
{
|
{
|
||||||
size_t added;
|
size_t added;
|
||||||
|
@ -129,9 +141,7 @@ int http_prepare_and_send(struct http_ctx *ctx,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!ctx->pending) {
|
if (!ctx->pending) {
|
||||||
ctx->pending = net_app_get_net_pkt(&ctx->app_ctx,
|
ctx->pending = get_net_pkt(ctx, dst);
|
||||||
AF_UNSPEC,
|
|
||||||
ctx->timeout);
|
|
||||||
if (!ctx->pending) {
|
if (!ctx->pending) {
|
||||||
return -ENOMEM;
|
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,
|
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];
|
char chunk_header[16];
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -202,19 +212,19 @@ int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
|
||||||
(unsigned int)len);
|
(unsigned int)len);
|
||||||
|
|
||||||
ret = http_prepare_and_send(ctx, chunk_header, strlen(chunk_header),
|
ret = http_prepare_and_send(ctx, chunk_header, strlen(chunk_header),
|
||||||
user_send_data);
|
dst, user_send_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len) {
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
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);
|
user_send_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
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,
|
static int _http_add_header(struct http_ctx *ctx, s32_t timeout,
|
||||||
const char *name, const char *value,
|
const char *name, const char *value,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_send_data)
|
void *user_send_data)
|
||||||
{
|
{
|
||||||
int ret;
|
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) {
|
if (value && ret >= 0) {
|
||||||
ret = http_prepare_and_send(ctx, ": ", strlen(": "),
|
ret = http_prepare_and_send(ctx, ": ", strlen(": "), dst,
|
||||||
user_send_data);
|
user_send_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_prepare_and_send(ctx, value, strlen(value),
|
ret = http_prepare_and_send(ctx, value, strlen(value), dst,
|
||||||
user_send_data);
|
user_send_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_prepare_and_send(ctx, HTTP_CRLF, strlen(HTTP_CRLF),
|
ret = http_prepare_and_send(ctx, HTTP_CRLF, strlen(HTTP_CRLF),
|
||||||
user_send_data);
|
dst, user_send_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -255,13 +267,18 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_add_header(struct http_ctx *ctx, const char *field,
|
int http_add_header(struct http_ctx *ctx, const char *field,
|
||||||
|
const struct sockaddr *dst,
|
||||||
void *user_send_data)
|
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,
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,41 +72,41 @@ int http_request(struct http_ctx *ctx, struct http_request *req, s32_t timeout,
|
||||||
ctx->pending = NULL;
|
ctx->pending = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, method, user_data);
|
ret = http_add_header(ctx, method, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, " ", user_data);
|
ret = http_add_header(ctx, " ", NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, req->url, user_data);
|
ret = http_add_header(ctx, req->url, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, req->protocol, user_data);
|
ret = http_add_header(ctx, req->protocol, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, HTTP_CRLF, user_data);
|
ret = http_add_header(ctx, HTTP_CRLF, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->host) {
|
if (req->host) {
|
||||||
ret = http_add_header_field(ctx, HTTP_HOST, req->host,
|
ret = http_add_header_field(ctx, HTTP_HOST, req->host,
|
||||||
user_data);
|
NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->header_fields) {
|
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) {
|
if (ret < 0) {
|
||||||
goto out;
|
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) {
|
if (req->content_type_value) {
|
||||||
ret = http_add_header_field(ctx, HTTP_CONTENT_TYPE,
|
ret = http_add_header_field(ctx, HTTP_CONTENT_TYPE,
|
||||||
req->content_type_value,
|
req->content_type_value,
|
||||||
user_data);
|
NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
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,
|
ret = http_add_header_field(ctx, HTTP_CONTENT_LEN,
|
||||||
content_len_str, user_data);
|
content_len_str,
|
||||||
|
NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, HTTP_CRLF, user_data);
|
ret = http_add_header(ctx, HTTP_CRLF, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_prepare_and_send(ctx, req->payload,
|
ret = http_prepare_and_send(ctx, req->payload,
|
||||||
req->payload_size, user_data);
|
req->payload_size,
|
||||||
|
NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = http_add_header(ctx, HTTP_EOF, user_data);
|
ret = http_add_header(ctx, HTTP_EOF, NULL, user_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -606,8 +608,10 @@ static void http_connected(struct net_app_ctx *app_ctx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->cb.connect) {
|
if (ctx->cb.connect && app_ctx->default_ctx) {
|
||||||
ctx->cb.connect(ctx, HTTP_CONNECTION, ctx->user_data);
|
ctx->cb.connect(ctx, HTTP_CONNECTION,
|
||||||
|
&app_ctx->default_ctx->remote,
|
||||||
|
ctx->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->is_connected) {
|
if (ctx->is_connected) {
|
||||||
|
|
|
@ -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,
|
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;
|
const char *msg;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -187,13 +188,14 @@ int http_send_error(struct http_ctx *ctx, int code,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = http_add_header(ctx, msg, NULL);
|
ret = http_add_header(ctx, msg, dst, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (html_payload) {
|
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) {
|
if (ret < 0) {
|
||||||
goto quit;
|
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,
|
static inline void new_client(struct http_ctx *ctx,
|
||||||
enum http_connection_type type,
|
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_DEBUG_HTTP) && (CONFIG_SYS_LOG_NET_LEVEL > 2)
|
||||||
#if defined(CONFIG_NET_IPV6)
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
@ -311,7 +314,7 @@ static inline void new_client(struct http_ctx *ctx,
|
||||||
struct net_context *net_ctx;
|
struct net_context *net_ctx;
|
||||||
const char *type_str = "HTTP";
|
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) {
|
if (net_ctx) {
|
||||||
NET_INFO("[%p] %s connection from %s (%p)", ctx, type_str,
|
NET_INFO("[%p] %s connection from %s (%p)", ctx, type_str,
|
||||||
sprint_ipaddr(buf, sizeof(buf), &net_ctx->remote),
|
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,
|
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) {
|
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;
|
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;
|
struct http_root_url *root_url;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -493,7 +498,8 @@ static int http_process_recv(struct http_ctx *ctx)
|
||||||
|
|
||||||
if (ctx->http.urls->default_cb) {
|
if (ctx->http.urls->default_cb) {
|
||||||
ret = ctx->http.urls->default_cb(ctx,
|
ret = ctx->http.urls->default_cb(ctx,
|
||||||
HTTP_CONNECTION);
|
HTTP_CONNECTION,
|
||||||
|
dst);
|
||||||
if (ret != HTTP_VERDICT_ACCEPT) {
|
if (ret != HTTP_VERDICT_ACCEPT) {
|
||||||
ret = -ECONNREFUSED;
|
ret = -ECONNREFUSED;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -502,7 +508,7 @@ static int http_process_recv(struct http_ctx *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
http_change_state(ctx, HTTP_STATE_OPEN);
|
http_change_state(ctx, HTTP_STATE_OPEN);
|
||||||
url_connected(ctx, HTTP_CONNECTION);
|
url_connected(ctx, HTTP_CONNECTION, dst);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
@ -538,6 +544,7 @@ static void http_received(struct net_app_ctx *app_ctx,
|
||||||
struct http_ctx *ctx = user_data;
|
struct http_ctx *ctx = user_data;
|
||||||
size_t start = ctx->http.data_len;
|
size_t start = ctx->http.data_len;
|
||||||
u16_t len = 0;
|
u16_t len = 0;
|
||||||
|
const struct sockaddr *dst = NULL;
|
||||||
struct net_buf *frag;
|
struct net_buf *frag;
|
||||||
int parsed_len;
|
int parsed_len;
|
||||||
size_t recv_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);
|
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) {
|
if (ctx->state == HTTP_STATE_OPEN) {
|
||||||
/* We have active websocket session and there is no longer
|
/* We have active websocket session and there is no longer
|
||||||
* any HTTP traffic in the connection. Give the data to
|
* 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
|
* overflows. Set the data_len to mark how many bytes
|
||||||
* should be needed in the response_buf.
|
* 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;
|
ctx->http.data_len = recv_len;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -635,13 +647,13 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->http.parser.http_errno != HPE_OK) {
|
if (ctx->http.parser.http_errno != HPE_OK) {
|
||||||
http_send_error(ctx, 400, NULL, 0);
|
http_send_error(ctx, 400, NULL, 0, dst);
|
||||||
} else {
|
} else {
|
||||||
if (ctx->state == HTTP_STATE_HEADER_RECEIVED) {
|
if (ctx->state == HTTP_STATE_HEADER_RECEIVED) {
|
||||||
goto http_ready;
|
goto http_ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
http_process_recv(ctx);
|
http_process_recv(ctx, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
|
@ -654,14 +666,14 @@ quit:
|
||||||
|
|
||||||
http_only:
|
http_only:
|
||||||
if (ctx->cb.recv) {
|
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;
|
return;
|
||||||
|
|
||||||
http_ready:
|
http_ready:
|
||||||
http_change_state(ctx, HTTP_STATE_OPEN);
|
http_change_state(ctx, HTTP_STATE_OPEN);
|
||||||
url_connected(ctx, HTTP_CONNECT);
|
url_connected(ctx, HTTP_CONNECT, dst);
|
||||||
net_pkt_unref(pkt);
|
net_pkt_unref(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue