Line data Source code
1 1 : /**
2 : * @file
3 : * @brief BSD Socket service API
4 : *
5 : * API can be used to install a k_work that is called
6 : * if there is data received to a socket.
7 : */
8 :
9 : /*
10 : * Copyright (c) 2023 Nordic Semiconductor ASA
11 : *
12 : * SPDX-License-Identifier: Apache-2.0
13 : */
14 :
15 : #ifndef ZEPHYR_INCLUDE_NET_SOCKET_SERVICE_H_
16 : #define ZEPHYR_INCLUDE_NET_SOCKET_SERVICE_H_
17 :
18 : /**
19 : * @brief BSD socket service API
20 : * @defgroup bsd_socket_service BSD socket service API
21 : * @since 3.6
22 : * @version 0.2.0
23 : * @ingroup networking
24 : * @{
25 : */
26 :
27 : #include <sys/types.h>
28 : #include <zephyr/types.h>
29 : #include <zephyr/net/socket.h>
30 :
31 : #ifdef __cplusplus
32 : extern "C" {
33 : #endif
34 :
35 : struct net_socket_service_event;
36 :
37 : /** @brief The signature for a net socket service handler function.
38 : *
39 : * The function will be invoked by the socket service.
40 : *
41 : * @param pev the socket service event that provided the handler.
42 : */
43 1 : typedef void (*net_socket_service_handler_t)(struct net_socket_service_event *pev);
44 :
45 : /**
46 : * This struct contains information which socket triggered
47 : * calls to the callback function.
48 : */
49 1 : struct net_socket_service_event {
50 : /** Callback to be called for desired socket activity */
51 1 : net_socket_service_handler_t callback;
52 : /** Socket information that triggered this event. */
53 1 : struct zsock_pollfd event;
54 : /** User data */
55 1 : void *user_data;
56 : /** Service back pointer */
57 1 : struct net_socket_service_desc *svc;
58 : };
59 :
60 : /**
61 : * Main structure holding socket service configuration information.
62 : * The k_work item is created so that when there is data coming
63 : * to those fds, the k_work callback is then called.
64 : * The workqueue can be set NULL in which case system workqueue is used.
65 : * The service descriptor should be created at built time, and then used
66 : * as a parameter to register the sockets to be monitored.
67 : * User should create needed sockets and then setup the poll struct and
68 : * then register the sockets to be monitored at runtime.
69 : */
70 1 : struct net_socket_service_desc {
71 : #if CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG
72 : /**
73 : * Owner name. This can be used in debugging to see who has
74 : * registered this service.
75 : */
76 1 : const char *owner;
77 : #endif
78 : /** Pointer to the list of services that we are listening */
79 1 : struct net_socket_service_event *pev;
80 : /** Length of the pollable socket array for this service. */
81 1 : int pev_len;
82 : /** Where are my pollfd entries in the global list */
83 1 : int *idx;
84 : };
85 :
86 : /** @cond INTERNAL_HIDDEN */
87 :
88 : #define __z_net_socket_svc_get_name(_svc_id) __z_net_socket_service_##_svc_id
89 : #define __z_net_socket_svc_get_idx(_svc_id) __z_net_socket_service_idx_##_svc_id
90 : #define __z_net_socket_svc_get_owner __FILE__ ":" STRINGIFY(__LINE__)
91 :
92 : #if CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG
93 : #define NET_SOCKET_SERVICE_OWNER .owner = __z_net_socket_svc_get_owner,
94 : #else
95 : #define NET_SOCKET_SERVICE_OWNER
96 : #endif
97 :
98 : #define __z_net_socket_service_define(_name, _cb, _count, ...) \
99 : static int __z_net_socket_svc_get_idx(_name); \
100 : static struct net_socket_service_event \
101 : __z_net_socket_svc_get_name(_name)[_count] = { \
102 : [0 ... ((_count) - 1)] = { \
103 : .event.fd = -1, /* Invalid socket */ \
104 : .callback = _cb, \
105 : } \
106 : }; \
107 : COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (), __VA_ARGS__) \
108 : const STRUCT_SECTION_ITERABLE(net_socket_service_desc, _name) = { \
109 : NET_SOCKET_SERVICE_OWNER \
110 : .pev = __z_net_socket_svc_get_name(_name), \
111 : .pev_len = (_count), \
112 : .idx = &__z_net_socket_svc_get_idx(_name), \
113 : }
114 :
115 : /** @endcond */
116 :
117 : /**
118 : * @brief Statically define a network socket service.
119 : * The user callback is called synchronously for this service meaning that
120 : * the service API will wait until the user callback returns before continuing
121 : * with next socket service.
122 : *
123 : * The socket service can be accessed outside the module where it is defined using:
124 : *
125 : * @code extern struct net_socket_service_desc <name>; @endcode
126 : *
127 : * @note This macro cannot be used together with a static keyword.
128 : * If such a use-case is desired, use NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC
129 : * instead.
130 : *
131 : * @param name Name of the service.
132 : * @param cb Callback function that is called for socket activity.
133 : * @param count How many pollable sockets is needed for this service.
134 : */
135 1 : #define NET_SOCKET_SERVICE_SYNC_DEFINE(name, cb, count) \
136 : __z_net_socket_service_define(name, cb, count)
137 :
138 : /**
139 : * @brief Statically define a network socket service in a private (static) scope.
140 : * The user callback is called synchronously for this service meaning that
141 : * the service API will wait until the user callback returns before continuing
142 : * with next socket service.
143 : *
144 : * @param name Name of the service.
145 : * @param cb Callback function that is called for socket activity.
146 : * @param count How many pollable sockets is needed for this service.
147 : */
148 1 : #define NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(name, cb, count) \
149 : __z_net_socket_service_define(name, cb, count, static)
150 :
151 : /**
152 : * @brief Register pollable sockets.
153 : *
154 : * @param service Pointer to a service description.
155 : * @param fds Socket array to poll.
156 : * @param len Length of the socket array.
157 : * @param user_data User specific data.
158 : *
159 : * @retval 0 No error
160 : * @retval -ENOENT Service is not found.
161 : * @retval -ENINVAL Invalid parameter.
162 : */
163 1 : __syscall int net_socket_service_register(const struct net_socket_service_desc *service,
164 : struct zsock_pollfd *fds, int len, void *user_data);
165 :
166 : /**
167 : * @brief Unregister pollable sockets.
168 : *
169 : * @param service Pointer to a service description.
170 : *
171 : * @retval 0 No error
172 : * @retval -ENOENT Service is not found.
173 : * @retval -ENINVAL Invalid parameter.
174 : */
175 1 : static inline int net_socket_service_unregister(const struct net_socket_service_desc *service)
176 : {
177 : return net_socket_service_register(service, NULL, 0, NULL);
178 : }
179 :
180 : /**
181 : * @typedef net_socket_service_cb_t
182 : * @brief Callback used while iterating over socket services.
183 : *
184 : * @param svc Pointer to current socket service.
185 : * @param user_data A valid pointer to user data or NULL
186 : */
187 1 : typedef void (*net_socket_service_cb_t)(const struct net_socket_service_desc *svc,
188 : void *user_data);
189 :
190 : /**
191 : * @brief Go through all the socket services and call callback for each service.
192 : *
193 : * @param cb User-supplied callback function to call
194 : * @param user_data User specified data
195 : */
196 1 : void net_socket_service_foreach(net_socket_service_cb_t cb, void *user_data);
197 :
198 : #ifdef __cplusplus
199 : }
200 : #endif
201 :
202 : #include <zephyr/syscalls/socket_service.h>
203 :
204 : /**
205 : * @}
206 : */
207 :
208 : #endif /* ZEPHYR_INCLUDE_NET_SOCKET_SERVICE_H_ */
|