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_ */