Line data Source code
1 1 : /*
2 : * Copyright (c) 2022 Meta
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_
8 : #define ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_
9 :
10 : /**
11 : * @file service.h
12 : *
13 : * @brief HTTP service API
14 : *
15 : * @defgroup http_service HTTP service API
16 : * @since 3.4
17 : * @version 0.1.0
18 : * @ingroup networking
19 : * @{
20 : */
21 :
22 : #include <stdint.h>
23 : #include <stddef.h>
24 :
25 : #include <zephyr/sys/util_macro.h>
26 : #include <zephyr/sys/iterable_sections.h>
27 : #include <zephyr/net/tls_credentials.h>
28 :
29 : #ifdef __cplusplus
30 : extern "C" {
31 : #endif
32 :
33 : /** HTTP resource description */
34 1 : struct http_resource_desc {
35 : /** Resource name */
36 1 : const char *resource;
37 : /** Detail associated with this resource */
38 1 : void *detail;
39 : };
40 :
41 : /**
42 : * @brief Define a static HTTP resource
43 : *
44 : * A static HTTP resource is one that is known prior to system initialization. In contrast,
45 : * dynamic resources may be discovered upon system initialization. Dynamic resources may also be
46 : * inserted, or removed by events originating internally or externally to the system at runtime.
47 : *
48 : * @note The @p _resource is the URL without the associated protocol, host, or URL parameters. E.g.
49 : * the resource for `http://www.foo.com/bar/baz.html#param1=value1` would be `/bar/baz.html`. It
50 : * is often referred to as the "path" of the URL. Every `(service, resource)` pair should be
51 : * unique. The @p _resource must be non-NULL.
52 : *
53 : * @param _name Name of the resource.
54 : * @param _service Name of the associated service.
55 : * @param _resource Pathname-like string identifying the resource.
56 : * @param _detail Implementation-specific detail associated with the resource.
57 : */
58 1 : #define HTTP_RESOURCE_DEFINE(_name, _service, _resource, _detail) \
59 : const STRUCT_SECTION_ITERABLE_ALTERNATE(http_resource_desc_##_service, http_resource_desc, \
60 : _name) = { \
61 : .resource = _resource, \
62 : .detail = (void *)(_detail), \
63 : }
64 :
65 : /** @cond INTERNAL_HIDDEN */
66 :
67 : struct http_service_desc {
68 : const char *host;
69 : uint16_t *port;
70 : void *detail;
71 : size_t concurrent;
72 : size_t backlog;
73 : struct http_resource_desc *res_begin;
74 : struct http_resource_desc *res_end;
75 : #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
76 : const sec_tag_t *sec_tag_list;
77 : size_t sec_tag_list_size;
78 : #endif
79 : };
80 :
81 : #define __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, _res_begin, \
82 : _res_end, ...) \
83 : const STRUCT_SECTION_ITERABLE(http_service_desc, _name) = { \
84 : .host = _host, \
85 : .port = (uint16_t *)(_port), \
86 : .detail = (void *)(_detail), \
87 : .concurrent = (_concurrent), \
88 : .backlog = (_backlog), \
89 : .res_begin = (_res_begin), \
90 : .res_end = (_res_end), \
91 : COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS, \
92 : (.sec_tag_list = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (NULL), \
93 : (GET_ARG_N(1, __VA_ARGS__))),), ()) \
94 : COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS, \
95 : (.sec_tag_list_size = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (0),\
96 : (GET_ARG_N(1, GET_ARGS_LESS_N(1, __VA_ARGS__))))), ())\
97 : }
98 :
99 : /** @endcond */
100 :
101 : /**
102 : * @brief Define an HTTP service without static resources.
103 : *
104 : * @note The @p _host parameter is used to specify an IP address either in
105 : * IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
106 : * port will listen on all addresses.
107 : *
108 : * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
109 : * number to use for the service. If the specified port number is zero, then an ephemeral port
110 : * number will be used and the actual port number assigned will be written back to memory. For
111 : * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
112 : *
113 : * @param _name Name of the service.
114 : * @param _host IP address or hostname associated with the service.
115 : * @param[inout] _port Pointer to port associated with the service.
116 : * @param _concurrent Maximum number of concurrent clients.
117 : * @param _backlog Maximum number queued connections.
118 : * @param _detail Implementation-specific detail associated with the service.
119 : */
120 1 : #define HTTP_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail) \
121 : __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, NULL, NULL)
122 :
123 : /**
124 : * @brief Define an HTTPS service without static resources.
125 : *
126 : * @note The @p _host parameter is used to specify an IP address either in
127 : * IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
128 : * port will listen on all addresses.
129 : *
130 : * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
131 : * number to use for the service. If the specified port number is zero, then an ephemeral port
132 : * number will be used and the actual port number assigned will be written back to memory. For
133 : * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
134 : *
135 : * @param _name Name of the service.
136 : * @param _host IP address or hostname associated with the service.
137 : * @param[inout] _port Pointer to port associated with the service.
138 : * @param _concurrent Maximum number of concurrent clients.
139 : * @param _backlog Maximum number queued connections.
140 : * @param _detail Implementation-specific detail associated with the service.
141 : * @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
142 : * @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
143 : */
144 : #define HTTPS_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
145 1 : _sec_tag_list, _sec_tag_list_size) \
146 : __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, NULL, NULL, \
147 : _sec_tag_list, _sec_tag_list_size); \
148 : BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
149 : "TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
150 :
151 : /**
152 : * @brief Define an HTTP service with static resources.
153 : *
154 : * @note The @p _host parameter is used to specify an IP address either in
155 : * IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
156 : * port will listen on all addresses.
157 : *
158 : * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
159 : * number to use for the service. If the specified port number is zero, then an ephemeral port
160 : * number will be used and the actual port number assigned will be written back to memory. For
161 : * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
162 : *
163 : * @param _name Name of the service.
164 : * @param _host IP address or hostname associated with the service.
165 : * @param[inout] _port Pointer to port associated with the service.
166 : * @param _concurrent Maximum number of concurrent clients.
167 : * @param _backlog Maximum number queued connections.
168 : * @param _detail Implementation-specific detail associated with the service.
169 : */
170 1 : #define HTTP_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail) \
171 : extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
172 : extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
173 : __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
174 : &_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
175 : &_CONCAT(_http_resource_desc_##_name, _list_end)[0])
176 :
177 : /**
178 : * @brief Define an HTTPS service with static resources.
179 : *
180 : * @note The @p _host parameter is used to specify an IP address either in
181 : * IPv4 or IPv6 format a fully-qualified hostname or a virtual host. If left NULL, the listening
182 : * port will listen on all addresses.
183 : *
184 : * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
185 : * number to use for the service. If the specified port number is zero, then an ephemeral port
186 : * number will be used and the actual port number assigned will be written back to memory. For
187 : * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
188 : *
189 : * @param _name Name of the service.
190 : * @param _host IP address or hostname associated with the service.
191 : * @param[inout] _port Pointer to port associated with the service.
192 : * @param _concurrent Maximum number of concurrent clients.
193 : * @param _backlog Maximum number queued connections.
194 : * @param _detail Implementation-specific detail associated with the service.
195 : * @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
196 : * @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
197 : */
198 : #define HTTPS_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, \
199 1 : _sec_tag_list, _sec_tag_list_size) \
200 : extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
201 : extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
202 : __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
203 : &_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
204 : &_CONCAT(_http_resource_desc_##_name, _list_end)[0], \
205 : _sec_tag_list, _sec_tag_list_size); \
206 : BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
207 : "TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
208 :
209 : /**
210 : * @brief Count the number of HTTP services.
211 : *
212 : * @param[out] _dst Pointer to location where result is written.
213 : */
214 1 : #define HTTP_SERVICE_COUNT(_dst) STRUCT_SECTION_COUNT(http_service_desc, _dst)
215 :
216 : /**
217 : * @brief Count HTTP service static resources.
218 : *
219 : * @param _service Pointer to a service.
220 : */
221 1 : #define HTTP_SERVICE_RESOURCE_COUNT(_service) ((_service)->res_end - (_service)->res_begin)
222 :
223 : /**
224 : * @brief Iterate over all HTTP services.
225 : *
226 : * @param _it Name of http_service_desc iterator
227 : */
228 1 : #define HTTP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(http_service_desc, _it)
229 :
230 : /**
231 : * @brief Iterate over static HTTP resources associated with a given @p _service.
232 : *
233 : * @note This macro requires that @p _service is defined with @ref HTTP_SERVICE_DEFINE.
234 : *
235 : * @param _service Name of HTTP service
236 : * @param _it Name of iterator (of type @ref http_resource_desc)
237 : */
238 1 : #define HTTP_RESOURCE_FOREACH(_service, _it) \
239 : STRUCT_SECTION_FOREACH_ALTERNATE(http_resource_desc_##_service, http_resource_desc, _it)
240 :
241 : /**
242 : * @brief Iterate over all static resources associated with @p _service .
243 : *
244 : * @note This macro is suitable for a @p _service defined with either @ref HTTP_SERVICE_DEFINE
245 : * or @ref HTTP_SERVICE_DEFINE_EMPTY.
246 : *
247 : * @param _service Pointer to HTTP service
248 : * @param _it Name of iterator (of type @ref http_resource_desc)
249 : */
250 1 : #define HTTP_SERVICE_FOREACH_RESOURCE(_service, _it) \
251 : for (struct http_resource_desc *_it = (_service)->res_begin; ({ \
252 : __ASSERT(_it <= (_service)->res_end, "unexpected list end location"); \
253 : _it < (_service)->res_end; \
254 : }); \
255 : _it++)
256 :
257 : #ifdef __cplusplus
258 : }
259 : #endif
260 :
261 : /**
262 : * @}
263 : */
264 :
265 : #endif /* ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ */
|