socket_misc.c
Go to the documentation of this file.
1 /**
2  * @file socket_misc.c
3  * @brief Helper functions for sockets
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/socket.h"
37 #include "core/socket_misc.h"
38 #include "core/raw_socket.h"
39 #include "core/udp.h"
40 #include "core/tcp.h"
41 #include "core/tcp_misc.h"
42 #include "debug.h"
43 
44 
45 /**
46  * @brief Allocate a socket
47  * @param[in] type Type specification for the new socket
48  * @param[in] protocol Protocol to be used
49  * @return Handle referencing the new socket
50  **/
51 
53 {
54  error_t error;
55  uint_t i;
56  uint16_t port;
57  Socket *socket;
58 
59  //Initialize socket handle
60  socket = NULL;
61 
62 #if (TCP_SUPPORT == ENABLED)
63  //Connection-oriented socket?
65  {
66  //Always use TCP as underlying transport protocol
68  //Get an ephemeral port number
70  //Continue processing
71  error = NO_ERROR;
72  }
73  else
74 #endif
75 #if (UDP_SUPPORT == ENABLED)
76  //Connectionless socket?
77  if(type == SOCKET_TYPE_DGRAM)
78  {
79  //Always use UDP as underlying transport protocol
81  //Get an ephemeral port number
83  //Continue processing
84  error = NO_ERROR;
85  }
86  else
87 #endif
88 #if (RAW_SOCKET_SUPPORT == ENABLED)
89  //Raw socket?
91  {
92  //Port numbers are not relevant for raw sockets
93  port = 0;
94  //Continue processing
95  error = NO_ERROR;
96  }
97  else
98 #endif
99  {
100  //The socket type is not supported
101  error = ERROR_INVALID_PARAMETER;
102  }
103 
104  //Check status code
105  if(!error)
106  {
107  //Loop through socket descriptors
108  for(i = 0; i < SOCKET_MAX_COUNT; i++)
109  {
110  //Unused socket found?
112  {
113  //Save socket handle
114  socket = &socketTable[i];
115  //We are done
116  break;
117  }
118  }
119 
120 #if (TCP_SUPPORT == ENABLED)
121  //No more sockets available?
122  if(socket == NULL)
123  {
124  //Kill the oldest connection in the TIME-WAIT state whenever the
125  //socket table runs out of space
127  }
128 #endif
129 
130  //Check whether the current entry is free
131  if(socket != NULL)
132  {
133  //Save socket descriptor
134  i = socket->descriptor;
135 
136  //Clear the structure keeping the event field untouched
137  osMemset(socket, 0, offsetof(Socket, event));
138 
139  osMemset((uint8_t *) socket + offsetof(Socket, event) + sizeof(OsEvent),
140  0, sizeof(Socket) - offsetof(Socket, event) - sizeof(OsEvent));
141 
142  //Save socket characteristics
143  socket->descriptor = i;
144  socket->type = type;
145  socket->protocol = protocol;
146  socket->localPort = port;
147  socket->timeout = INFINITE_DELAY;
148 
149 #if (ETH_VLAN_SUPPORT == ENABLED)
150  //Default VLAN PCP and DEI fields
151  socket->vlanPcp = -1;
152  socket->vlanDei = -1;
153 #endif
154 
155 #if (ETH_VMAN_SUPPORT == ENABLED)
156  //Default VMAN PCP and DEI fields
157  socket->vmanPcp = -1;
158  socket->vmanDei = -1;
159 #endif
160 
161 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
162  //TCP keep-alive mechanism must be disabled by default (refer to
163  //RFC 1122, section 4.2.3.6)
164  socket->keepAliveEnabled = FALSE;
165 
166  //Default TCP keep-alive parameters
167  socket->keepAliveIdle = TCP_DEFAULT_KEEP_ALIVE_IDLE;
168  socket->keepAliveInterval = TCP_DEFAULT_KEEP_ALIVE_INTERVAL;
169  socket->keepAliveMaxProbes = TCP_DEFAULT_KEEP_ALIVE_PROBES;
170 #endif
171 
172 #if (TCP_SUPPORT == ENABLED)
173  //Default MSS value
174  socket->mss = TCP_MAX_MSS;
175 
176  //Default TX and RX buffer size
179 
180  //Compute the window scale factor to use for the receive window
182 #endif
183  }
184  }
185 
186  //Return a handle to the freshly created socket
187  return socket;
188 }
189 
190 
191 /**
192  * @brief Subscribe to the specified socket events
193  * @param[in] socket Handle that identifies a socket
194  * @param[in] event Event object used to receive notifications
195  * @param[in] eventMask Logic OR of the requested socket events
196  **/
197 
199 {
200  //Valid socket handle?
201  if(socket != NULL)
202  {
203  //Get exclusive access
205 
206  //An user event may have been previously registered...
207  if(socket->userEvent != NULL)
208  {
209  socket->eventMask |= eventMask;
210  }
211  else
212  {
213  socket->eventMask = eventMask;
214  }
215 
216  //Suscribe to get notified of events
217  socket->userEvent = event;
218 
219 #if (TCP_SUPPORT == ENABLED)
220  //Handle TCP specific events
221  if(socket->type == SOCKET_TYPE_STREAM)
222  {
224  }
225 #endif
226 #if (UDP_SUPPORT == ENABLED)
227  //Handle UDP specific events
228  if(socket->type == SOCKET_TYPE_DGRAM)
229  {
231  }
232 #endif
233 #if (RAW_SOCKET_SUPPORT == ENABLED)
234  //Handle events that are specific to raw sockets
235  if(socket->type == SOCKET_TYPE_RAW_IP ||
236  socket->type == SOCKET_TYPE_RAW_ETH)
237  {
239  }
240 #endif
241 
242  //Release exclusive access
244  }
245 }
246 
247 
248 /**
249  * @brief Unsubscribe previously registered events
250  * @param[in] socket Handle that identifies a socket
251  **/
252 
254 {
255  //Valid socket handle?
256  if(socket != NULL)
257  {
258  //Get exclusive access
260 
261  //Unsuscribe socket events
262  socket->userEvent = NULL;
263 
264  //Release exclusive access
266  }
267 }
268 
269 
270 /**
271  * @brief Retrieve event flags for a specified socket
272  * @param[in] socket Handle that identifies a socket
273  * @return Logic OR of events in the signaled state
274  **/
275 
277 {
278  uint_t eventFlags;
279 
280  //Valid socket handle?
281  if(socket != NULL)
282  {
283  //Get exclusive access
285 
286  //Read event flags for the specified socket
287  eventFlags = socket->eventFlags;
288 
289  //Release exclusive access
291  }
292  else
293  {
294  //The socket handle is not valid
295  eventFlags = 0;
296  }
297 
298  //Return the events in the signaled state
299  return eventFlags;
300 }
301 
302 
303 /**
304  * @brief Filter out incoming multicast traffic
305  * @param[in] socket Handle that identifies a socket
306  * @param[in] destAddr Destination IP address of the received packet
307  * @param[in] srcAddr Source IP address of the received packet
308  * @return Return TRUE if the multicast packet should be accepted, else FALSE
309  **/
310 
312  const IpAddr *srcAddr)
313 {
314 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
315  uint_t i;
316  bool_t acceptable;
317  SocketMulticastGroup *group;
318 
319  //Initialize flag
320  acceptable = FALSE;
321 
322  //Loop through multicast groups
323  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
324  {
325  //Point to the current multicast group
326  group = &socket->multicastGroups[i];
327 
328  //Matching multicast address?
329  if(ipCompAddr(&group->addr, destAddr))
330  {
331 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
332  uint_t j;
333 
334  //Check filter mode
335  if(group->filterMode == IP_FILTER_MODE_INCLUDE)
336  {
337  //In INCLUDE mode, reception of packets sent to the specified
338  //multicast address is requested only from those IP source
339  //addresses listed in the source list
340  for(j = 0; j < SOCKET_MAX_MULTICAST_SOURCES && !acceptable; j++)
341  {
342  //Compare source addresses
343  if(ipCompAddr(&group->sources[j], srcAddr))
344  {
345  acceptable = TRUE;
346  }
347  }
348  }
349  else
350  {
351  //In EXCLUDE mode, reception of packets sent to the given multicast
352  //address is requested from all IP source addresses except those
353  //listed in the source list
354  acceptable = TRUE;
355 
356  //Loop through the list of excluded source addresses
357  for(j = 0; j < group->numSources && acceptable; j++)
358  {
359  //Compare source addresses
360  if(ipCompAddr(&group->sources[j], srcAddr))
361  {
362  acceptable = FALSE;
363  }
364  }
365  }
366 #else
367  //The multicast address is acceptable
368  acceptable = TRUE;
369 #endif
370  }
371  }
372 
373  //Return TRUE if the multicast packet should be accepted
374  return acceptable;
375 #else
376  //Not implemented
377  return FALSE;
378 #endif
379 }
380 
381 
382 /**
383  * @brief Create a new multicast group
384  * @param[in] socket Handle to a socket
385  * @param[in] groupAddr IP address identifying a multicast group
386  * @return Pointer to the newly created multicast group
387  **/
388 
390  const IpAddr *groupAddr)
391 {
392 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
393  uint_t i;
394  SocketMulticastGroup *group;
395 
396  //Initialize pointer
397  group = NULL;
398 
399  //Loop through multicast groups
400  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
401  {
402  //Check whether the current entry is available for use
403  if(socket->multicastGroups[i].addr.length == 0)
404  {
405  //Point to the current group
406  group = &socket->multicastGroups[i];
407 
408  //Save multicast group address
409  group->addr = *groupAddr;
410 
411 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
412  //By default, all sources are accepted
413  group->filterMode = IP_FILTER_MODE_EXCLUDE;
414  group->numSources = 0;
415 #endif
416  //We are done
417  break;
418  }
419  }
420 
421  //Return a pointer to the newly created multicast group
422  return group;
423 #else
424  //Not implemented
425  return NULL;
426 #endif
427 }
428 
429 
430 /**
431  * @brief Search the list of multicast groups for a given group address
432  * @param[in] socket Handle to a socket
433  * @param[in] groupAddr IP address identifying a multicast group
434  * @return A pointer to the matching multicast group is returned. NULL is
435  * returned if the specified group address cannot be found
436  **/
437 
439  const IpAddr *groupAddr)
440 {
441 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
442  uint_t i;
443  SocketMulticastGroup *group;
444 
445  //Initialize pointer
446  group = NULL;
447 
448  //Loop through multicast groups
449  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
450  {
451  //Compare group addresses
452  if(ipCompAddr(&socket->multicastGroups[i].addr, groupAddr))
453  {
454  //Point to the current group
455  group = &socket->multicastGroups[i];
456  break;
457  }
458  }
459 
460  //Return a pointer to the matching multicast group
461  return group;
462 #else
463  //Not implemented
464  return NULL;
465 #endif
466 }
467 
468 
469 /**
470  * @brief Delete a multicast group
471  * @param[in] group Pointer to the multicast group
472  **/
473 
475 {
476  //Delete the specified entry
477  group->addr = IP_ADDR_UNSPECIFIED;
478 }
479 
480 
481 /**
482  * @brief Add an address to the multicast source filter
483  * @param[in] group Pointer to the multicast group
484  * @param[in] srcAddr IP address to be added to the list
485  * @return Error code
486  **/
487 
489  const IpAddr *srcAddr)
490 {
491 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
492  error_t error;
493 
494  //Initialize status code
495  error = NO_ERROR;
496 
497  //Make sure that the source address is not a duplicate
498  if(socketFindMulticastSrcAddr(group, srcAddr) < 0)
499  {
500  //Check the length of the list
501  if(group->numSources < SOCKET_MAX_MULTICAST_SOURCES)
502  {
503  //Append the source address to the list
504  group->sources[group->numSources] = *srcAddr;
505  group->numSources++;
506  }
507  else
508  {
509  //The implementation limits the number of source addresses
510  error = ERROR_OUT_OF_RESOURCES;
511  }
512  }
513 
514  //Return status code
515  return error;
516 #else
517  //Not implemented
518  return ERROR_NOT_IMPLEMENTED;
519 #endif
520 }
521 
522 
523 /**
524  * @brief Remove an address from the multicast source filter
525  * @param[in] group Pointer to the multicast group
526  * @param[in] srcAddr IP address to be removed from the list
527  **/
528 
530  const IpAddr *srcAddr)
531 {
532 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
533  uint_t i;
534  uint_t j;
535 
536  //Loop through the list of source addresses
537  for(i = 0; i < group->numSources; i++)
538  {
539  //Matching IP address?
540  if(ipCompAddr(&group->sources[i], srcAddr))
541  {
542  //Remove the source address from the list
543  for(j = i + 1; j < group->numSources; j++)
544  {
545  group->sources[j - 1] = group->sources[j];
546  }
547 
548  //Update the length of the list
549  group->numSources--;
550 
551  //We are done
552  break;
553  }
554  }
555 #endif
556 }
557 
558 
559 /**
560  * @brief Search the list of multicast sources for a given IP address
561  * @param[in] group Pointer to the multicast group
562  * @param[in] srcAddr Source IP address
563  * @return Index of the matching IP address is returned. -1 is
564  * returned if the specified IP address cannot be found
565  **/
566 
568  const IpAddr *srcAddr)
569 {
570 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
571  int_t i;
572  int_t index;
573 
574  //Initialize index
575  index = -1;
576 
577  //Loop through the list of source addresses
578  for(i = 0; i < group->numSources; i++)
579  {
580  //Matching IP address?
581  if(ipCompAddr(&group->sources[i], srcAddr))
582  {
583  index = i;
584  break;
585  }
586  }
587 
588  //Return the index of the matching IP address, if any
589  return index;
590 #else
591  //Not implemented
592  return -1;
593 #endif
594 }
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:108
Multicast group.
Definition: socket.h:273
void tcpComputeWindowScaleFactor(Socket *socket)
Compute the window scale factor to use for the receive window.
Definition: tcp_misc.c:1587
int bool_t
Definition: compiler_port.h:61
Ipv4Addr destAddr
Definition: ipv4.h:330
uint8_t protocol
Definition: ipv4.h:327
signed int int_t
Definition: compiler_port.h:56
#define netMutex
Definition: net_legacy.h:195
void udpUpdateEvents(Socket *socket)
Update UDP related events.
Definition: udp.c:971
IP network address.
Definition: ip.h:90
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:54
#define TRUE
Definition: os_port.h:50
#define SOCKET_MAX_MULTICAST_GROUPS
Definition: socket.h:53
Event object.
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
@ IP_FILTER_MODE_EXCLUDE
Definition: ip.h:68
uint8_t type
Definition: coap_common.h:176
SocketMulticastGroup * socketCreateMulticastGroupEntry(Socket *socket, const IpAddr *groupAddr)
Create a new multicast group.
Definition: socket_misc.c:389
#define TCP_MAX_MSS
Definition: tcp.h:54
@ SOCKET_TYPE_STREAM
Definition: socket.h:92
#define TCP_DEFAULT_KEEP_ALIVE_INTERVAL
Definition: tcp.h:222
#define TCP_DEFAULT_TX_BUFFER_SIZE
Definition: tcp.h:68
IpAddr addr
Multicast address.
Definition: socket.h:274
#define FALSE
Definition: os_port.h:46
void socketRemoveMulticastSrcAddr(SocketMulticastGroup *group, const IpAddr *srcAddr)
Remove an address from the multicast source filter.
Definition: socket_misc.c:529
Helper functions for TCP.
void socketDeleteMulticastGroupEntry(SocketMulticastGroup *group)
Delete a multicast group.
Definition: socket_misc.c:474
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
Socket * tcpKillOldestConnection(void)
Kill the oldest socket in the TIME-WAIT state.
Definition: tcp.c:1061
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:317
#define TCP_MAX_RX_BUFFER_SIZE
Definition: tcp.h:89
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
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:94
void tcpUpdateEvents(Socket *socket)
Update TCP related events.
Definition: tcp_misc.c:2175
#define MIN(a, b)
Definition: os_port.h:63
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
void rawSocketUpdateEvents(Socket *socket)
Update event state for raw sockets.
Definition: raw_socket.c:1025
#define TCP_MAX_TX_BUFFER_SIZE
Definition: tcp.h:75
uint16_t udpGetDynamicPort(void)
Get an ephemeral port number.
Definition: udp.c:81
TCP/IP raw sockets.
uint16_t port
Definition: dns_common.h:267
#define TCP_DEFAULT_KEEP_ALIVE_PROBES
Definition: tcp.h:229
error_t socketAddMulticastSrcAddr(SocketMulticastGroup *group, const IpAddr *srcAddr)
Add an address to the multicast source filter.
Definition: socket_misc.c:488
Socket * socketAllocate(uint_t type, uint_t protocol)
Allocate a socket.
Definition: socket_misc.c:52
void socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
Subscribe to the specified socket events.
Definition: socket_misc.c:198
uint16_t tcpGetDynamicPort(void)
Get an ephemeral port number.
Definition: tcp.c:106
Helper functions for sockets.
TCP (Transmission Control Protocol)
@ SOCKET_TYPE_UNUSED
Definition: socket.h:91
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
Ipv4Addr groupAddr
Definition: igmp_common.h:214
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
UDP (User Datagram Protocol)
#define Socket
Definition: socket.h:36
@ IP_FILTER_MODE_INCLUDE
Definition: ip.h:69
#define SOCKET_MAX_MULTICAST_SOURCES
Definition: socket.h:60
MacAddr srcAddr
Definition: ethernet.h:220
Socket API.
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
#define TCP_DEFAULT_KEEP_ALIVE_IDLE
Definition: tcp.h:215
bool_t socketMulticastFilter(Socket *socket, const IpAddr *destAddr, const IpAddr *srcAddr)
Filter out incoming multicast traffic.
Definition: socket_misc.c:311
#define TCP_DEFAULT_RX_BUFFER_SIZE
Definition: tcp.h:82
unsigned int uint_t
Definition: compiler_port.h:57
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:253
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
#define SOCKET_MAX_COUNT
Definition: socket.h:46
SocketMulticastGroup * socketFindMulticastGroupEntry(Socket *socket, const IpAddr *groupAddr)
Search the list of multicast groups for a given group address.
Definition: socket_misc.c:438
@ SOCKET_IP_PROTO_TCP
Definition: socket.h:107
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:276
int_t socketFindMulticastSrcAddr(SocketMulticastGroup *group, const IpAddr *srcAddr)
Search the list of multicast sources for a given IP address.
Definition: socket_misc.c:567
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:75