bsd_socket_misc.c
Go to the documentation of this file.
1 /**
2  * @file bsd_socket_misc.c
3  * @brief Helper function for BSD socket API
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL BSD_SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/bsd_socket.h"
37 #include "core/bsd_socket_misc.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (BSD_SOCKET_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Get first ancillary data header
46  * @param[in] msg Pointer to the message header
47  * @return Pointer to the first ancillary data header
48  **/
49 
50 struct cmsghdr *socketCmsgFirstHdr(struct msghdr *msg)
51 {
52  CMSGHDR *first;
53 
54  //Initialize pointer
55  first = NULL;
56 
57  //Check parameter
58  if(msg != NULL)
59  {
60  //Check the length of the ancillary data buffer
61  if(msg->msg_controllen >= sizeof(CMSGHDR))
62  {
63  //Point to the first ancillary data header
64  first = (CMSGHDR *) msg->msg_control;
65  }
66  }
67 
68  //Return a pointer to the first ancillary data header
69  return first;
70 }
71 
72 
73 /**
74  * @brief Get next ancillary data header
75  * @param[in] msg Pointer to the message header
76  * @param[in] cmsg Pointer to the current ancillary data header
77  * @return Pointer to the next ancillary data header
78  **/
79 
80 struct cmsghdr *socketCmsgNextHdr(struct msghdr *msg, struct cmsghdr *cmsg)
81 {
82  size_t n;
83  CMSGHDR *next;
84 
85  //Initialize pointer
86  next = NULL;
87 
88  //Check parameters
89  if(msg != NULL && cmsg != NULL)
90  {
91  //Valid ancillary data header?
92  if(cmsg->cmsg_len >= sizeof(CMSGHDR) &&
93  cmsg->cmsg_len <= msg->msg_controllen)
94  {
95  //Offset to the next ancillary data header
96  n = (uint8_t *) cmsg - (uint8_t *) msg->msg_control +
97  CMSG_ALIGN(cmsg->cmsg_len);
98 
99  //Check the length of the ancillary data buffer
100  if((n + sizeof(CMSGHDR)) <= msg->msg_controllen)
101  {
102  //Point to the next ancillary data header
103  next = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
104  }
105  }
106  }
107 
108  //Return a pointer to the next ancillary data header
109  return next;
110 }
111 
112 
113 /**
114  * @brief Initializes a descriptor set
115  * @param[in] fds Pointer to a descriptor set
116  **/
117 
119 {
120  //Reset the descriptor count
121  fds->fd_count = 0;
122 }
123 
124 
125 /**
126  * @brief Add a descriptor to an existing set
127  * @param[in] fds Pointer to a descriptor set
128  * @param[in] s Descriptor that identifies the socket to add
129  **/
130 
132 {
133  int_t i;
134 
135  //Loop through descriptors
136  for(i = 0; i < fds->fd_count; i++)
137  {
138  //The specified descriptor is already set?
139  if(fds->fd_array[i] == s)
140  return;
141  }
142 
143  //Ensure the descriptor set is not full
144  if(i < FD_SETSIZE)
145  {
146  //The specified descriptor can be safely added
147  fds->fd_array[i] = s;
148  //Adjust the size of the descriptor set
149  fds->fd_count++;
150  }
151 }
152 
153 
154 /**
155  * @brief Remove a descriptor from an existing set
156  * @param[in] fds Pointer to a descriptor set
157  * @param[in] s Descriptor that identifies the socket to remove
158  **/
159 
161 {
162  int_t i;
163  int_t j;
164 
165  //Loop through descriptors
166  for(i = 0; i < fds->fd_count; i++)
167  {
168  //Specified descriptor found?
169  if(fds->fd_array[i] == s)
170  {
171  //Adjust the size of the descriptor set
172  fds->fd_count--;
173 
174  //Remove the entry from the descriptor set
175  for(j = i; j < fds->fd_count; j++)
176  {
177  fds->fd_array[j] = fds->fd_array[j + 1];
178  }
179 
180  //Return immediately
181  return;
182  }
183  }
184 }
185 
186 
187 /**
188  * @brief Check whether a descriptor is set
189  * @param[in] fds Pointer to a descriptor set
190  * @param[in] s Descriptor that identifies the socket to test
191  * @return Nonzero if s is a member of the set. Otherwise, zero
192  **/
193 
195 {
196  int_t i;
197 
198  //Loop through descriptors
199  for(i = 0; i < fds->fd_count; i++)
200  {
201  //Check whether the specified descriptor is set
202  if(fds->fd_array[i] == s)
203  {
204  return TRUE;
205  }
206  }
207 
208  //The specified descriptor is not currently set
209  return FALSE;
210 }
211 
212 
213 /**
214  * @brief Set BSD error code
215  * @param[in] socket Handle that identifies a socket
216  * @param[in] errnoCode BSD error code
217  **/
218 
220 {
221  //Valid socket handle?
222  if(socket != NULL)
223  {
224  //Save error code
225  socket->errnoCode = errnoCode;
226  }
227 
228  //Save the code of the last error
229  BSD_SOCKET_SET_ERRNO(errnoCode);
230 }
231 
232 
233 /**
234  * @brief Translate error code
235  * @param[in] socket Handle that identifies a socket
236  * @param[in] errorCode Error code
237  **/
238 
240 {
241  uint_t errnoCode;
242 
243  //Translate error code
244  switch(errorCode)
245  {
246  case NO_ERROR:
247  errnoCode = 0;
248  break;
249 
250  case ERROR_TIMEOUT:
251  errnoCode = EWOULDBLOCK;
252  break;
253 
255  errnoCode = EINVAL;
256  break;
257 
259  errnoCode = ECONNRESET;
260  break;
261 
263  errnoCode = EISCONN;
264  break;
265 
266  case ERROR_NOT_CONNECTED:
267  errnoCode = ENOTCONN;
268  break;
269 
271  errnoCode = ESHUTDOWN;
272  break;
273 
275  errnoCode = ECONNREFUSED;
276  break;
277 
279  errnoCode = EMSGSIZE;
280  break;
281 
282  default:
283  errnoCode = EFAULT;
284  break;
285  }
286 
287  //Valid socket handle?
288  if(socket != NULL)
289  {
290  //Save error code
291  socket->errnoCode = errnoCode;
292  }
293 
294  //Save the code of the last error
295  BSD_SOCKET_SET_ERRNO(errnoCode);
296 }
297 
298 #endif
int_t socket(int_t family, int_t type, int_t protocol)
Create a socket that is bound to a specific transport service provider.
Definition: bsd_socket.c:65
BSD socket API.
#define EISCONN
Definition: bsd_socket.h:251
#define ESHUTDOWN
Definition: bsd_socket.h:253
#define EINVAL
Definition: bsd_socket.h:244
#define EFAULT
Definition: bsd_socket.h:243
#define EWOULDBLOCK
Definition: bsd_socket.h:242
#define FD_SETSIZE
Definition: bsd_socket.h:43
#define CMSG_ALIGN(len)
Definition: bsd_socket.h:516
#define ECONNREFUSED
Definition: bsd_socket.h:254
#define BSD_SOCKET_SET_ERRNO(e)
Definition: bsd_socket.h:50
#define ECONNRESET
Definition: bsd_socket.h:250
#define EMSGSIZE
Definition: bsd_socket.h:248
#define ENOTCONN
Definition: bsd_socket.h:252
void socketFdClr(fd_set *fds, int_t s)
Remove a descriptor from an existing set.
void socketTranslateErrorCode(Socket *socket, error_t errorCode)
Translate error code.
void socketFdSet(fd_set *fds, int_t s)
Add a descriptor to an existing set.
void socketSetErrnoCode(Socket *socket, uint_t errnoCode)
Set BSD error code.
struct cmsghdr * socketCmsgFirstHdr(struct msghdr *msg)
Get first ancillary data header.
int_t socketFdIsSet(fd_set *fds, int_t s)
Check whether a descriptor is set.
void socketFdZero(fd_set *fds)
Initializes a descriptor set.
struct cmsghdr * socketCmsgNextHdr(struct msghdr *msg, struct cmsghdr *cmsg)
Get next ancillary data header.
Helper function for BSD socket API.
signed int int_t
Definition: compiler_port.h:49
unsigned int uint_t
Definition: compiler_port.h:50
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_CONNECTION_FAILED
Definition: error.h:76
@ ERROR_CONNECTION_CLOSING
Definition: error.h:78
@ ERROR_TIMEOUT
Definition: error.h:95
@ ERROR_MESSAGE_TOO_LONG
Definition: error.h:136
@ ERROR_NOT_CONNECTED
Definition: error.h:80
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_CONNECTION_RESET
Definition: error.h:79
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_ALREADY_CONNECTED
Definition: error.h:82
uint16_t next
Definition: ipv4_frag.h:106
uint8_t s
Definition: ndp.h:345
TCP/IP stack core.
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define Socket
Definition: socket.h:36
Ancillary data header.
Definition: bsd_socket.h:426
size_t cmsg_len
Definition: bsd_socket.h:427
Set of sockets.
Definition: bsd_socket.h:460
int_t fd_count
Definition: bsd_socket.h:461
int_t fd_array[FD_SETSIZE]
Definition: bsd_socket.h:462
Message header.
Definition: bsd_socket.h:410
size_t msg_controllen
Definition: bsd_socket.h:416
void * msg_control
Definition: bsd_socket.h:415
uint16_t errorCode
Definition: tftp_common.h:138