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