Skip to content

Commit 6cf7a0b

Browse files
net: http: service: enhance HTTP service with optional custom socket create
Update the HTTP service API to allow custom socket creation through a function pointer in the service descriptor. The existing socket creation method is retained as a fallback if no custom function is provided. Signed-off-by: Andrey Dodonov <Andrey.Dodonov@endress.com>
1 parent 0f8b7b7 commit 6cf7a0b

File tree

2 files changed

+148
-6
lines changed

2 files changed

+148
-6
lines changed

include/zephyr/net/http/service.h

Lines changed: 143 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ struct http_service_runtime_data {
6969
int num_clients;
7070
};
7171

72+
struct http_service_desc;
73+
74+
/** Custom socket creation function type */
75+
typedef int (*http_socket_create_fn)(const struct http_service_desc *svc, int af, int proto);
76+
77+
/** HTTP service configuration */
78+
struct http_service_config {
79+
/** Custom socket creation for the service if needed */
80+
http_socket_create_fn socket_create;
81+
/* If any more service-specific configuration is needed, it can be added here. */
82+
};
83+
7284
struct http_service_desc {
7385
const char *host;
7486
uint16_t *port;
@@ -80,14 +92,15 @@ struct http_service_desc {
8092
struct http_resource_desc *res_begin;
8193
struct http_resource_desc *res_end;
8294
struct http_resource_detail *res_fallback;
95+
const struct http_service_config *config;
8396
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
8497
const sec_tag_t *sec_tag_list;
8598
size_t sec_tag_list_size;
8699
#endif
87100
};
88101

89102
#define __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
90-
_res_fallback, _res_begin, _res_end, ...) \
103+
_res_fallback, _res_begin, _res_end, _config, ...) \
91104
BUILD_ASSERT(_concurrent <= CONFIG_HTTP_SERVER_MAX_CLIENTS, \
92105
"can't accept more then MAX_CLIENTS"); \
93106
BUILD_ASSERT(_backlog > 0, "backlog can't be 0"); \
@@ -104,6 +117,7 @@ struct http_service_desc {
104117
.res_begin = (_res_begin), \
105118
.res_end = (_res_end), \
106119
.res_fallback = (_res_fallback), \
120+
.config = (_config), \
107121
COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS, \
108122
(.sec_tag_list = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (NULL), \
109123
(GET_ARG_N(1, __VA_ARGS__))),), ()) \
@@ -137,7 +151,33 @@ struct http_service_desc {
137151
#define HTTP_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
138152
_res_fallback) \
139153
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
140-
_res_fallback, NULL, NULL)
154+
_res_fallback, NULL, NULL, NULL)
155+
156+
/**
157+
* @brief Define an HTTP service without static resources with custom configuration.
158+
*
159+
* @note The @p _host parameter is used to specify an IP address either in
160+
* IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
161+
* port will listen on all addresses.
162+
*
163+
* @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
164+
* number to use for the service. If the specified port number is zero, then an ephemeral port
165+
* number will be used and the actual port number assigned will be written back to memory. For
166+
* ephemeral port numbers, the memory pointed to by @p _port must be writeable.
167+
*
168+
* @param _name Name of the service.
169+
* @param _host IP address or hostname associated with the service.
170+
* @param[inout] _port Pointer to port associated with the service.
171+
* @param _concurrent Maximum number of concurrent clients. (max. CONFIG_HTTP_SERVER_MAX_CLIENTS)
172+
* @param _backlog Maximum number of queued connections. (min. 1)
173+
* @param _detail User-defined detail associated with the service.
174+
* @param _res_fallback Fallback resource to be served if no other resource matches path
175+
* @param _config Pointer to http_service_config structure
176+
*/
177+
#define HTTP_SERVICE_DEFINE_EMPTY_CONFIG(_name, _host, _port, _concurrent, _backlog, _detail, \
178+
_res_fallback, _config) \
179+
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
180+
_res_fallback, NULL, NULL, _config)
141181

142182
/**
143183
* @brief Define an HTTPS service without static resources.
@@ -164,7 +204,39 @@ struct http_service_desc {
164204
#define HTTPS_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
165205
_res_fallback, _sec_tag_list, _sec_tag_list_size) \
166206
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
167-
_res_fallback, NULL, NULL, \
207+
_res_fallback, NULL, NULL, NULL, \
208+
_sec_tag_list, _sec_tag_list_size); \
209+
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
210+
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
211+
212+
/**
213+
* @brief Define an HTTPS service without static resources with custom configuration.
214+
*
215+
* @note The @p _host parameter is used to specify an IP address either in
216+
* IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
217+
* port will listen on all addresses.
218+
*
219+
* @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
220+
* number to use for the service. If the specified port number is zero, then an ephemeral port
221+
* number will be used and the actual port number assigned will be written back to memory. For
222+
* ephemeral port numbers, the memory pointed to by @p _port must be writeable.
223+
*
224+
* @param _name Name of the service.
225+
* @param _host IP address or hostname associated with the service.
226+
* @param[inout] _port Pointer to port associated with the service.
227+
* @param _concurrent Maximum number of concurrent clients. (max. CONFIG_HTTP_SERVER_MAX_CLIENTS)
228+
* @param _backlog Maximum number of queued connections. (min. 1)
229+
* @param _detail User-defined detail associated with the service.
230+
* @param _res_fallback Fallback resource to be served if no other resource matches path
231+
* @param _config Pointer to http_service_config structure
232+
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
233+
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
234+
*/
235+
#define HTTPS_SERVICE_DEFINE_EMPTY_CONFIG(_name, _host, _port, _concurrent, _backlog, _detail, \
236+
_res_fallback, _config, _sec_tag_list, \
237+
_sec_tag_list_size) \
238+
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
239+
_res_fallback, NULL, NULL, _config, \
168240
_sec_tag_list, _sec_tag_list_size); \
169241
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
170242
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
@@ -195,7 +267,37 @@ struct http_service_desc {
195267
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
196268
_res_fallback, \
197269
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
198-
&_CONCAT(_http_resource_desc_##_name, _list_end)[0]);
270+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], NULL);
271+
272+
/**
273+
* @brief Define an HTTP service with static resources and custom configuration.
274+
*
275+
* @note The @p _host parameter is used to specify an IP address either in
276+
* IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
277+
* port will listen on all addresses.
278+
*
279+
* @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
280+
* number to use for the service. If the specified port number is zero, then an ephemeral port
281+
* number will be used and the actual port number assigned will be written back to memory. For
282+
* ephemeral port numbers, the memory pointed to by @p _port must be writeable.
283+
*
284+
* @param _name Name of the service.
285+
* @param _host IP address or hostname associated with the service.
286+
* @param[inout] _port Pointer to port associated with the service.
287+
* @param _concurrent Maximum number of concurrent clients. (max. CONFIG_HTTP_SERVER_MAX_CLIENTS)
288+
* @param _backlog Maximum number of queued connections. (min. 1)
289+
* @param _detail User-defined detail associated with the service.
290+
* @param _res_fallback Fallback resource to be served if no other resource matches path
291+
* @param _config Pointer to http_service_config structure
292+
*/
293+
#define HTTP_SERVICE_DEFINE_CONFIG(_name, _host, _port, _concurrent, _backlog, _detail, \
294+
_res_fallback, _config) \
295+
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
296+
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
297+
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
298+
_res_fallback, \
299+
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
300+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config);
199301

200302
/**
201303
* @brief Define an HTTPS service with static resources.
@@ -226,7 +328,43 @@ struct http_service_desc {
226328
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
227329
_res_fallback, \
228330
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
229-
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], \
331+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], NULL, \
332+
_sec_tag_list, _sec_tag_list_size); \
333+
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
334+
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
335+
336+
/**
337+
* @brief Define an HTTPS service with static resources and custom configuration.
338+
*
339+
* @note The @p _host parameter is used to specify an IP address either in
340+
* IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
341+
* port will listen on all addresses.
342+
*
343+
* @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
344+
* number to use for the service. If the specified port number is zero, then an ephemeral port
345+
* number will be used and the actual port number assigned will be written back to memory. For
346+
* ephemeral port numbers, the memory pointed to by @p _port must be writeable.
347+
*
348+
* @param _name Name of the service.
349+
* @param _host IP address or hostname associated with the service.
350+
* @param[inout] _port Pointer to port associated with the service.
351+
* @param _concurrent Maximum number of concurrent clients. (max. CONFIG_HTTP_SERVER_MAX_CLIENTS)
352+
* @param _backlog Maximum number of queued connections. (min. 1)
353+
* @param _detail User-defined detail associated with the service.
354+
* @param _res_fallback Fallback resource to be served if no other resource matches path
355+
* @param _config Pointer to http_service_config structure
356+
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
357+
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
358+
*/
359+
#define HTTPS_SERVICE_DEFINE_CONFIG(_name, _host, _port, _concurrent, _backlog, _detail, \
360+
_res_fallback, _config, _sec_tag_list, \
361+
_sec_tag_list_size) \
362+
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
363+
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
364+
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
365+
_res_fallback, \
366+
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
367+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config, \
230368
_sec_tag_list, _sec_tag_list_size); \
231369
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
232370
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")

subsys/net/lib/http/http_server_core.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ int http_server_init(struct http_server_ctx *ctx)
156156
proto = IPPROTO_TCP;
157157
}
158158

159-
fd = zsock_socket(af, SOCK_STREAM, proto);
159+
if (svc->config != NULL && svc->config->socket_creat != NULL) {
160+
fd = svc->config->socket_create(svc, af, proto);
161+
} else {
162+
fd = zsock_socket(af, SOCK_STREAM, proto);
163+
}
160164
if (fd < 0) {
161165
LOG_ERR("socket: %d", errno);
162166
failed++;

0 commit comments

Comments
 (0)