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