1 /********************************************************************************
2 * @file sl_si91x_socket_utility.h
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29
30 #pragma once
31
32 #include "sl_si91x_types.h"
33 #include "sl_si91x_socket_types.h"
34 #include "sl_si91x_protocol_types.h"
35 #include "sl_si91x_socket_constants.h"
36 #include "errno.h"
37 #include <stdbool.h>
38
39 #define SET_ERROR_AND_RETURN(error) \
40 do { \
41 if (PRINT_ERROR_LOGS) { \
42 PRINT_ERROR_STATUS(ERROR_TAG, error); \
43 } \
44 errno = error; \
45 return -1; \
46 } while (0)
47
48 #define SET_ERRNO_AND_RETURN_IF_TRUE(condition, errno_value) \
49 do { \
50 if (condition) { \
51 if (PRINT_ERROR_LOGS) { \
52 PRINT_ERROR_STATUS(ERROR_TAG, errno_value); \
53 } \
54 errno = errno_value; \
55 return -1; \
56 } \
57 } while (0)
58
59 #define SOCKET_VERIFY_STATUS_AND_RETURN(status, expected_status, errno_value) \
60 do { \
61 if (status != expected_status) { \
62 if (PRINT_ERROR_LOGS) { \
63 PRINT_ERROR_STATUS(ERROR_TAG, errno_value); \
64 } \
65 errno = errno_value; \
66 return -1; \
67 } \
68 } while (0)
69
70 #define SLI_SI91X_NULL_SAFE_FD_ZERO(fd_set) \
71 do { \
72 if (NULL != fd_set) { \
73 SL_SI91X_FD_ZERO(fd_set); \
74 } \
75 } while (0)
76
77 #define GET_SAFE_MEMCPY_LENGTH(destination_size, source_size) \
78 source_size > destination_size ? destination_size : source_size
79
80 extern sli_si91x_socket_t *sli_si91x_sockets[NUMBER_OF_SOCKETS];
81
82 sl_status_t sli_si91x_socket_init(uint8_t max_select_count);
83
84 sl_status_t sli_si91x_socket_deinit(void);
85
86 sl_status_t sli_si91x_vap_shutdown(uint8_t vap_id);
87
88 /**
89 * @addtogroup SOCKET_CONFIGURATION_FUNCTION
90 * @{
91 */
92 /**
93 * @brief SiWx91x Socket Configuration
94 *
95 * The structure defines the configuration parameters for SiWx91x sockets.
96 * It includes settings for the total number of sockets, TCP and UDP socket
97 * configurations, and performance-related parameters.
98 */
99 typedef struct {
100 uint8_t total_sockets; ///< Total number of sockets (that includes BSD, IoT, Si91x)
101
102 uint8_t total_tcp_sockets; ///< Total number of TCP sockets
103
104 uint8_t total_udp_sockets; ///< Total number of UDP sockets
105
106 uint8_t tcp_tx_only_sockets; ///< Number of TCP sockets intended for transmission (TX)
107
108 uint8_t tcp_rx_only_sockets; ///< Number of TCP sockets intended for reception (RX)
109
110 uint8_t udp_tx_only_sockets; ///< Number of UDP sockets intended for transmission (TX)
111
112 uint8_t udp_rx_only_sockets; ///< Number of UDP sockets intended for reception (RX)
113
114 uint8_t tcp_rx_high_performance_sockets; ///< Total number of high-performance TCP RX sockets
115
116 uint8_t
117 tcp_rx_window_size_cap; ///< TCP RX window size cap, scales window size linearly (TCP MSS * TCP_RX_WINDOW_SIZE_CAP)
118
119 uint8_t tcp_rx_window_div_factor; ///< TCP RX window division factor, increases ACK frequency for asynchronous sockets
120 } sl_si91x_socket_config_t;
121
122 /// SiWx91x specific socket type length value
123 typedef struct {
124 uint16_t type; ///< Socket type
125 uint16_t length; ///< Data length
126 uint8_t value[]; ///< Data
127 } sl_si91x_socket_type_length_value_t;
128
129 /** @} */
130
131 /**
132 * @addtogroup SOCKET_CONFIGURATION_FUNCTION
133 * @{
134 */
135
136 /**
137 * @brief
138 * Configures SiWx91x specific socket settings.
139 *
140 * @details
141 * This function sets up the socket configuration specific to the SiWx91x.
142 * It must be called before invoking @ref sl_si91x_socket_async.
143 * The configuration includes setting parameters such as socket type,
144 * protocol, and other options specific to the SiWx91x series.
145 *
146 * @pre Pre-conditions:
147 * - Ensure that the necessary initialization for the SiWx91x module has been completed.
148 * - This API is called before calling @ref sl_si91x_socket_async.
149 *
150 * @param[in] socket_config
151 * Socket configuration of type @ref sl_si91x_socket_config_t.
152 *
153 * @return
154 * sl_status_t. See https://docs.silabs.com/gecko-platform/latest/platform-common/status for details.
155 *
156 ******************************************************************************/
157 sl_status_t sl_si91x_config_socket(sl_si91x_socket_config_t socket_config);
158
159 /** @} */
160
161 /**
162 * A internal function to reset the socket.
163 * @param socket socket FD which needs to be reset.
164 */
165 void reset_socket_state(int socket);
166
167 /**
168 * A internal function to get sl_si91x_socket structure based on socket FD sent
169 * @param socket
170 * Socket FD whose structure is required.
171 * @param index
172 * Socket FD index number.
173 * @return
174 * sl_si91x_socket or NULL in case of invalid FD.
175 */
176 void get_free_socket(sli_si91x_socket_t **socket, int *index);
177
178 /**
179 * A internal function to get free socket.
180 * @param socket_id
181 * Socket ID.
182 */
183 sli_si91x_socket_t *get_si91x_socket(int32_t socket_id);
184
185 sl_status_t sli_si91x_add_tls_extension(sli_si91x_tls_extensions_t *socket_tls_extensions,
186 const sl_si91x_socket_type_length_value_t *tls_extension);
187
188 sl_status_t create_and_send_socket_request(int socketIdIndex, int type, const int *backlog);
189
190 int sli_si91x_socket(int family, int type, int protocol, sl_si91x_socket_receive_data_callback_t callback);
191
192 int sli_si91x_shutdown(int socket, int how);
193
194 int sli_si91x_connect(int socket, const struct sockaddr *addr, socklen_t addr_len);
195
196 int sli_si91x_bind(int socket, const struct sockaddr *addr, socklen_t addr_len);
197
198 int sli_si91x_accept(int socket,
199 struct sockaddr *addr,
200 socklen_t *addr_len,
201 sl_si91x_socket_accept_callback_t callback);
202
203 int sli_si91x_select(int nfds,
204 sl_si91x_fd_set *readfds,
205 sl_si91x_fd_set *writefds,
206 sl_si91x_fd_set *exceptfds,
207 const struct timeval *timeout,
208 sl_si91x_socket_select_callback_t callback);
209
210 void handle_accept_response(sli_si91x_socket_t *si91x_client_socket, const sl_si91x_rsp_ltcp_est_t *accept_response);
211
212 int handle_select_response(const sl_si91x_socket_select_rsp_t *response,
213 sl_si91x_fd_set *readfds,
214 sl_si91x_fd_set *writefds,
215 sl_si91x_fd_set *exception_fd);
216
217 uint8_t sli_si91x_socket_identification_function_based_on_socketid(sl_wifi_buffer_t *buffer, void *user_data);
218
219 void set_select_callback(sl_si91x_socket_select_callback_t callback);
220
221 void sli_si91x_set_accept_callback(sli_si91x_socket_t *server_socket,
222 sl_si91x_socket_accept_callback_t callback,
223 int32_t client_socket_id);
224
225 void sli_si91x_set_remote_socket_termination_callback(sl_si91x_socket_remote_termination_callback_t callback);
226
227 sl_status_t sli_si91x_send_socket_command(sli_si91x_socket_t *socket,
228 uint32_t command,
229 const void *data,
230 uint32_t data_length,
231 uint32_t wait_period,
232 sl_wifi_buffer_t **response_buffer);
233
234 int sli_si91x_get_socket_id(sl_si91x_packet_t *packet);
235
236 /**
237 * A internal function to find a socket with the matching ID and not in the exlcuded_state
238 * @param socket_id Socket ID
239 * @param excluded_state The socket state that the socket must not be
240 * @param role Socket role
241 */
242 sli_si91x_socket_t *sli_si91x_get_socket_from_id(int socket_id,
243 sli_si91x_bsd_socket_state_t excluded_state,
244 int16_t role);
245
246 sl_status_t sli_si91x_send_socket_data(sli_si91x_socket_t *si91x_socket,
247 const sli_si91x_socket_send_request_t *request,
248 const void *data);
249 int32_t sli_get_socket_command_from_host_packet(sl_wifi_buffer_t *buffer);
250
251 void sli_si91x_set_socket_event(uint32_t event_mask);
252
253 sl_status_t sli_si91x_flush_select_request_table(uint16_t error_code);
SL_SI91X_FD_CLR(unsigned int n,sl_si91x_fd_set * p)254 static inline void SL_SI91X_FD_CLR(unsigned int n, sl_si91x_fd_set *p)
255 {
256 p->__fds_bits &= ~(1U << n);
257 }
258
SL_SI91X_FD_SET(unsigned int n,sl_si91x_fd_set * p)259 static inline void SL_SI91X_FD_SET(unsigned int n, sl_si91x_fd_set *p)
260 {
261 p->__fds_bits |= 1U << n;
262 }
263
SL_SI91X_FD_ISSET(unsigned int n,sl_si91x_fd_set * p)264 static inline bool SL_SI91X_FD_ISSET(unsigned int n, sl_si91x_fd_set *p)
265 {
266 return p->__fds_bits & (1U << n);
267 }
268
SL_SI91X_FD_ZERO(sl_si91x_fd_set * p)269 static inline void SL_SI91X_FD_ZERO(sl_si91x_fd_set *p)
270 {
271 p->__fds_bits = 0;
272 }
273