socket.c
Go to the documentation of this file.
1 /**
2  * @file socket.c
3  * @brief Socket API
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.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 "dns/dns_client.h"
43 #include "mdns/mdns_client.h"
44 #include "netbios/nbns_client.h"
45 #include "llmnr/llmnr_client.h"
46 #include "debug.h"
47 
48 //Socket table
50 
51 //Default socket message
53 {
54  NULL, //Pointer to the payload
55  0, //Size of the payload, in bytes
56  0, //Actual length of the payload, in bytes
57  0, //Time-to-live value
58  0, //Type-of-service value
59  IP_DEFAULT_DF, //Do not fragment the IP packet
60  NULL, //Underlying network interface
61  {0}, //Source IP address
62  0, //Source port
63  {0}, //Destination IP address
64  0, //Destination port
65 #if (ETH_SUPPORT == ENABLED)
66  {{{0}}}, //Source MAC address
67  {{{0}}}, //Destination MAC address
68  0, //Ethernet type field
69 #endif
70 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
71  0, //Switch port identifier
72 #endif
73 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
74  -1, //Unique identifier for hardware time stamping
75  {0}, //Captured time stamp
76 #endif
77 };
78 
79 
80 /**
81  * @brief Socket related initialization
82  * @param[in] context Pointer to the TCP/IP stack context
83  * @return Error code
84  **/
85 
87 {
88  uint_t i;
89  uint_t j;
90 
91  //Initialize socket descriptors
92  osMemset(socketTable, 0, sizeof(socketTable));
93 
94  //Loop through socket descriptors
95  for(i = 0; i < SOCKET_MAX_COUNT; i++)
96  {
97  //Set socket identifier
98  socketTable[i].descriptor = i;
99 
100  //Create an event object to track socket events
101  if(!osCreateEvent(&socketTable[i].event))
102  {
103  //Clean up side effects
104  for(j = 0; j < i; j++)
105  {
106  osDeleteEvent(&socketTable[j].event);
107  }
108 
109  //Report an error
110  return ERROR_OUT_OF_RESOURCES;
111  }
112  }
113 
114  //Successful initialization
115  return NO_ERROR;
116 }
117 
118 
119 /**
120  * @brief Create a socket
121  * @param[in] type Type specification for the new socket (stream, datagram or raw)
122  * @param[in] protocol Protocol to be used
123  * @return Handle referencing the new socket
124  **/
125 
127 {
128  NetContext *context;
129 
130  //Point to the TCP/IP stack context
131  context = netGetDefaultContext();
132 
133  //Allocate a new socket
134  return socketOpenEx(context, type, protocol);
135 }
136 
137 
138 /**
139  * @brief Create a socket
140  * @param[in] context Pointer to the TCP/IP stack context
141  * @param[in] type Type specification for the new socket (stream, datagram or raw)
142  * @param[in] protocol Protocol to be used
143  * @return Handle referencing the new socket
144  **/
145 
147 {
148  Socket *socket;
149 
150  //Get exclusive access
151  netLock(context);
152  //Allocate a new socket
153  socket = socketAllocate(context, type, protocol);
154  //Release exclusive access
155  netUnlock(context);
156 
157  //Return a handle to the freshly created socket
158  return socket;
159 }
160 
161 
162 /**
163  * @brief Set timeout value for blocking operations
164  * @param[in] socket Handle to a socket
165  * @param[in] timeout Maximum time to wait
166  * @return Error code
167  **/
168 
170 {
171  //Make sure the socket handle is valid
172  if(socket == NULL)
174 
175  //Get exclusive access
176  netLock(socket->netContext);
177  //Record timeout value
178  socket->timeout = timeout;
179  //Release exclusive access
180  netUnlock(socket->netContext);
181 
182  //No error to report
183  return NO_ERROR;
184 }
185 
186 
187 /**
188  * @brief Set TTL value for unicast datagrams
189  * @param[in] socket Handle to a socket
190  * @param[in] ttl Time-to-live value
191  * @return Error code
192  **/
193 
195 {
196  //Make sure the socket handle is valid
197  if(socket == NULL)
199 
200  //Get exclusive access
201  netLock(socket->netContext);
202  //Set TTL value
203  socket->ttl = ttl;
204  //Release exclusive access
205  netUnlock(socket->netContext);
206 
207  //No error to report
208  return NO_ERROR;
209 }
210 
211 
212 /**
213  * @brief Set TTL value for multicast datagrams
214  * @param[in] socket Handle to a socket
215  * @param[in] ttl Time-to-live value
216  * @return Error code
217  **/
218 
220 {
221  //Make sure the socket handle is valid
222  if(socket == NULL)
224 
225  //Get exclusive access
226  netLock(socket->netContext);
227  //Set TTL value
228  socket->multicastTtl = ttl;
229  //Release exclusive access
230  netUnlock(socket->netContext);
231 
232  //No error to report
233  return NO_ERROR;
234 }
235 
236 
237 /**
238  * @brief Set DSCP field
239  * @param[in] socket Handle to a socket
240  * @param[in] dscp Differentiated services codepoint
241  * @return Error code
242  **/
243 
245 {
246  //Make sure the socket handle is valid
247  if(socket == NULL)
249 
250  //The DSCP field is 6 bits wide
251  if(dscp >= 64)
253 
254  //Get exclusive access
255  netLock(socket->netContext);
256  //Set differentiated services codepoint
257  socket->tos = (dscp << 2) & 0xFF;
258  //Release exclusive access
259  netUnlock(socket->netContext);
260 
261  //No error to report
262  return NO_ERROR;
263 }
264 
265 
266 /**
267  * @brief Set VLAN priority
268  * @param[in] socket Handle to a socket
269  * @param[in] pcp VLAN priority value
270  * @return Error code
271  **/
272 
274 {
275 #if (ETH_VLAN_SUPPORT == ENABLED)
276  //Make sure the socket handle is valid
277  if(socket == NULL)
279 
280  //The PCP field is 3 bits wide
281  if(pcp >= 8)
283 
284  //Get exclusive access
285  netLock(socket->netContext);
286 
287  //The PCP field specifies the frame priority level. Different PCP values
288  //can be used to prioritize different classes of traffic
289  socket->vlanPcp = pcp;
290 
291  //Release exclusive access
292  netUnlock(socket->netContext);
293 
294  //No error to report
295  return NO_ERROR;
296 #else
297  //Not implemented
298  return ERROR_NOT_IMPLEMENTED;
299 #endif
300 }
301 
302 
303 /**
304  * @brief Set VLAN DEI flag
305  * @param[in] socket Handle to a socket
306  * @param[in] dei Drop eligible indicator
307  * @return Error code
308  **/
309 
311 {
312 #if (ETH_VLAN_SUPPORT == ENABLED)
313  //Make sure the socket handle is valid
314  if(socket == NULL)
316 
317  //Get exclusive access
318  netLock(socket->netContext);
319 
320  //The DEI flag may be used to indicate frames eligible to be dropped in
321  //the presence of congestion
322  socket->vlanDei = dei;
323 
324  //Release exclusive access
325  netUnlock(socket->netContext);
326 
327  //No error to report
328  return NO_ERROR;
329 #else
330  //Not implemented
331  return ERROR_NOT_IMPLEMENTED;
332 #endif
333 }
334 
335 
336 /**
337  * @brief Set VMAN priority
338  * @param[in] socket Handle to a socket
339  * @param[in] pcp VLAN priority value
340  * @return Error code
341  **/
342 
344 {
345 #if (ETH_VMAN_SUPPORT == ENABLED)
346  //Make sure the socket handle is valid
347  if(socket == NULL)
349 
350  //The PCP field is 3 bits wide
351  if(pcp >= 8)
353 
354  //Get exclusive access
355  netLock(socket->netContext);
356 
357  //The PCP field specifies the frame priority level. Different PCP values
358  //can be used to prioritize different classes of traffic
359  socket->vmanPcp = pcp;
360 
361  //Release exclusive access
362  netUnlock(socket->netContext);
363 
364  //No error to report
365  return NO_ERROR;
366 #else
367  //Not implemented
368  return ERROR_NOT_IMPLEMENTED;
369 #endif
370 }
371 
372 
373 /**
374  * @brief Set VMAN DEI flag
375  * @param[in] socket Handle to a socket
376  * @param[in] dei Drop eligible indicator
377  * @return Error code
378  **/
379 
381 {
382 #if (ETH_VMAN_SUPPORT == ENABLED)
383  //Make sure the socket handle is valid
384  if(socket == NULL)
386 
387  //Get exclusive access
388  netLock(socket->netContext);
389 
390  //The DEI flag may be used to indicate frames eligible to be dropped in
391  //the presence of congestion
392  socket->vmanDei = dei;
393 
394  //Release exclusive access
395  netUnlock(socket->netContext);
396 
397  //No error to report
398  return NO_ERROR;
399 #else
400  //Not implemented
401  return ERROR_NOT_IMPLEMENTED;
402 #endif
403 }
404 
405 
406 /**
407  * @brief Enable reception of broadcast messages
408  * @param[in] socket Handle to a socket
409  * @param[in] enabled Specifies whether broadcast messages should be accepted
410  * @return Error code
411  **/
412 
414 {
415  //Make sure the socket handle is valid
416  if(socket == NULL)
418 
419  //Get exclusive access
420  netLock(socket->netContext);
421 
422  //Check whether broadcast messages should be accepted
423  if(enabled)
424  {
425  socket->options |= SOCKET_OPTION_BROADCAST;
426  }
427  else
428  {
429  socket->options &= ~SOCKET_OPTION_BROADCAST;
430  }
431 
432  //Release exclusive access
433  netUnlock(socket->netContext);
434 
435  //Successful processing
436  return NO_ERROR;
437 }
438 
439 
440 /**
441  * @brief Join the specified host group
442  * @param[in] socket Handle to a socket
443  * @param[in] groupAddr IP address identifying the host group to join
444  * @return Error code
445  **/
446 
448 {
449 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
450  error_t error;
451  SocketMulticastGroup *group;
452 
453  //Check parameters
454  if(socket == NULL || groupAddr == NULL)
456 
457  //This function shall be used with connectionless or raw sockets
458  if(socket->type != SOCKET_TYPE_DGRAM &&
459  socket->type != SOCKET_TYPE_RAW_IP)
460  {
461  return ERROR_INVALID_SOCKET;
462  }
463 
464  //The group address must be a valid multicast address
466  return ERROR_INVALID_ADDRESS;
467 
468  //Initialize status code
469  error = NO_ERROR;
470 
471  //Get exclusive access
472  netLock(socket->netContext);
473 
474  //Search the list of multicast groups for en existing entry
476 
477  //No matching entry found?
478  if(group == NULL)
479  {
480  //Create a new entry
482  }
483 
484  //Entry successfully created?
485  if(group != NULL)
486  {
487  //Update the multicast reception state of the interface
488  ipUpdateMulticastFilter(socket->netContext, socket->interface, groupAddr);
489  }
490  else
491  {
492  //Report an error
493  error = ERROR_OUT_OF_RESOURCES;
494  }
495 
496  //Release exclusive access
497  netUnlock(socket->netContext);
498 
499  //Return status code
500  return error;
501 #else
502  //Not implemented
503  return ERROR_NOT_IMPLEMENTED;
504 #endif
505 }
506 
507 
508 /**
509  * @brief Leave the specified host group
510  * @param[in] socket Handle to a socket
511  * @param[in] groupAddr IP address identifying the host group to leave
512  * @return Error code
513  **/
514 
516 {
517 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
518  error_t error;
519  SocketMulticastGroup *group;
520 
521  //Check parameters
522  if(socket == NULL || groupAddr == NULL)
524 
525  //This function shall be used with connectionless or raw sockets
526  if(socket->type != SOCKET_TYPE_DGRAM &&
527  socket->type != SOCKET_TYPE_RAW_IP)
528  {
529  return ERROR_INVALID_SOCKET;
530  }
531 
532  //The group address must be a valid multicast address
534  return ERROR_INVALID_ADDRESS;
535 
536  //Initialize status code
537  error = NO_ERROR;
538 
539  //Get exclusive access
540  netLock(socket->netContext);
541 
542  //Search the list of multicast groups for the specified address
544 
545  //Any matching entry found?
546  if(group != NULL)
547  {
548  //Delete entry
550 
551  //Update the multicast reception state of the interface
552  ipUpdateMulticastFilter(socket->netContext, socket->interface, groupAddr);
553  }
554  else
555  {
556  //Report an error
557  error = ERROR_ADDRESS_NOT_FOUND;
558  }
559 
560  //Release exclusive access
561  netUnlock(socket->netContext);
562 
563  //Return status code
564  return error;
565 #else
566  //Not implemented
567  return ERROR_NOT_IMPLEMENTED;
568 #endif
569 }
570 
571 
572 /**
573  * @brief Set multicast source filter (full-state API)
574  * @param[in] socket Handle to a socket
575  * @param[in] groupAddr IP address identifying a multicast group
576  * @param[in] filterMode Multicast filter mode (include or exclude)
577  * @param[in] sources IP addresses of sources to include or exclude depending
578  * on the filter mode
579  * @param[in] numSources Number of source addresses in the list
580  * @return Error code
581  **/
582 
584  IpFilterMode filterMode, const IpAddr *sources, uint_t numSources)
585 {
586 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
587  error_t error;
588  uint_t i;
589  SocketMulticastGroup *group;
590 
591  //Check parameters
592  if(socket == NULL || groupAddr == NULL)
594 
595  //This function shall be used with connectionless or raw sockets
596  if(socket->type != SOCKET_TYPE_DGRAM &&
597  socket->type != SOCKET_TYPE_RAW_IP)
598  {
599  return ERROR_INVALID_SOCKET;
600  }
601 
602  //The group address must be a valid multicast address
604  return ERROR_INVALID_ADDRESS;
605 
606  //Invalid filter mode?
607  if(filterMode != IP_FILTER_MODE_INCLUDE &&
608  filterMode != IP_FILTER_MODE_EXCLUDE)
609  {
611  }
612 
613  //Invalid set of source addresses?
614  if(numSources != 0 && sources == NULL)
616 
617  //The implementation limits the number of source addresses
618  if(numSources > SOCKET_MAX_MULTICAST_SOURCES)
620 
621  //Initialize status code
622  error = NO_ERROR;
623 
624  //Get exclusive access
625  netLock(socket->netContext);
626 
627  //Search the list of multicast groups for the specified address
629 
630  //The "non-existent" state is considered to have a filter mode of INCLUDE
631  //and an empty source list
632  if(filterMode == IP_FILTER_MODE_INCLUDE && numSources == 0)
633  {
634  //Any matching entry found?
635  if(group != NULL)
636  {
637  //Delete entry
639  }
640  }
641  else
642  {
643  //No matching entry found?
644  if(group == NULL)
645  {
646  //Create a new entry
648  }
649 
650  //Entry successfully created?
651  if(group != NULL)
652  {
653  //Replace the previous filter with a new one
654  group->filterMode = filterMode;
655  group->numSources = numSources;
656 
657  //Save the list of sources to include or exclude
658  for(i = 0; i < numSources; i++)
659  {
660  group->sources[i] = sources[i];
661  }
662  }
663  else
664  {
665  //Report an error
666  error = ERROR_OUT_OF_RESOURCES;
667  }
668  }
669 
670  //Check status code
671  if(!error)
672  {
673  //Update the multicast reception state of the interface
674  ipUpdateMulticastFilter(socket->netContext, socket->interface, groupAddr);
675  }
676 
677  //Release exclusive access
678  netUnlock(socket->netContext);
679 
680  //Return status code
681  return error;
682 #else
683  //Not implemented
684  return ERROR_NOT_IMPLEMENTED;
685 #endif
686 }
687 
688 
689 /**
690  * @brief Get multicast source filter
691  * @param[in] socket Handle to a socket
692  * @param[in] groupAddr IP address identifying a multicast group
693  * @param[out] filterMode Multicast filter mode (include or exclude)
694  * @param[out] sources IP addresses of sources to include or exclude depending
695  * on the filter mode
696  * @param[out] numSources Number of source addresses in the list
697  * @return Error code
698  **/
699 
701  IpFilterMode *filterMode, IpAddr *sources, uint_t *numSources)
702 {
703 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
704  uint_t i;
705  SocketMulticastGroup *group;
706 
707  //Check parameters
708  if(socket == NULL || groupAddr == NULL || numSources == NULL)
710 
711  //This function shall be used with connectionless or raw sockets
712  if(socket->type != SOCKET_TYPE_DGRAM &&
713  socket->type != SOCKET_TYPE_RAW_IP)
714  {
715  return ERROR_INVALID_SOCKET;
716  }
717 
718  //The group address must be a valid multicast address
720  return ERROR_INVALID_ADDRESS;
721 
722  //Get exclusive access
723  netLock(socket->netContext);
724 
725  //Search the list of multicast groups for the specified address
727 
728  //Any matching entry found?
729  if(group != NULL)
730  {
731  //Filter mode
732  *filterMode = group->filterMode;
733  //Number of source addresses in the list
734  *numSources = group->numSources;
735 
736  //This parameter is optional
737  if(sources != NULL)
738  {
739  //Copy the list of source addresses
740  for(i = 0; i < group->numSources; i++)
741  {
742  sources[i] = group->sources[i];
743  }
744  }
745  }
746  else
747  {
748  //The "non-existent" state is considered to have a filter mode of INCLUDE
749  //and an empty source list
750  *filterMode = IP_FILTER_MODE_EXCLUDE;
751  *numSources = 0;
752  }
753 
754  //Release exclusive access
755  netUnlock(socket->netContext);
756 
757  //Successful processing
758  return NO_ERROR;
759 #else
760  //Not implemented
761  return ERROR_NOT_IMPLEMENTED;
762 #endif
763 }
764 
765 
766 /**
767  * @brief Accept specific source for specific group (delta-based API)
768  * @param[in] socket Handle to a socket
769  * @param[in] groupAddr IP address identifying a multicast group
770  * @param[in] srcAddr Source IP address to accept
771  * @return Error code
772  **/
773 
775  const IpAddr *srcAddr)
776 {
777 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
778  error_t error;
779  SocketMulticastGroup *group;
780 
781  //Check parameters
782  if(socket == NULL || groupAddr == NULL || srcAddr == NULL)
784 
785  //This function shall be used with connectionless or raw sockets
786  if(socket->type != SOCKET_TYPE_DGRAM &&
787  socket->type != SOCKET_TYPE_RAW_IP)
788  {
789  return ERROR_INVALID_SOCKET;
790  }
791 
792  //The group address must be a valid multicast address
794  return ERROR_INVALID_ADDRESS;
795 
796  //Initialize status code
797  error = NO_ERROR;
798 
799  //Get exclusive access
800  netLock(socket->netContext);
801 
802  //Search the list of multicast groups for en existing entry
804 
805  //No matching entry found?
806  if(group == NULL)
807  {
808  //Create a new entry
810 
811  //Failed to create entry?
812  if(group == NULL)
813  {
814  //Report an error
815  error = ERROR_OUT_OF_RESOURCES;
816  }
817  }
818 
819  //Check status code
820  if(!error)
821  {
822  //Check multicast filter mode
823  if(group->filterMode == IP_FILTER_MODE_EXCLUDE)
824  {
825  //Switch to source-specific multicast mode
826  group->filterMode = IP_FILTER_MODE_INCLUDE;
827  group->numSources = 0;
828  }
829 
830  //Add the address to the list of allowed sources
831  error = socketAddMulticastSrcAddr(group, srcAddr);
832  }
833 
834  //Check status code
835  if(!error)
836  {
837  //Update the multicast reception state of the interface
838  ipUpdateMulticastFilter(socket->netContext, socket->interface, groupAddr);
839  }
840 
841  //Release exclusive access
842  netUnlock(socket->netContext);
843 
844  //Return status code
845  return error;
846 #else
847  //Not implemented
848  return ERROR_NOT_IMPLEMENTED;
849 #endif
850 }
851 
852 
853 /**
854  * @brief Drop specific source for specific group (delta-based API)
855  * @param[in] socket Handle to a socket
856  * @param[in] groupAddr IP address identifying a multicast group
857  * @param[in] srcAddr Source IP address to drop
858  * @return Error code
859  **/
860 
862  const IpAddr *srcAddr)
863 {
864 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
865  error_t error;
866  SocketMulticastGroup *group;
867 
868  //Check parameters
869  if(socket == NULL || groupAddr == NULL || srcAddr == NULL)
871 
872  //This function shall be used with connectionless or raw sockets
873  if(socket->type != SOCKET_TYPE_DGRAM &&
874  socket->type != SOCKET_TYPE_RAW_IP)
875  {
876  return ERROR_INVALID_SOCKET;
877  }
878 
879  //The group address must be a valid multicast address
881  return ERROR_INVALID_ADDRESS;
882 
883  //Initialize status code
884  error = NO_ERROR;
885 
886  //Get exclusive access
887  netLock(socket->netContext);
888 
889  //Search the list of multicast groups for en existing entry
891 
892  //Any matching entry found?
893  if(group != NULL)
894  {
895  //Check multicast filter mode
896  if(group->filterMode == IP_FILTER_MODE_INCLUDE)
897  {
898  //Remove the address to the list of allowed sources
900 
901  //Empty set of source addresses?
902  if(group->numSources == 0)
903  {
904  //Delete entry
906  }
907 
908  //Update the multicast reception state of the interface
909  ipUpdateMulticastFilter(socket->netContext, socket->interface,
910  groupAddr);
911  }
912  }
913  else
914  {
915  //Report an error
916  error = ERROR_ADDRESS_NOT_FOUND;
917  }
918 
919  //Release exclusive access
920  netUnlock(socket->netContext);
921 
922  //Return status code
923  return error;
924 #else
925  //Not implemented
926  return ERROR_NOT_IMPLEMENTED;
927 #endif
928 }
929 
930 
931 /**
932  * @brief Block specific source for specific group (delta-based API)
933  * @param[in] socket Handle to a socket
934  * @param[in] groupAddr IP address identifying a multicast group
935  * @param[in] srcAddr Source IP address to block
936  * @return Error code
937  **/
938 
940  const IpAddr *srcAddr)
941 {
942 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
943  error_t error;
944  SocketMulticastGroup *group;
945 
946  //Check parameters
947  if(socket == NULL || groupAddr == NULL || srcAddr == NULL)
949 
950  //This function shall be used with connectionless or raw sockets
951  if(socket->type != SOCKET_TYPE_DGRAM &&
952  socket->type != SOCKET_TYPE_RAW_IP)
953  {
954  return ERROR_INVALID_SOCKET;
955  }
956 
957  //The group address must be a valid multicast address
959  return ERROR_INVALID_ADDRESS;
960 
961  //Initialize status code
962  error = NO_ERROR;
963 
964  //Get exclusive access
965  netLock(socket->netContext);
966 
967  //Search the list of multicast groups for en existing entry
969 
970  //No matching entry found?
971  if(group == NULL)
972  {
973  //Create a new entry
975 
976  //Failed to create entry?
977  if(group == NULL)
978  {
979  //Report an error
980  error = ERROR_OUT_OF_RESOURCES;
981  }
982  }
983 
984  //Check status code
985  if(!error)
986  {
987  //Check multicast filter mode
988  if(group->filterMode == IP_FILTER_MODE_INCLUDE)
989  {
990  //Switch to any-source multicast mode
991  group->filterMode = IP_FILTER_MODE_EXCLUDE;
992  group->numSources = 0;
993  }
994 
995  //Add the address to the list of blocked sources
996  error = socketAddMulticastSrcAddr(group, srcAddr);
997  }
998 
999  //Check status code
1000  if(!error)
1001  {
1002  //Update the multicast reception state of the interface
1003  ipUpdateMulticastFilter(socket->netContext, socket->interface, groupAddr);
1004  }
1005 
1006  //Release exclusive access
1007  netUnlock(socket->netContext);
1008 
1009  //Return status code
1010  return error;
1011 #else
1012  //Not implemented
1013  return ERROR_NOT_IMPLEMENTED;
1014 #endif
1015 }
1016 
1017 
1018 /**
1019  * @brief Unblock specific source for specific group (delta-based API)
1020  * @param[in] socket Handle to a socket
1021  * @param[in] groupAddr IP address identifying a multicast group
1022  * @param[in] srcAddr Source IP address to unblock
1023  * @return Error code
1024  **/
1025 
1027  const IpAddr *srcAddr)
1028 {
1029 #if (SOCKET_MAX_MULTICAST_GROUPS > 0 && SOCKET_MAX_MULTICAST_SOURCES > 0)
1030  error_t error;
1031  SocketMulticastGroup *group;
1032 
1033  //Check parameters
1034  if(socket == NULL || groupAddr == NULL || srcAddr == NULL)
1035  return ERROR_INVALID_PARAMETER;
1036 
1037  //This function shall be used with connectionless or raw sockets
1038  if(socket->type != SOCKET_TYPE_DGRAM &&
1039  socket->type != SOCKET_TYPE_RAW_IP)
1040  {
1041  return ERROR_INVALID_SOCKET;
1042  }
1043 
1044  //The group address must be a valid multicast address
1046  return ERROR_INVALID_ADDRESS;
1047 
1048  //Initialize status code
1049  error = NO_ERROR;
1050 
1051  //Get exclusive access
1052  netLock(socket->netContext);
1053 
1054  //Search the list of multicast groups for en existing entry
1056 
1057  //Any matching entry found?
1058  if(group != NULL)
1059  {
1060  //Check multicast filter mode
1061  if(group->filterMode == IP_FILTER_MODE_EXCLUDE)
1062  {
1063  //Remove the address from the list of blocked sources
1065 
1066  //Update the multicast reception state of the interface
1067  ipUpdateMulticastFilter(socket->netContext, socket->interface,
1068  groupAddr);
1069  }
1070  }
1071  else
1072  {
1073  //Report an error
1074  error = ERROR_ADDRESS_NOT_FOUND;
1075  }
1076 
1077  //Release exclusive access
1078  netUnlock(socket->netContext);
1079 
1080  //Return status code
1081  return error;
1082 #else
1083  //Not implemented
1084  return ERROR_NOT_IMPLEMENTED;
1085 #endif
1086 }
1087 
1088 
1089 /**
1090  * @brief Enable TCP keep-alive
1091  * @param[in] socket Handle to a socket
1092  * @param[in] enabled Specifies whether TCP keep-alive is enabled
1093  * @return Error code
1094  **/
1095 
1097 {
1098 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1099  //Make sure the socket handle is valid
1100  if(socket == NULL)
1101  return ERROR_INVALID_PARAMETER;
1102 
1103  //Get exclusive access
1104  netLock(socket->netContext);
1105 
1106  //Check whether TCP keep-alive mechanism should be enabled
1107  if(enabled)
1108  {
1109  //Enable TCP keep-alive mechanism
1110  socket->keepAliveEnabled = TRUE;
1111  //Reset keep-alive probe counter
1112  socket->keepAliveProbeCount = 0;
1113  //Start keep-alive timer
1114  socket->keepAliveTimestamp = osGetSystemTime();
1115  }
1116  else
1117  {
1118  //Disable TCP keep-alive mechanism
1119  socket->keepAliveEnabled = FALSE;
1120  }
1121 
1122  //Release exclusive access
1123  netUnlock(socket->netContext);
1124 
1125  //Successful processing
1126  return NO_ERROR;
1127 #else
1128  //Not implemented
1129  return ERROR_NOT_IMPLEMENTED;
1130 #endif
1131 }
1132 
1133 
1134 /**
1135  * @brief Set TCP keep-alive parameters
1136  * @param[in] socket Handle to a socket
1137  * @param[in] idle Time interval between last data packet sent and first
1138  * keep-alive probe
1139  * @param[in] interval Time interval between subsequent keep-alive probes
1140  * @param[in] maxProbes Number of unacknowledged keep-alive probes to send before
1141  * considering the connection is dead
1142  * @return Error code
1143  **/
1144 
1146  systime_t interval, uint_t maxProbes)
1147 {
1148 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1149  //Check parameters
1150  if(socket == NULL || idle == 0 || interval == 0 || maxProbes == 0)
1151  {
1152  return ERROR_INVALID_PARAMETER;
1153  }
1154 
1155  //Get exclusive access
1156  netLock(socket->netContext);
1157 
1158  //Time interval between last data packet sent and first keep-alive probe
1159  socket->keepAliveIdle = idle;
1160 
1161  //Time interval between subsequent keep-alive probes
1162  socket->keepAliveInterval = interval;
1163 
1164  //Number of unacknowledged keep-alive probes to send before considering
1165  //the connection is dead
1166  socket->keepAliveMaxProbes = maxProbes;
1167 
1168  //Release exclusive access
1169  netUnlock(socket->netContext);
1170 
1171  //Successful processing
1172  return NO_ERROR;
1173 #else
1174  //Not implemented
1175  return ERROR_NOT_IMPLEMENTED;
1176 #endif
1177 }
1178 
1179 
1180 /**
1181  * @brief Specify the maximum segment size for outgoing TCP packets
1182  * @param[in] socket Handle to a socket
1183  * @param[in] mss Maximum segment size, in bytes
1184  * @return Error code
1185  **/
1186 
1188 {
1189 #if (TCP_SUPPORT == ENABLED)
1190  //Make sure the socket handle is valid
1191  if(socket == NULL)
1192  return ERROR_INVALID_PARAMETER;
1193 
1194  //Get exclusive access
1195  netLock(socket->netContext);
1196 
1197  //TCP imposes its minimum and maximum bounds over the value provided
1198  mss = MIN(mss, TCP_MAX_MSS);
1199  mss = MAX(mss, TCP_MIN_MSS);
1200 
1201  //Set the maximum segment size for outgoing TCP packets. If this option
1202  //is set before connection establishment, it also change the MSS value
1203  //announced to the other end in the initial SYN packet
1204  socket->mss = mss;
1205 
1206  //Release exclusive access
1207  netUnlock(socket->netContext);
1208 
1209  //No error to report
1210  return NO_ERROR;
1211 #else
1212  return ERROR_NOT_IMPLEMENTED;
1213 #endif
1214 }
1215 
1216 
1217 /**
1218  * @brief Specify the size of the TCP send buffer
1219  * @param[in] socket Handle to a socket
1220  * @param[in] size Desired buffer size, in bytes
1221  * @return Error code
1222  **/
1223 
1225 {
1226 #if (TCP_SUPPORT == ENABLED)
1227  //Make sure the socket handle is valid
1228  if(socket == NULL)
1229  return ERROR_INVALID_PARAMETER;
1230 
1231  //This function shall be used with connection-oriented sockets
1232  if(socket->type != SOCKET_TYPE_STREAM)
1233  return ERROR_INVALID_SOCKET;
1234 
1235  //The buffer size cannot be changed when the connection is established
1237  return ERROR_INVALID_SOCKET;
1238 
1239  //Check parameter value
1240  if(size < 1 || size > TCP_MAX_TX_BUFFER_SIZE)
1241  return ERROR_INVALID_PARAMETER;
1242 
1243  //Use the specified buffer size
1244  socket->txBufferSize = size;
1245 
1246  //No error to report
1247  return NO_ERROR;
1248 #else
1249  return ERROR_NOT_IMPLEMENTED;
1250 #endif
1251 }
1252 
1253 
1254 /**
1255  * @brief Specify the size of the TCP receive buffer
1256  * @param[in] socket Handle to a socket
1257  * @param[in] size Desired buffer size, in bytes
1258  * @return Error code
1259  **/
1260 
1262 {
1263 #if (TCP_SUPPORT == ENABLED)
1264  //Make sure the socket handle is valid
1265  if(socket == NULL)
1266  return ERROR_INVALID_PARAMETER;
1267 
1268  //This function shall be used with connection-oriented sockets
1269  if(socket->type != SOCKET_TYPE_STREAM)
1270  return ERROR_INVALID_SOCKET;
1271 
1272  //The buffer size cannot be changed when the connection is established
1274  return ERROR_INVALID_SOCKET;
1275 
1276  //Check parameter value
1277  if(size < 1 || size > TCP_MAX_RX_BUFFER_SIZE)
1278  return ERROR_INVALID_PARAMETER;
1279 
1280  //Use the specified buffer size
1281  socket->rxBufferSize = size;
1282 
1283  //Compute the window scale factor to use for the receive window
1285 
1286  //No error to report
1287  return NO_ERROR;
1288 #else
1289  return ERROR_NOT_IMPLEMENTED;
1290 #endif
1291 }
1292 
1293 
1294 /**
1295  * @brief Bind a socket to a particular network interface
1296  * @param[in] socket Handle to a socket
1297  * @param[in] interface Network interface to be used
1298  * @return Error code
1299  **/
1300 
1302 {
1303  //Make sure the socket handle is valid
1304  if(socket == NULL)
1305  return ERROR_INVALID_PARAMETER;
1306 
1307  //Explicitly associate the socket with the specified interface
1308  socket->interface = interface;
1309 
1310  //No error to report
1311  return NO_ERROR;
1312 }
1313 
1314 
1315 /**
1316  * @brief Retrieve the underlying interface
1317  * @param[in] socket Handle to a socket
1318  * @return Pointer to the underlying network interface
1319  **/
1320 
1322 {
1323  NetInterface *interface = NULL;
1324 
1325  //Make sure the socket handle is valid
1326  if(socket != NULL)
1327  {
1328  interface = socket->interface;
1329  }
1330 
1331  //Return a pointer to the underlying network interface
1332  return interface;
1333 }
1334 
1335 
1336 /**
1337  * @brief Associate a local address with a socket
1338  * @param[in] socket Handle to a socket
1339  * @param[in] localIpAddr Local address to assign to the bound socket
1340  * @param[in] localPort Local port number to assign to the bound socket
1341  * @return Error code
1342  **/
1343 
1344 error_t socketBind(Socket *socket, const IpAddr *localIpAddr,
1345  uint16_t localPort)
1346 {
1347  //Check input parameters
1348  if(socket == NULL || localIpAddr == NULL)
1349  return ERROR_INVALID_PARAMETER;
1350 
1351  //Make sure the socket type is correct
1352  if(socket->type != SOCKET_TYPE_STREAM &&
1353  socket->type != SOCKET_TYPE_DGRAM &&
1354  socket->type != SOCKET_TYPE_RAW_IP)
1355  {
1356  return ERROR_INVALID_SOCKET;
1357  }
1358 
1359  //Associate the specified IP address and port number
1360  socket->localIpAddr = *localIpAddr;
1361  socket->localPort = localPort;
1362 
1363  //No error to report
1364  return NO_ERROR;
1365 }
1366 
1367 
1368 /**
1369  * @brief Establish a connection to a specified socket
1370  * @param[in] socket Handle to an unconnected socket
1371  * @param[in] remoteIpAddr IP address of the remote host
1372  * @param[in] remotePort Remote port number that will be used to establish
1373  * the connection
1374  * @return Error code
1375  **/
1376 
1377 error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr,
1378  uint16_t remotePort)
1379 {
1380  error_t error;
1381 
1382  //Check input parameters
1383  if(socket == NULL || remoteIpAddr == NULL)
1384  return ERROR_INVALID_PARAMETER;
1385 
1386 #if (TCP_SUPPORT == ENABLED)
1387  //Connection-oriented socket?
1388  if(socket->type == SOCKET_TYPE_STREAM)
1389  {
1390  //Get exclusive access
1391  netLock(socket->netContext);
1392 
1393  //Establish TCP connection
1394  error = tcpConnect(socket, remoteIpAddr, remotePort);
1395 
1396  //Release exclusive access
1397  netUnlock(socket->netContext);
1398  }
1399  else
1400 #endif
1401  //Connectionless socket?
1402  if(socket->type == SOCKET_TYPE_DGRAM)
1403  {
1404  //Save port number and IP address of the remote host
1405  socket->remoteIpAddr = *remoteIpAddr;
1406  socket->remotePort = remotePort;
1407  //No error to report
1408  error = NO_ERROR;
1409  }
1410  //Raw socket?
1411  else if(socket->type == SOCKET_TYPE_RAW_IP)
1412  {
1413  //Save the IP address of the remote host
1414  socket->remoteIpAddr = *remoteIpAddr;
1415  //No error to report
1416  error = NO_ERROR;
1417  }
1418  //Invalid socket type?
1419  else
1420  {
1421  //Report an error
1422  error = ERROR_INVALID_SOCKET;
1423  }
1424 
1425  //Return status code
1426  return error;
1427 }
1428 
1429 
1430 /**
1431  * @brief Place a socket in the listening state
1432  *
1433  * Place a socket in a state in which it is listening for an incoming connection
1434  *
1435  * @param[in] socket Socket to place in the listening state
1436  * @param[in] backlog backlog The maximum length of the pending connection queue.
1437  * If this parameter is zero, then the default backlog value is used instead
1438  * @return Error code
1439  **/
1440 
1442 {
1443 #if (TCP_SUPPORT == ENABLED)
1444  error_t error;
1445 
1446  //Make sure the socket handle is valid
1447  if(socket == NULL)
1448  return ERROR_INVALID_PARAMETER;
1449 
1450  //This function shall be used with connection-oriented sockets
1451  if(socket->type != SOCKET_TYPE_STREAM)
1452  return ERROR_INVALID_SOCKET;
1453 
1454  //Get exclusive access
1455  netLock(socket->netContext);
1456 
1457  //Start listening for an incoming connection
1458  error = tcpListen(socket, backlog);
1459 
1460  //Release exclusive access
1461  netUnlock(socket->netContext);
1462 
1463  //Return status code
1464  return error;
1465 #else
1466  return ERROR_NOT_IMPLEMENTED;
1467 #endif
1468 }
1469 
1470 
1471 /**
1472  * @brief Permit an incoming connection attempt on a socket
1473  * @param[in] socket Handle to a socket previously placed in a listening state
1474  * @param[out] clientIpAddr IP address of the client
1475  * @param[out] clientPort Port number used by the client
1476  * @return Handle to the socket in which the actual connection is made
1477  **/
1478 
1480  uint16_t *clientPort)
1481 {
1482 #if (TCP_SUPPORT == ENABLED)
1483  Socket *newSocket;
1484 
1485  //Make sure the socket handle is valid
1486  if(socket == NULL)
1487  return NULL;
1488 
1489  //This function shall be used with connection-oriented sockets
1490  if(socket->type != SOCKET_TYPE_STREAM)
1491  return NULL;
1492 
1493  //Accept an incoming connection attempt
1494  newSocket = tcpAccept(socket, clientIpAddr, clientPort);
1495 
1496  //Return a handle to the newly created socket
1497  return newSocket;
1498 #else
1499  return NULL;
1500 #endif
1501 }
1502 
1503 
1504 /**
1505  * @brief Send data to a connected socket
1506  * @param[in] socket Handle that identifies a connected socket
1507  * @param[in] data Pointer to a buffer containing the data to be transmitted
1508  * @param[in] length Number of data bytes to send
1509  * @param[out] written Actual number of bytes written (optional parameter)
1510  * @param[in] flags Set of flags that influences the behavior of this function
1511  * @return Error code
1512  **/
1513 
1514 error_t socketSend(Socket *socket, const void *data, size_t length,
1515  size_t *written, uint_t flags)
1516 {
1517  //Use default remote IP address for connectionless or raw sockets
1518  return socketSendTo(socket, &socket->remoteIpAddr, socket->remotePort,
1519  data, length, written, flags);
1520 }
1521 
1522 
1523 /**
1524  * @brief Send a datagram to a specific destination
1525  * @param[in] socket Handle that identifies a socket
1526  * @param[in] destIpAddr IP address of the target host
1527  * @param[in] destPort Target port number
1528  * @param[in] data Pointer to a buffer containing the data to be transmitted
1529  * @param[in] length Number of data bytes to send
1530  * @param[out] written Actual number of bytes written (optional parameter)
1531  * @param[in] flags Set of flags that influences the behavior of this function
1532  * @return Error code
1533  **/
1534 
1536  const void *data, size_t length, size_t *written, uint_t flags)
1537 {
1538  error_t error;
1539 
1540  //No data has been transmitted yet
1541  if(written != NULL)
1542  {
1543  *written = 0;
1544  }
1545 
1546  //Make sure the socket handle is valid
1547  if(socket == NULL)
1548  return ERROR_INVALID_PARAMETER;
1549 
1550  //Get exclusive access
1551  netLock(socket->netContext);
1552 
1553 #if (TCP_SUPPORT == ENABLED)
1554  //Connection-oriented socket?
1555  if(socket->type == SOCKET_TYPE_STREAM)
1556  {
1557  //For connection-oriented sockets, target address is ignored
1558  error = tcpSend(socket, data, length, written, flags);
1559  }
1560  else
1561 #endif
1562  {
1564 
1565  //Initialize structure
1567 
1568  //Set destination IP address
1569  if(destIpAddr != NULL)
1570  {
1571  message.destIpAddr = *destIpAddr;
1572  }
1573 
1574  //Set destination port
1575  message.destPort = destPort;
1576 
1577 #if (UDP_SUPPORT == ENABLED)
1578  //Connectionless socket?
1579  if(socket->type == SOCKET_TYPE_DGRAM)
1580  {
1581  //Set data payload
1582  message.data = (uint8_t *) data;
1583  message.length = length;
1584 
1585  //Send UDP datagram
1586  error = udpSendDatagram(socket, &message, flags);
1587  }
1588  else
1589 #endif
1590 #if (RAW_SOCKET_SUPPORT == ENABLED)
1591  //Raw socket?
1592  if(socket->type == SOCKET_TYPE_RAW_IP)
1593  {
1594  //Set data payload
1595  message.data = (uint8_t *) data;
1596  message.length = length;
1597 
1598  //Send a raw IP packet
1600  }
1601  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1602  {
1603  //Sanity check
1604  if(length >= sizeof(EthHeader))
1605  {
1606  EthHeader *header;
1607 
1608  //Point to the Ethernet header
1609  header = (EthHeader *) data;
1610 
1611  //Set source and destination MAC addresses
1612  message.srcMacAddr = header->srcAddr;
1613  message.destMacAddr = header->destAddr;
1614 
1615  //Set the value of the EtherType field
1616  message.ethType = ntohs(header->type);
1617 
1618  //Set data payload
1619  message.data = (uint8_t *) data + sizeof(EthHeader);
1620  message.length = length - sizeof(EthHeader);
1621 
1622  //Send a raw Ethernet packet
1624  }
1625  else
1626  {
1627  //Report an error
1628  error = ERROR_INVALID_LENGTH;
1629  }
1630  }
1631  else
1632 #endif
1633  //Invalid socket type?
1634  {
1635  //Report an error
1636  error = ERROR_INVALID_SOCKET;
1637  }
1638 
1639  //Check status code
1640  if(!error)
1641  {
1642  //Total number of data bytes successfully transmitted
1643  if(written != NULL)
1644  {
1645  *written = message.length;
1646  }
1647  }
1648  }
1649 
1650  //Release exclusive access
1651  netUnlock(socket->netContext);
1652 
1653  //Return status code
1654  return error;
1655 }
1656 
1657 
1658 /**
1659  * @brief Send a message to a connectionless socket
1660  * @param[in] socket Handle that identifies a socket
1661  * @param[in] message Pointer to the structure describing the message
1662  * @param[in] flags Set of flags that influences the behavior of this function
1663  * @return Error code
1664  **/
1665 
1667 {
1668  error_t error;
1669 
1670  //Make sure the socket handle is valid
1671  if(socket == NULL)
1672  return ERROR_INVALID_PARAMETER;
1673 
1674  //Get exclusive access
1675  netLock(socket->netContext);
1676 
1677 #if (UDP_SUPPORT == ENABLED)
1678  //Connectionless socket?
1679  if(socket->type == SOCKET_TYPE_DGRAM)
1680  {
1681  //Send UDP datagram
1682  error = udpSendDatagram(socket, message, flags);
1683  }
1684  else
1685 #endif
1686 #if (RAW_SOCKET_SUPPORT == ENABLED)
1687  //Raw socket?
1688  if(socket->type == SOCKET_TYPE_RAW_IP)
1689  {
1690  //Send a raw IP packet
1692  }
1693  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1694  {
1695  //Send a raw Ethernet packet
1697  }
1698  else
1699 #endif
1700  //Invalid socket type?
1701  {
1702  //Report an error
1703  error = ERROR_INVALID_SOCKET;
1704  }
1705 
1706  //Release exclusive access
1707  netUnlock(socket->netContext);
1708 
1709  //Return status code
1710  return error;
1711 }
1712 
1713 
1714 /**
1715  * @brief Receive data from a connected socket
1716  * @param[in] socket Handle that identifies a connected socket
1717  * @param[out] data Buffer where to store the incoming data
1718  * @param[in] size Maximum number of bytes that can be received
1719  * @param[out] received Number of bytes that have been received
1720  * @param[in] flags Set of flags that influences the behavior of this function
1721  * @return Error code
1722  **/
1723 
1725  size_t size, size_t *received, uint_t flags)
1726 {
1727  //For connection-oriented sockets, source and destination addresses are
1728  //no use
1729  return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received,
1730  flags);
1731 }
1732 
1733 
1734 /**
1735  * @brief Receive a datagram from a connectionless socket
1736  * @param[in] socket Handle that identifies a socket
1737  * @param[out] srcIpAddr Source IP address (optional)
1738  * @param[out] srcPort Source port number (optional)
1739  * @param[out] data Buffer where to store the incoming data
1740  * @param[in] size Maximum number of bytes that can be received
1741  * @param[out] received Number of bytes that have been received
1742  * @param[in] flags Set of flags that influences the behavior of this function
1743  * @return Error code
1744  **/
1745 
1747  void *data, size_t size, size_t *received, uint_t flags)
1748 {
1749  //Destination address is no use
1750  return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size,
1751  received, flags);
1752 }
1753 
1754 
1755 /**
1756  * @brief Receive a datagram
1757  * @param[in] socket Handle that identifies a socket
1758  * @param[out] srcIpAddr Source IP address (optional)
1759  * @param[out] srcPort Source port number (optional)
1760  * @param[out] destIpAddr Destination IP address (optional)
1761  * @param[out] data Buffer where to store the incoming data
1762  * @param[in] size Maximum number of bytes that can be received
1763  * @param[out] received Number of bytes that have been received
1764  * @param[in] flags Set of flags that influences the behavior of this function
1765  * @return Error code
1766  **/
1767 
1769  IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
1770 {
1771  error_t error;
1772 
1773  //No data has been received yet
1774  if(received != NULL)
1775  *received = 0;
1776 
1777  //Make sure the socket handle is valid
1778  if(socket == NULL)
1779  return ERROR_INVALID_PARAMETER;
1780 
1781  //Get exclusive access
1782  netLock(socket->netContext);
1783 
1784 #if (TCP_SUPPORT == ENABLED)
1785  //Connection-oriented socket?
1786  if(socket->type == SOCKET_TYPE_STREAM)
1787  {
1788  //Receive data
1789  error = tcpReceive(socket, data, size, received, flags);
1790 
1791  //Save the source IP address
1792  if(srcIpAddr != NULL)
1793  {
1794  *srcIpAddr = socket->remoteIpAddr;
1795  }
1796 
1797  //Save the source port number
1798  if(srcPort != NULL)
1799  {
1800  *srcPort = socket->remotePort;
1801  }
1802 
1803  //Save the destination IP address
1804  if(destIpAddr != NULL)
1805  {
1806  *destIpAddr = socket->localIpAddr;
1807  }
1808  }
1809  else
1810 #endif
1811  {
1813 
1814  //Initialize structure
1816 
1817 #if (UDP_SUPPORT == ENABLED)
1818  //Connectionless socket?
1819  if(socket->type == SOCKET_TYPE_DGRAM)
1820  {
1821  //Set data buffer
1822  message.data = data;
1823  message.size = size;
1824 
1825  //Receive UDP datagram
1826  error = udpReceiveDatagram(socket, &message, flags);
1827  }
1828  else
1829 #endif
1830 #if (RAW_SOCKET_SUPPORT == ENABLED)
1831  //Raw socket?
1832  if(socket->type == SOCKET_TYPE_RAW_IP)
1833  {
1834  //Set data buffer
1835  message.data = data;
1836  message.size = size;
1837 
1838  //Receive a raw IP packet
1840  }
1841  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1842  {
1843  //Sanity check
1844  if(size >= sizeof(EthHeader))
1845  {
1846  //Set data buffer
1847  message.data = (uint8_t *) data + sizeof(EthHeader);
1848  message.size = size - sizeof(EthHeader);
1849 
1850  //Receive a raw Ethernet packet
1852 
1853  //Check status code
1854  if(!error)
1855  {
1856  EthHeader *header;
1857 
1858  //Point to the Ethernet header
1859  header = (EthHeader *) data;
1860 
1861  //Reconstruct Ethernet header
1862  header->destAddr = message.destMacAddr;
1863  header->srcAddr = message.srcMacAddr;
1864  header->type = htons(message.ethType);
1865 
1866  //Ajust the length of the frame
1867  message.length += sizeof(EthHeader);
1868  }
1869  }
1870  else
1871  {
1872  //Report an error
1873  error = ERROR_BUFFER_OVERFLOW;
1874  }
1875  }
1876  else
1877 #endif
1878  //Invalid socket type?
1879  {
1880  //Report an error
1881  error = ERROR_INVALID_SOCKET;
1882  }
1883 
1884  //Check status code
1885  if(!error)
1886  {
1887  //Save the source IP address
1888  if(srcIpAddr != NULL)
1889  {
1890  *srcIpAddr = message.srcIpAddr;
1891  }
1892 
1893  //Save the source port number
1894  if(srcPort != NULL)
1895  {
1896  *srcPort = message.srcPort;
1897  }
1898 
1899  //Save the destination IP address
1900  if(destIpAddr != NULL)
1901  {
1902  *destIpAddr = message.destIpAddr;
1903  }
1904 
1905  //Total number of data that have been received
1906  *received = message.length;
1907  }
1908  }
1909 
1910  //Release exclusive access
1911  netUnlock(socket->netContext);
1912 
1913  //Return status code
1914  return error;
1915 }
1916 
1917 
1918 /**
1919  * @brief Receive a message from a connectionless socket
1920  * @param[in] socket Handle that identifies a socket
1921  * @param[in,out] message Pointer to the structure describing the message
1922  * @param[in] flags Set of flags that influences the behavior of this function
1923  * @return Error code
1924  **/
1925 
1927 {
1928  error_t error;
1929 
1930  //No data has been received yet
1931  message->length = 0;
1932 
1933  //Make sure the socket handle is valid
1934  if(socket == NULL)
1935  return ERROR_INVALID_PARAMETER;
1936 
1937  //Get exclusive access
1938  netLock(socket->netContext);
1939 
1940 #if (UDP_SUPPORT == ENABLED)
1941  //Connectionless socket?
1942  if(socket->type == SOCKET_TYPE_DGRAM)
1943  {
1944  //Receive UDP datagram
1946  }
1947  else
1948 #endif
1949 #if (RAW_SOCKET_SUPPORT == ENABLED)
1950  //Raw socket?
1951  if(socket->type == SOCKET_TYPE_RAW_IP)
1952  {
1953  //Receive a raw IP packet
1955  }
1956  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1957  {
1958  //Receive a raw Ethernet packet
1960  }
1961  else
1962 #endif
1963  //Invalid socket type?
1964  {
1965  //Report an error
1966  error = ERROR_INVALID_SOCKET;
1967  }
1968 
1969  //Release exclusive access
1970  netUnlock(socket->netContext);
1971 
1972  //Return status code
1973  return error;
1974 }
1975 
1976 
1977 /**
1978  * @brief Retrieve the local address for a given socket
1979  * @param[in] socket Handle that identifies a socket
1980  * @param[out] localIpAddr Local IP address (optional)
1981  * @param[out] localPort Local port number (optional)
1982  * @return Error code
1983  **/
1984 
1986  uint16_t *localPort)
1987 {
1988  //Make sure the socket handle is valid
1989  if(socket == NULL)
1990  return ERROR_INVALID_PARAMETER;
1991 
1992  //Retrieve local IP address
1993  if(localIpAddr != NULL)
1994  {
1995  *localIpAddr = socket->localIpAddr;
1996  }
1997 
1998  //Retrieve local port number
1999  if(localPort != NULL)
2000  {
2001  *localPort = socket->localPort;
2002  }
2003 
2004  //Successful processing
2005  return NO_ERROR;
2006 }
2007 
2008 
2009 /**
2010  * @brief Retrieve the address of the peer to which a socket is connected
2011  * @param[in] socket Handle that identifies a socket
2012  * @param[out] remoteIpAddr IP address of the remote host (optional)
2013  * @param[out] remotePort Remote port number (optional)
2014  * @return Error code
2015  **/
2016 
2018  uint16_t *remotePort)
2019 {
2020  //Make sure the socket handle is valid
2021  if(socket == NULL)
2022  return ERROR_INVALID_PARAMETER;
2023 
2024  //Retrieve local IP address
2025  if(remoteIpAddr != NULL)
2026  {
2027  *remoteIpAddr = socket->remoteIpAddr;
2028  }
2029 
2030  //Retrieve local port number
2031  if(remotePort != NULL)
2032  {
2033  *remotePort = socket->remotePort;
2034  }
2035 
2036  //Successful processing
2037  return NO_ERROR;
2038 }
2039 
2040 
2041 /**
2042  * @brief Disable reception, transmission, or both
2043  *
2044  * Note that socketShutdown() does not close the socket, and resources attached
2045  * to the socket will not be freed until socketClose() is invoked
2046  *
2047  * @param[in] socket Handle to a socket
2048  * @param[in] how Flag that describes what types of operation will no longer be allowed
2049  * @return Error code
2050  **/
2051 
2053 {
2054 #if (TCP_SUPPORT == ENABLED)
2055  error_t error;
2056 
2057  //Make sure the socket handle is valid
2058  if(socket == NULL)
2059  return ERROR_INVALID_PARAMETER;
2060 
2061  //Make sure the socket type is correct
2062  if(socket->type != SOCKET_TYPE_STREAM)
2063  return ERROR_INVALID_SOCKET;
2064 
2065  //Check flags
2066  if(how != SOCKET_SD_SEND && how != SOCKET_SD_RECEIVE &&
2067  how != SOCKET_SD_BOTH)
2068  {
2069  return ERROR_INVALID_PARAMETER;
2070  }
2071 
2072  //Get exclusive access
2073  netLock(socket->netContext);
2074 
2075  //Graceful shutdown
2076  error = tcpShutdown(socket, how);
2077 
2078  //Release exclusive access
2079  netUnlock(socket->netContext);
2080 
2081  //Return status code
2082  return error;
2083 #else
2084  return ERROR_NOT_IMPLEMENTED;
2085 #endif
2086 }
2087 
2088 
2089 /**
2090  * @brief Close an existing socket
2091  * @param[in] socket Handle identifying the socket to close
2092  **/
2093 
2095 {
2096  //Make sure the socket handle is valid
2097  if(socket == NULL)
2098  return;
2099 
2100  //Get exclusive access
2101  netLock(socket->netContext);
2102 
2103 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
2104  //Connectionless or raw socket?
2105  if(socket->type == SOCKET_TYPE_DGRAM ||
2106  socket->type == SOCKET_TYPE_RAW_IP)
2107  {
2108  uint_t i;
2109  IpAddr groupAddr;
2110 
2111  //Loop through multicast groups
2112  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
2113  {
2114  //Get current group address
2115  groupAddr = socket->multicastGroups[i].addr;
2116 
2117  //Valid multicast address?
2118  if(groupAddr.length != 0)
2119  {
2120  //Delete entry
2121  socket->multicastGroups[i].addr = IP_ADDR_UNSPECIFIED;
2122 
2123  //Update the multicast reception state of the interface
2124  ipUpdateMulticastFilter(socket->netContext, socket->interface,
2125  &groupAddr);
2126  }
2127  }
2128  }
2129 #endif
2130 
2131 #if (TCP_SUPPORT == ENABLED)
2132  //Connection-oriented socket?
2133  if(socket->type == SOCKET_TYPE_STREAM)
2134  {
2135  //Abort the current TCP connection
2136  tcpAbort(socket);
2137  }
2138 #endif
2139 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
2140  //Connectionless socket or raw socket?
2141  if(socket->type == SOCKET_TYPE_DGRAM ||
2142  socket->type == SOCKET_TYPE_RAW_IP ||
2143  socket->type == SOCKET_TYPE_RAW_ETH)
2144  {
2145  //Point to the first item in the receive queue
2146  SocketQueueItem *queueItem = socket->receiveQueue;
2147 
2148  //Purge the receive queue
2149  while(queueItem != NULL)
2150  {
2151  //Keep track of the next item in the queue
2152  SocketQueueItem *nextQueueItem = queueItem->next;
2153  //Free previously allocated memory
2154  netBufferFree(queueItem->buffer);
2155  //Point to the next item
2156  queueItem = nextQueueItem;
2157  }
2158 
2159  //Mark the socket as closed
2160  socket->type = SOCKET_TYPE_UNUSED;
2161  }
2162 #endif
2163 
2164  //Release exclusive access
2165  netUnlock(socket->netContext);
2166 }
2167 
2168 
2169 /**
2170  * @brief Wait for one of a set of sockets to become ready to perform I/O
2171  *
2172  * This function determines the status of one or more sockets, waiting if
2173  * necessary, to perform synchronous I/O
2174  *
2175  * @param[in,out] eventDesc Set of entries specifying the events the user is interested in
2176  * @param[in] size Number of entries in the descriptor set
2177  * @param[in] extEvent External event that can abort the wait if necessary (optional)
2178  * @param[in] timeout Maximum time to wait before returning
2179  * @return Error code
2180  **/
2181 
2182 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent,
2183  systime_t timeout)
2184 {
2185  error_t error;
2186  uint_t i;
2187  bool_t status;
2188  OsEvent *event;
2189  OsEvent eventObject;
2190 
2191  //Check parameters
2192  if(eventDesc == NULL || size == 0)
2193  return ERROR_INVALID_PARAMETER;
2194 
2195  //Try to use the supplied event object to receive notifications
2196  if(extEvent == NULL)
2197  {
2198  //Create an event object only if necessary
2199  if(!osCreateEvent(&eventObject))
2200  {
2201  //Report an error
2202  return ERROR_OUT_OF_RESOURCES;
2203  }
2204 
2205  //Reference to the newly created event
2206  event = &eventObject;
2207  }
2208  else
2209  {
2210  //Reference to the external event
2211  event = extEvent;
2212  }
2213 
2214  //Loop through descriptors
2215  for(i = 0; i < size; i++)
2216  {
2217  //Valid socket handle?
2218  if(eventDesc[i].socket != NULL)
2219  {
2220  //Clear event flags
2221  eventDesc[i].eventFlags = 0;
2222 
2223  //Subscribe to the requested events
2224  socketRegisterEvents(eventDesc[i].socket, event,
2225  eventDesc[i].eventMask);
2226  }
2227  }
2228 
2229  //Block the current task until an event occurs
2230  status = osWaitForEvent(event, timeout);
2231 
2232  //Any event?
2233  if(status)
2234  {
2235  //Clear flag
2236  status = FALSE;
2237 
2238  //Loop through descriptors
2239  for(i = 0; i < size; i++)
2240  {
2241  //Valid socket handle?
2242  if(eventDesc[i].socket != NULL)
2243  {
2244  //Retrieve event flags for the current socket
2245  eventDesc[i].eventFlags = socketGetEvents(eventDesc[i].socket);
2246  //Clear unnecessary flags
2247  eventDesc[i].eventFlags &= eventDesc[i].eventMask;
2248 
2249  //Check whether the socket is ready to perform I/O
2250  if(eventDesc[i].eventFlags != 0)
2251  {
2252  status = TRUE;
2253  }
2254  }
2255  }
2256 
2257  //Any socket event in the signaled state?
2258  if(status)
2259  {
2260  error = NO_ERROR;
2261  }
2262  else
2263  {
2264  error = ERROR_WAIT_CANCELED;
2265  }
2266  }
2267  else
2268  {
2269  //Report a timeout error
2270  error = ERROR_TIMEOUT;
2271  }
2272 
2273  //Loop through descriptors
2274  for(i = 0; i < size; i++)
2275  {
2276  //Valid socket handle?
2277  if(eventDesc[i].socket != NULL)
2278  {
2279  //Unsubscribe previously registered events
2280  socketUnregisterEvents(eventDesc[i].socket);
2281  }
2282  }
2283 
2284  //Reset event object
2285  osResetEvent(event);
2286 
2287  //Release previously allocated resources
2288  if(extEvent == NULL)
2289  {
2290  osDeleteEvent(&eventObject);
2291  }
2292 
2293  //Return status code
2294  return error;
2295 }
2296 
2297 
2298 /**
2299  * @brief Resolve a host name into an IP address
2300  * @param[in] interface Underlying network interface (optional parameter)
2301  * @param[in] name Name of the host to be resolved
2302  * @param[out] ipAddr IP address corresponding to the specified host name
2303  * @param[in] flags Set of flags that influences the behavior of this function
2304  * @return Error code
2305  **/
2306 
2309 {
2310  error_t error;
2311  HostType type;
2313 
2314  //Default address type depends on TCP/IP stack configuration
2315 #if (IPV4_SUPPORT == ENABLED)
2316  type = HOST_TYPE_IPV4;
2317 #elif (IPV6_SUPPORT == ENABLED)
2318  type = HOST_TYPE_IPV6;
2319 #else
2320  type = HOST_TYPE_ANY;
2321 #endif
2322 
2323  //Default name resolution protocol depends on TCP/IP stack configuration
2324 #if (DNS_CLIENT_SUPPORT == ENABLED)
2326 #elif (MDNS_CLIENT_SUPPORT == ENABLED)
2328 #elif (NBNS_CLIENT_SUPPORT == ENABLED)
2330 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2332 #else
2334 #endif
2335 
2336  //Check parameters
2337  if(name == NULL || ipAddr == NULL)
2338  return ERROR_INVALID_PARAMETER;
2339 
2340  //Use default network interface?
2341  if(interface == NULL)
2342  {
2343  interface = netGetDefaultInterface(NULL);
2344  }
2345 
2346  //The specified name can be either an IP or a host name
2347  error = ipStringToAddr(name, ipAddr);
2348 
2349  //Perform name resolution if necessary
2350  if(error)
2351  {
2352  //The user may provide a hint to choose between IPv4 and IPv6
2353  if((flags & HOST_TYPE_IPV4) != 0)
2354  {
2355  type = HOST_TYPE_IPV4;
2356  }
2357  else if((flags & HOST_TYPE_IPV6) != 0)
2358  {
2359  type = HOST_TYPE_IPV6;
2360  }
2361  else
2362  {
2363  //Just for sanity
2364  }
2365 
2366  //The user may provide a hint to to select the desired protocol to be used
2367  if((flags & HOST_NAME_RESOLVER_DNS) != 0)
2368  {
2369  //Use DNS to resolve the specified host name
2371  }
2372  else if((flags & HOST_NAME_RESOLVER_MDNS) != 0)
2373  {
2374  //Use mDNS to resolve the specified host name
2376  }
2377  else if((flags & HOST_NAME_RESOLVER_NBNS) != 0)
2378  {
2379  //Use NBNS to resolve the specified host name
2381  }
2382  else if((flags & HOST_NAME_RESOLVER_LLMNR) != 0)
2383  {
2384  //Use LLMNR to resolve the specified host name
2386  }
2387  else
2388  {
2389  //Retrieve the length of the host name to be resolved
2390  size_t n = osStrlen(name);
2391 
2392  //Select the most suitable protocol
2393  if(n >= 6 && osStrcasecmp(name + n - 6, ".local") == 0)
2394  {
2395 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2396  //Use mDNS to resolve the specified host name
2398 #endif
2399  }
2400  else if(n <= 15 && osStrchr(name, '.') == NULL &&
2401  type == HOST_TYPE_IPV4)
2402  {
2403 #if (NBNS_CLIENT_SUPPORT == ENABLED)
2404  //Use NetBIOS Name Service to resolve the specified host name
2406 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2407  //Use LLMNR to resolve the specified host name
2409 #endif
2410  }
2411  else if(osStrchr(name, '.') == NULL)
2412  {
2413 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2414  //Use LLMNR to resolve the specified host name
2416 #endif
2417  }
2418  }
2419 
2420 #if (DNS_CLIENT_SUPPORT == ENABLED)
2421  //Use DNS protocol?
2423  {
2424  //Perform host name resolution
2425  error = dnsResolve(interface, name, type, ipAddr);
2426  }
2427  else
2428 #endif
2429 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2430  //Use mDNS protocol?
2432  {
2433  //Perform host name resolution
2434  error = mdnsClientResolve(interface, name, type, ipAddr);
2435  }
2436  else
2437 #endif
2438 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
2439  //Use NetBIOS Name Service protocol?
2441  {
2442  //Perform host name resolution
2443  error = nbnsResolve(interface, name, ipAddr);
2444  }
2445  else
2446 #endif
2447 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2448  //Use LLMNR protocol?
2450  {
2451  //Perform host name resolution
2452  error = llmnrResolve(interface, name, type, ipAddr);
2453  }
2454  else
2455 #endif
2456  //Invalid protocol?
2457  {
2458  //Just for sanity
2459  (void) protocol;
2460  //Report an error
2461  error = ERROR_INVALID_PARAMETER;
2462  }
2463  }
2464 
2465  //Return status code
2466  return error;
2467 }
error_t socketSend(Socket *socket, const void *data, size_t length, size_t *written, uint_t flags)
Send data to a connected socket.
Definition: socket.c:1514
IpFilterMode
Multicast filter mode.
Definition: ip.h:67
#define htons(value)
Definition: cpu_endian.h:413
error_t rawSocketSendEthPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw Ethernet packet.
Definition: raw_socket.c:726
HostType
Host types.
Definition: socket.h:215
#define osStrchr(s, c)
Definition: os_port.h:198
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:1344
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define NetContext
Definition: net.h:36
error_t socketSetDscp(Socket *socket, uint8_t dscp)
Set DSCP field.
Definition: socket.c:244
Multicast group.
Definition: socket.h:273
HostnameResolver
Name resolution protocols.
Definition: socket.h:227
void tcpComputeWindowScaleFactor(Socket *socket)
Compute the window scale factor to use for the receive window.
Definition: tcp_misc.c:1583
int bool_t
Definition: compiler_port.h:63
uint8_t protocol
Definition: ipv4.h:351
@ HOST_NAME_RESOLVER_DNS
Definition: socket.h:229
IP network address.
Definition: ip.h:90
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ HOST_TYPE_ANY
Definition: socket.h:216
uint8_t message[]
Definition: chap.h:154
error_t tcpReceive(Socket *socket, uint8_t *data, size_t size, size_t *received, uint_t flags)
Receive data from a connected socket.
Definition: tcp.c:671
error_t socketInit(NetContext *context)
Socket related initialization.
Definition: socket.c:86
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:54
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
Message and ancillary data.
Definition: socket.h:241
#define SOCKET_MAX_MULTICAST_GROUPS
Definition: socket.h:53
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2094
Event object.
error_t socketJoinMulticastGroup(Socket *socket, const IpAddr *groupAddr)
Join the specified host group.
Definition: socket.c:447
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ HOST_NAME_RESOLVER_LLMNR
Definition: socket.h:232
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
@ IP_FILTER_MODE_EXCLUDE
Definition: ip.h:68
error_t socketSetMulticastSourceFilter(Socket *socket, const IpAddr *groupAddr, IpFilterMode filterMode, const IpAddr *sources, uint_t numSources)
Set multicast source filter (full-state API)
Definition: socket.c:583
uint8_t type
Definition: coap_common.h:176
SocketMulticastGroup * socketCreateMulticastGroupEntry(Socket *socket, const IpAddr *groupAddr)
Create a new multicast group.
Definition: socket_misc.c:391
#define TCP_MAX_MSS
Definition: tcp.h:54
char_t name[]
uint16_t destPort
Definition: tcp.h:347
#define osStrlen(s)
Definition: os_port.h:168
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
struct _SocketQueueItem * next
Definition: socket.h:289
#define IP_DEFAULT_DF
Definition: ip.h:40
error_t tcpListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: tcp.c:292
EthHeader
Definition: ethernet.h:225
@ SOCKET_TYPE_STREAM
Definition: socket.h:92
error_t socketGetRemoteAddr(Socket *socket, IpAddr *remoteIpAddr, uint16_t *remotePort)
Retrieve the address of the peer to which a socket is connected.
Definition: socket.c:2017
error_t udpReceiveDatagram(Socket *socket, SocketMsg *message, uint_t flags)
Receive data from a UDP socket.
Definition: udp.c:843
Structure describing socket events.
Definition: socket.h:433
error_t socketSetVmanDei(Socket *socket, bool_t dei)
Set VMAN DEI flag.
Definition: socket.c:380
error_t rawSocketSendIpPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw IP packet.
Definition: raw_socket.c:532
error_t socketSetTxBufferSize(Socket *socket, size_t size)
Specify the size of the TCP send buffer.
Definition: socket.c:1224
@ HOST_TYPE_IPV6
Definition: socket.h:218
error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
Convert a string representation of an IP address to a binary IP address.
Definition: ip.c:766
@ SOCKET_SD_SEND
Definition: socket.h:160
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1666
#define FALSE
Definition: os_port.h:46
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:52
void socketRemoveMulticastSrcAddr(SocketMulticastGroup *group, const IpAddr *srcAddr)
Remove an address from the multicast source filter.
Definition: socket_misc.c:531
error_t socketSetRxBufferSize(Socket *socket, size_t size)
Specify the size of the TCP receive buffer.
Definition: socket.c:1261
Helper functions for TCP.
void socketDeleteMulticastGroupEntry(SocketMulticastGroup *group)
Delete a multicast group.
Definition: socket_misc.c:476
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
error_t socketEnableKeepAlive(Socket *socket, bool_t enabled)
Enable TCP keep-alive.
Definition: socket.c:1096
error_t dnsResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using DNS.
Definition: dns_client.c:54
error_t
Error codes.
Definition: error.h:43
void ipUpdateMulticastFilter(NetContext *context, NetInterface *interface, const IpAddr *groupAddr)
Update IP multicast filter table.
Definition: ip.c:411
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:251
#define TCP_MAX_RX_BUFFER_SIZE
Definition: tcp.h:89
error_t socketReceive(Socket *socket, void *data, size_t size, size_t *received, uint_t flags)
Receive data from a connected socket.
Definition: socket.c:1724
error_t tcpSend(Socket *socket, const uint8_t *data, size_t length, size_t *written, uint_t flags)
Send data to a connected socket.
Definition: tcp.c:542
error_t socketEnableBroadcast(Socket *socket, bool_t enabled)
Enable reception of broadcast messages.
Definition: socket.c:413
Socket * socketAllocate(NetContext *context, uint_t type, uint_t protocol)
Allocate a socket.
Definition: socket_misc.c:53
error_t socketAddMulticastSource(Socket *socket, const IpAddr *groupAddr, const IpAddr *srcAddr)
Accept specific source for specific group (delta-based API)
Definition: socket.c:774
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
@ HOST_NAME_RESOLVER_MDNS
Definition: socket.h:230
NBNS client (NetBIOS Name Service)
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
TcpState tcpGetState(Socket *socket)
Get the current state of the TCP FSM.
Definition: tcp.c:1033
error_t socketSetVmanPcp(Socket *socket, uint8_t pcp)
Set VMAN priority.
Definition: socket.c:343
void osDeleteEvent(OsEvent *event)
Delete an event object.
@ ERROR_INVALID_SOCKET
Definition: error.h:83
#define NetInterface
Definition: net.h:40
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define osStrcasecmp(s1, s2)
Definition: os_port.h:186
error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram from a connectionless socket.
Definition: socket.c:1746
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1926
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
error_t getHostByName(NetInterface *interface, const char_t *name, IpAddr *ipAddr, uint_t flags)
Resolve a host name into an IP address.
Definition: socket.c:2307
@ SOCKET_OPTION_BROADCAST
Definition: socket.h:193
error_t socketSetTtl(Socket *socket, uint8_t ttl)
Set TTL value for unicast datagrams.
Definition: socket.c:194
mDNS client (Multicast DNS)
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:1377
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:94
error_t llmnrResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using LLMNR.
Definition: llmnr_client.c:53
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:2052
error_t socketSetMaxSegmentSize(Socket *socket, size_t mss)
Specify the maximum segment size for outgoing TCP packets.
Definition: socket.c:1187
error_t udpSendDatagram(Socket *socket, const SocketMsg *message, uint_t flags)
Send a UDP datagram.
Definition: udp.c:514
uint8_t length
Definition: tcp.h:375
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:126
#define MIN(a, b)
Definition: os_port.h:63
@ HOST_TYPE_IPV4
Definition: socket.h:217
uint_t eventFlags
Returned events.
Definition: socket.h:436
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:2182
#define TCP_MAX_TX_BUFFER_SIZE
Definition: tcp.h:75
error_t socketSetVlanDei(Socket *socket, bool_t dei)
Set VLAN DEI flag.
Definition: socket.c:310
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:1479
DNS client (Domain Name System)
TCP/IP raw sockets.
error_t socketSetVlanPcp(Socket *socket, uint8_t pcp)
Set VLAN priority.
Definition: socket.c:273
error_t socketSetKeepAliveParams(Socket *socket, systime_t idle, systime_t interval, uint_t maxProbes)
Set TCP keep-alive parameters.
Definition: socket.c:1145
uint32_t systime_t
System time.
@ TCP_STATE_CLOSED
Definition: tcp.h:275
#define ntohs(value)
Definition: cpu_endian.h:421
Receive queue item.
Definition: socket.h:288
error_t socketAddMulticastSrcAddr(SocketMulticastGroup *group, const IpAddr *srcAddr)
Add an address to the multicast source filter.
Definition: socket_misc.c:490
#define MAX(a, b)
Definition: os_port.h:67
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:55
LLMNR client (Link-Local Multicast Name Resolution)
void socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
Subscribe to the specified socket events.
Definition: socket_misc.c:200
error_t socketGetMulticastSourceFilter(Socket *socket, const IpAddr *groupAddr, IpFilterMode *filterMode, IpAddr *sources, uint_t *numSources)
Get multicast source filter.
Definition: socket.c:700
Helper functions for sockets.
error_t socketSetInterface(Socket *socket, NetInterface *interface)
Bind a socket to a particular network interface.
Definition: socket.c:1301
@ HOST_NAME_RESOLVER_ANY
Definition: socket.h:228
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
TCP (Transmission Control Protocol)
@ SOCKET_TYPE_UNUSED
Definition: socket.h:91
error_t socketBlockMulticastSource(Socket *socket, const IpAddr *groupAddr, const IpAddr *srcAddr)
Block specific source for specific group (delta-based API)
Definition: socket.c:939
error_t socketGetLocalAddr(Socket *socket, IpAddr *localIpAddr, uint16_t *localPort)
Retrieve the local address for a given socket.
Definition: socket.c:1985
Ipv4Addr groupAddr
Definition: igmp_common.h:214
@ SOCKET_SD_RECEIVE
Definition: socket.h:159
Socket * socketOpenEx(NetContext *context, uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:146
error_t tcpAbort(Socket *socket)
Abort an existing TCP connection.
Definition: tcp.c:970
error_t rawSocketReceiveEthPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an Ethernet packet from a raw socket.
Definition: raw_socket.c:925
error_t mdnsClientResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using mDNS.
Definition: mdns_client.c:55
UDP (User Datagram Protocol)
#define Socket
Definition: socket.h:36
@ HOST_NAME_RESOLVER_NBNS
Definition: socket.h:231
@ IP_FILTER_MODE_INCLUDE
Definition: ip.h:69
NetInterface * socketGetInterface(Socket *socket)
Retrieve the underlying interface.
Definition: socket.c:1321
@ ERROR_WAIT_CANCELED
Definition: error.h:73
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define SOCKET_MAX_MULTICAST_SOURCES
Definition: socket.h:60
MacAddr srcAddr
Definition: ethernet.h:222
#define TCP_MIN_MSS
Definition: tcp.h:61
Socket API.
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1535
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
@ ERROR_ADDRESS_NOT_FOUND
Definition: error.h:259
error_t socketSetMulticastTtl(Socket *socket, uint8_t ttl)
Set TTL value for multicast datagrams.
Definition: socket.c:219
error_t tcpConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a TCP connection.
Definition: tcp.c:142
error_t socketUnblockMulticastSource(Socket *socket, const IpAddr *groupAddr, const IpAddr *srcAddr)
Unblock specific source for specific group (delta-based API)
Definition: socket.c:1026
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
Ipv4Addr ipAddr
Definition: ipcp.h:105
error_t socketReceiveEx(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram.
Definition: socket.c:1768
error_t tcpShutdown(Socket *socket, uint_t how)
Shutdown gracefully reception, transmission, or both.
Definition: tcp.c:832
uint32_t ttl
Definition: dns_common.h:224
uint8_t flags
Definition: tcp.h:358
Socket * tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a TCP socket.
Definition: tcp.c:319
unsigned int uint_t
Definition: compiler_port.h:57
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:255
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
error_t rawSocketReceiveIpPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an IP packet from a raw socket.
Definition: raw_socket.c:819
#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:440
@ SOCKET_SD_BOTH
Definition: socket.h:161
error_t socketDropMulticastSource(Socket *socket, const IpAddr *groupAddr, const IpAddr *srcAddr)
Drop specific source for specific group (delta-based API)
Definition: socket.c:861
error_t socketLeaveMulticastGroup(Socket *socket, const IpAddr *groupAddr)
Leave the specified host group.
Definition: socket.c:515
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:169
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:278
NetBuffer * buffer
Definition: socket.h:294
uint_t eventMask
Requested events.
Definition: socket.h:435
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t nbnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr)
Resolve a host name using NBNS.
Definition: nbns_client.c:53
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:1441