Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions include/zephyr/net/http/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ struct http_service_runtime_data {
int num_clients;
};

struct http_service_desc;

/** Custom socket creation function type */
typedef int (*http_socket_create_fn)(const struct http_service_desc *svc, int af, int proto);

/** HTTP service configuration */
struct http_service_config {
/** Custom socket creation for the service if needed */
http_socket_create_fn socket_create;
/* If any more service-specific configuration is needed, it can be added here. */
};

struct http_service_desc {
const char *host;
uint16_t *port;
Expand All @@ -80,14 +92,15 @@ struct http_service_desc {
struct http_resource_desc *res_begin;
struct http_resource_desc *res_end;
struct http_resource_detail *res_fallback;
const struct http_service_config *config;
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
const sec_tag_t *sec_tag_list;
size_t sec_tag_list_size;
#endif
};

#define __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, _res_begin, _res_end, ...) \
_res_fallback, _res_begin, _res_end, _config, ...) \
BUILD_ASSERT(_concurrent <= CONFIG_HTTP_SERVER_MAX_CLIENTS, \
"can't accept more then MAX_CLIENTS"); \
BUILD_ASSERT(_backlog > 0, "backlog can't be 0"); \
Expand All @@ -104,6 +117,7 @@ struct http_service_desc {
.res_begin = (_res_begin), \
.res_end = (_res_end), \
.res_fallback = (_res_fallback), \
.config = (_config), \
COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS, \
(.sec_tag_list = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (NULL), \
(GET_ARG_N(1, __VA_ARGS__))),), ()) \
Expand Down Expand Up @@ -133,11 +147,12 @@ struct http_service_desc {
* @param _backlog Maximum number of queued connections. (min. 1)
* @param _detail User-defined detail associated with the service.
* @param _res_fallback Fallback resource to be served if no other resource matches path
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
*/
#define HTTP_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback) \
_res_fallback, _config) \
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, NULL, NULL)
_res_fallback, NULL, NULL, _config)

/**
* @brief Define an HTTPS service without static resources.
Expand All @@ -158,13 +173,14 @@ struct http_service_desc {
* @param _backlog Maximum number of queued connections. (min. 1)
* @param _detail User-defined detail associated with the service.
* @param _res_fallback Fallback resource to be served if no other resource matches path
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
*/
#define HTTPS_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, _sec_tag_list, _sec_tag_list_size) \
_res_fallback, _config, _sec_tag_list, _sec_tag_list_size) \
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, NULL, NULL, \
_res_fallback, NULL, NULL, _config, \
_sec_tag_list, _sec_tag_list_size); \
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
Expand All @@ -188,14 +204,16 @@ struct http_service_desc {
* @param _backlog Maximum number of queued connections. (min. 1)
* @param _detail User-defined detail associated with the service.
* @param _res_fallback Fallback resource to be served if no other resource matches path
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
*/
#define HTTP_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, _res_fallback) \
#define HTTP_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, _res_fallback, \
_config) \
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, \
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
&_CONCAT(_http_resource_desc_##_name, _list_end)[0]);
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config);

/**
* @brief Define an HTTPS service with static resources.
Expand All @@ -216,17 +234,18 @@ struct http_service_desc {
* @param _backlog Maximum number of queued connections. (min. 1)
* @param _detail User-defined detail associated with the service.
* @param _res_fallback Fallback resource to be served if no other resource matches path
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
*/
#define HTTPS_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, _sec_tag_list, _sec_tag_list_size) \
_res_fallback, _config, _sec_tag_list, _sec_tag_list_size) \
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
_res_fallback, \
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], \
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config, \
_sec_tag_list, _sec_tag_list_size); \
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
Expand Down
2 changes: 1 addition & 1 deletion include/zephyr/net/net_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -3475,7 +3475,7 @@ extern int net_stats_prometheus_scrape(struct prometheus_collector *collector,
}; \
static Z_DECL_ALIGN(struct net_if) \
NET_IF_GET_NAME(dev_id, sfx)[NET_IF_MAX_CONFIGS] \
__used __in_section(_net_if, static, \
__used __noasan __in_section(_net_if, static, \
dev_id) = { \
[0 ... (NET_IF_MAX_CONFIGS - 1)] = { \
.if_dev = &(NET_IF_DEV_GET_NAME(dev_id, sfx)), \
Expand Down
12 changes: 12 additions & 0 deletions subsys/net/lib/http/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ if HTTP_SERVER

config HTTP_SERVER_STACK_SIZE
int "HTTP server thread stack size"
default 4096 if FILE_SYSTEM
default 3072
help
HTTP server thread stack size for processing RX/TX events.
Expand Down Expand Up @@ -219,6 +220,17 @@ config HTTP_SERVER_COMPRESSION
5. deflate -> .zz
6. File without compression

config HTTP_SERVER_STATIC_FS_RESPONSE_SIZE
int "Size of static file system response buffer"
depends on FILE_SYSTEM
default 1024
help
The size of a single chunk when serving static files from the file system.
This config value must be large enough to hold the headers in a single chunk.
If set to 0, the server will use the minimal viable buffer size for the response.
Please note that it is allocated on the stack of the HTTP server thread,
so CONFIG_HTTP_SERVER_STACK_SIZE has to be sufficiently large.

endif

# Hidden option to avoid having multiple individual options that are ORed together
Expand Down
5 changes: 5 additions & 0 deletions subsys/net/lib/http/http_server_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,12 @@ int http_server_init(struct http_server_ctx *ctx)
proto = IPPROTO_TCP;
}

if (svc->config != NULL && svc->config->socket_create != NULL) {
fd = svc->config->socket_create(svc, af, proto);
} else {
fd = zsock_socket(af, SOCK_STREAM, proto);
}

if (fd < 0) {
LOG_ERR("socket: %d", errno);
failed++;
Expand Down
13 changes: 12 additions & 1 deletion subsys/net/lib/http/http_server_http1.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,23 @@ int handle_http1_static_fs_resource(struct http_resource_detail_static_fs *stati
sizeof("Content-Length: 01234567890123456789\r\n")
#define CONTENT_ENCODING_HEADER_SIZE \
sizeof(CONTENT_ENCODING_HEADER) + HTTP_COMPRESSION_MAX_STRING_LEN + sizeof("\r\n")

/* Calculate the minimum required size */
#define STATIC_FS_RESPONSE_SIZE \
COND_CODE_1( \
IS_ENABLED(CONFIG_HTTP_SERVER_COMPRESSION), \
(STATIC_FS_RESPONSE_BASE_SIZE + CONTENT_ENCODING_HEADER_SIZE), \
(STATIC_FS_RESPONSE_BASE_SIZE))

// Issue in Zephyr: https://github.com/zephyrproject-rtos/zephyr/issues/92921
#if CONFIG_HTTP_SERVER_STATIC_FS_RESPONSE_SIZE > 0
BUILD_ASSERT(CONFIG_HTTP_SERVER_STATIC_FS_RESPONSE_SIZE >= STATIC_FS_RESPONSE_SIZE,
"CONFIG_HTTP_SERVER_STATIC_FS_RESPONSE_SIZE must be at least "
"large enough to hold HTTP headers");
#undef STATIC_FS_RESPONSE_SIZE
#define STATIC_FS_RESPONSE_SIZE CONFIG_HTTP_SERVER_STATIC_FS_RESPONSE_SIZE
#endif

enum http_compression chosen_compression = 0;
int len;
int remaining;
Expand Down Expand Up @@ -919,7 +930,7 @@ int handle_http1_request(struct http_client_ctx *client)

parsed = http_parser_execute(&client->parser, &client->parser_settings,
client->cursor, client->data_len);

if (parsed > client->data_len) {
LOG_ERR("HTTP/1 parser error, too much data consumed");
ret = -EBADMSG;
Expand Down