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.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  * @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  *written = 0;
1520 
1521  //Make sure the socket handle is valid
1522  if(socket == NULL)
1523  return ERROR_INVALID_PARAMETER;
1524 
1525  //Get exclusive access
1527 
1528 #if (TCP_SUPPORT == ENABLED)
1529  //Connection-oriented socket?
1530  if(socket->type == SOCKET_TYPE_STREAM)
1531  {
1532  //For connection-oriented sockets, target address is ignored
1533  error = tcpSend(socket, data, length, written, flags);
1534  }
1535  else
1536 #endif
1537  {
1539 
1540  //Initialize structure
1542 
1543  //Set destination IP address
1544  if(destIpAddr != NULL)
1545  {
1546  message.destIpAddr = *destIpAddr;
1547  }
1548 
1549  //Set destination port
1550  message.destPort = destPort;
1551 
1552 #if (UDP_SUPPORT == ENABLED)
1553  //Connectionless socket?
1554  if(socket->type == SOCKET_TYPE_DGRAM)
1555  {
1556  //Set data payload
1557  message.data = (uint8_t *) data;
1558  message.length = length;
1559 
1560  //Send UDP datagram
1561  error = udpSendDatagram(socket, &message, flags);
1562  }
1563  else
1564 #endif
1565 #if (RAW_SOCKET_SUPPORT == ENABLED)
1566  //Raw socket?
1567  if(socket->type == SOCKET_TYPE_RAW_IP)
1568  {
1569  //Set data payload
1570  message.data = (uint8_t *) data;
1571  message.length = length;
1572 
1573  //Send a raw IP packet
1575  }
1576  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1577  {
1578  //Sanity check
1579  if(length >= sizeof(EthHeader))
1580  {
1581  EthHeader *header;
1582 
1583  //Point to the Ethernet header
1584  header = (EthHeader *) data;
1585 
1586  //Set source and destination MAC addresses
1587  message.srcMacAddr = header->srcAddr;
1588  message.destMacAddr = header->destAddr;
1589 
1590  //Set the value of the EtherType field
1591  message.ethType = ntohs(header->type);
1592 
1593  //Set data payload
1594  message.data = (uint8_t *) data + sizeof(EthHeader);
1595  message.length = length - sizeof(EthHeader);
1596 
1597  //Send a raw Ethernet packet
1599  }
1600  else
1601  {
1602  //Report an error
1603  error = ERROR_INVALID_LENGTH;
1604  }
1605  }
1606  else
1607 #endif
1608  //Invalid socket type?
1609  {
1610  //Report an error
1611  error = ERROR_INVALID_SOCKET;
1612  }
1613 
1614  //Check status code
1615  if(!error)
1616  {
1617  //Total number of data bytes successfully transmitted
1618  if(written != NULL)
1619  *written = message.length;
1620  }
1621  }
1622 
1623  //Release exclusive access
1625 
1626  //Return status code
1627  return error;
1628 }
1629 
1630 
1631 /**
1632  * @brief Send a message to a connectionless socket
1633  * @param[in] socket Handle that identifies a socket
1634  * @param[in] message Pointer to the structure describing the message
1635  * @param[in] flags Set of flags that influences the behavior of this function
1636  * @return Error code
1637  **/
1638 
1640 {
1641  error_t error;
1642 
1643  //Make sure the socket handle is valid
1644  if(socket == NULL)
1645  return ERROR_INVALID_PARAMETER;
1646 
1647  //Get exclusive access
1649 
1650 #if (UDP_SUPPORT == ENABLED)
1651  //Connectionless socket?
1652  if(socket->type == SOCKET_TYPE_DGRAM)
1653  {
1654  //Send UDP datagram
1655  error = udpSendDatagram(socket, message, flags);
1656  }
1657  else
1658 #endif
1659 #if (RAW_SOCKET_SUPPORT == ENABLED)
1660  //Raw socket?
1661  if(socket->type == SOCKET_TYPE_RAW_IP)
1662  {
1663  //Send a raw IP packet
1665  }
1666  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1667  {
1668  //Send a raw Ethernet packet
1670  }
1671  else
1672 #endif
1673  //Invalid socket type?
1674  {
1675  //Report an error
1676  error = ERROR_INVALID_SOCKET;
1677  }
1678 
1679  //Release exclusive access
1681 
1682  //Return status code
1683  return error;
1684 }
1685 
1686 
1687 /**
1688  * @brief Receive data from a connected socket
1689  * @param[in] socket Handle that identifies a connected socket
1690  * @param[out] data Buffer where to store the incoming data
1691  * @param[in] size Maximum number of bytes that can be received
1692  * @param[out] received Number of bytes that have been received
1693  * @param[in] flags Set of flags that influences the behavior of this function
1694  * @return Error code
1695  **/
1696 
1698  size_t size, size_t *received, uint_t flags)
1699 {
1700  //For connection-oriented sockets, source and destination addresses are
1701  //no use
1702  return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received,
1703  flags);
1704 }
1705 
1706 
1707 /**
1708  * @brief Receive a datagram from a connectionless socket
1709  * @param[in] socket Handle that identifies a socket
1710  * @param[out] srcIpAddr Source IP address (optional)
1711  * @param[out] srcPort Source port number (optional)
1712  * @param[out] data Buffer where to store the incoming data
1713  * @param[in] size Maximum number of bytes that can be received
1714  * @param[out] received Number of bytes that have been received
1715  * @param[in] flags Set of flags that influences the behavior of this function
1716  * @return Error code
1717  **/
1718 
1720  void *data, size_t size, size_t *received, uint_t flags)
1721 {
1722  //Destination address is no use
1723  return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size,
1724  received, flags);
1725 }
1726 
1727 
1728 /**
1729  * @brief Receive a datagram
1730  * @param[in] socket Handle that identifies a socket
1731  * @param[out] srcIpAddr Source IP address (optional)
1732  * @param[out] srcPort Source port number (optional)
1733  * @param[out] destIpAddr Destination IP address (optional)
1734  * @param[out] data Buffer where to store the incoming data
1735  * @param[in] size Maximum number of bytes that can be received
1736  * @param[out] received Number of bytes that have been received
1737  * @param[in] flags Set of flags that influences the behavior of this function
1738  * @return Error code
1739  **/
1740 
1742  IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
1743 {
1744  error_t error;
1745 
1746  //No data has been received yet
1747  if(received != NULL)
1748  *received = 0;
1749 
1750  //Make sure the socket handle is valid
1751  if(socket == NULL)
1752  return ERROR_INVALID_PARAMETER;
1753 
1754  //Get exclusive access
1756 
1757 #if (TCP_SUPPORT == ENABLED)
1758  //Connection-oriented socket?
1759  if(socket->type == SOCKET_TYPE_STREAM)
1760  {
1761  //Receive data
1762  error = tcpReceive(socket, data, size, received, flags);
1763 
1764  //Save the source IP address
1765  if(srcIpAddr != NULL)
1766  {
1767  *srcIpAddr = socket->remoteIpAddr;
1768  }
1769 
1770  //Save the source port number
1771  if(srcPort != NULL)
1772  {
1773  *srcPort = socket->remotePort;
1774  }
1775 
1776  //Save the destination IP address
1777  if(destIpAddr != NULL)
1778  {
1779  *destIpAddr = socket->localIpAddr;
1780  }
1781  }
1782  else
1783 #endif
1784  {
1786 
1787  //Initialize structure
1789 
1790 #if (UDP_SUPPORT == ENABLED)
1791  //Connectionless socket?
1792  if(socket->type == SOCKET_TYPE_DGRAM)
1793  {
1794  //Set data buffer
1795  message.data = data;
1796  message.size = size;
1797 
1798  //Receive UDP datagram
1799  error = udpReceiveDatagram(socket, &message, flags);
1800  }
1801  else
1802 #endif
1803 #if (RAW_SOCKET_SUPPORT == ENABLED)
1804  //Raw socket?
1805  if(socket->type == SOCKET_TYPE_RAW_IP)
1806  {
1807  //Set data buffer
1808  message.data = data;
1809  message.size = size;
1810 
1811  //Receive a raw IP packet
1813  }
1814  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1815  {
1816  //Sanity check
1817  if(size >= sizeof(EthHeader))
1818  {
1819  //Set data buffer
1820  message.data = (uint8_t *) data + sizeof(EthHeader);
1821  message.size = size - sizeof(EthHeader);
1822 
1823  //Receive a raw Ethernet packet
1825 
1826  //Check status code
1827  if(!error)
1828  {
1829  EthHeader *header;
1830 
1831  //Point to the Ethernet header
1832  header = (EthHeader *) data;
1833 
1834  //Reconstruct Ethernet header
1835  header->destAddr = message.destMacAddr;
1836  header->srcAddr = message.srcMacAddr;
1837  header->type = htons(message.ethType);
1838 
1839  //Ajust the length of the frame
1840  message.length += sizeof(EthHeader);
1841  }
1842  }
1843  else
1844  {
1845  //Report an error
1846  error = ERROR_BUFFER_OVERFLOW;
1847  }
1848  }
1849  else
1850 #endif
1851  //Invalid socket type?
1852  {
1853  //Report an error
1854  error = ERROR_INVALID_SOCKET;
1855  }
1856 
1857  //Check status code
1858  if(!error)
1859  {
1860  //Save the source IP address
1861  if(srcIpAddr != NULL)
1862  {
1863  *srcIpAddr = message.srcIpAddr;
1864  }
1865 
1866  //Save the source port number
1867  if(srcPort != NULL)
1868  {
1869  *srcPort = message.srcPort;
1870  }
1871 
1872  //Save the destination IP address
1873  if(destIpAddr != NULL)
1874  {
1875  *destIpAddr = message.destIpAddr;
1876  }
1877 
1878  //Total number of data that have been received
1879  *received = message.length;
1880  }
1881  }
1882 
1883  //Release exclusive access
1885 
1886  //Return status code
1887  return error;
1888 }
1889 
1890 
1891 /**
1892  * @brief Receive a message from a connectionless socket
1893  * @param[in] socket Handle that identifies a socket
1894  * @param[in,out] message Pointer to the structure describing the message
1895  * @param[in] flags Set of flags that influences the behavior of this function
1896  * @return Error code
1897  **/
1898 
1900 {
1901  error_t error;
1902 
1903  //No data has been received yet
1904  message->length = 0;
1905 
1906  //Make sure the socket handle is valid
1907  if(socket == NULL)
1908  return ERROR_INVALID_PARAMETER;
1909 
1910  //Get exclusive access
1912 
1913 #if (UDP_SUPPORT == ENABLED)
1914  //Connectionless socket?
1915  if(socket->type == SOCKET_TYPE_DGRAM)
1916  {
1917  //Receive UDP datagram
1919  }
1920  else
1921 #endif
1922 #if (RAW_SOCKET_SUPPORT == ENABLED)
1923  //Raw socket?
1924  if(socket->type == SOCKET_TYPE_RAW_IP)
1925  {
1926  //Receive a raw IP packet
1928  }
1929  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1930  {
1931  //Receive a raw Ethernet packet
1933  }
1934  else
1935 #endif
1936  //Invalid socket type?
1937  {
1938  //Report an error
1939  error = ERROR_INVALID_SOCKET;
1940  }
1941 
1942  //Release exclusive access
1944 
1945  //Return status code
1946  return error;
1947 }
1948 
1949 
1950 /**
1951  * @brief Retrieve the local address for a given socket
1952  * @param[in] socket Handle that identifies a socket
1953  * @param[out] localIpAddr Local IP address (optional)
1954  * @param[out] localPort Local port number (optional)
1955  * @return Error code
1956  **/
1957 
1959  uint16_t *localPort)
1960 {
1961  //Make sure the socket handle is valid
1962  if(socket == NULL)
1963  return ERROR_INVALID_PARAMETER;
1964 
1965  //Retrieve local IP address
1966  if(localIpAddr != NULL)
1967  {
1968  *localIpAddr = socket->localIpAddr;
1969  }
1970 
1971  //Retrieve local port number
1972  if(localPort != NULL)
1973  {
1974  *localPort = socket->localPort;
1975  }
1976 
1977  //Successful processing
1978  return NO_ERROR;
1979 }
1980 
1981 
1982 /**
1983  * @brief Retrieve the address of the peer to which a socket is connected
1984  * @param[in] socket Handle that identifies a socket
1985  * @param[out] remoteIpAddr IP address of the remote host (optional)
1986  * @param[out] remotePort Remote port number (optional)
1987  * @return Error code
1988  **/
1989 
1991  uint16_t *remotePort)
1992 {
1993  //Make sure the socket handle is valid
1994  if(socket == NULL)
1995  return ERROR_INVALID_PARAMETER;
1996 
1997  //Retrieve local IP address
1998  if(remoteIpAddr != NULL)
1999  {
2000  *remoteIpAddr = socket->remoteIpAddr;
2001  }
2002 
2003  //Retrieve local port number
2004  if(remotePort != NULL)
2005  {
2006  *remotePort = socket->remotePort;
2007  }
2008 
2009  //Successful processing
2010  return NO_ERROR;
2011 }
2012 
2013 
2014 /**
2015  * @brief Disable reception, transmission, or both
2016  *
2017  * Note that socketShutdown() does not close the socket, and resources attached
2018  * to the socket will not be freed until socketClose() is invoked
2019  *
2020  * @param[in] socket Handle to a socket
2021  * @param[in] how Flag that describes what types of operation will no longer be allowed
2022  * @return Error code
2023  **/
2024 
2026 {
2027 #if (TCP_SUPPORT == ENABLED)
2028  error_t error;
2029 
2030  //Make sure the socket handle is valid
2031  if(socket == NULL)
2032  return ERROR_INVALID_PARAMETER;
2033 
2034  //Make sure the socket type is correct
2035  if(socket->type != SOCKET_TYPE_STREAM)
2036  return ERROR_INVALID_SOCKET;
2037 
2038  //Check flags
2039  if(how != SOCKET_SD_SEND && how != SOCKET_SD_RECEIVE &&
2040  how != SOCKET_SD_BOTH)
2041  {
2042  return ERROR_INVALID_PARAMETER;
2043  }
2044 
2045  //Get exclusive access
2047 
2048  //Graceful shutdown
2049  error = tcpShutdown(socket, how);
2050 
2051  //Release exclusive access
2053 
2054  //Return status code
2055  return error;
2056 #else
2057  return ERROR_NOT_IMPLEMENTED;
2058 #endif
2059 }
2060 
2061 
2062 /**
2063  * @brief Close an existing socket
2064  * @param[in] socket Handle identifying the socket to close
2065  **/
2066 
2068 {
2069  //Make sure the socket handle is valid
2070  if(socket == NULL)
2071  return;
2072 
2073  //Get exclusive access
2075 
2076 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
2077  //Connectionless or raw socket?
2078  if(socket->type == SOCKET_TYPE_DGRAM ||
2079  socket->type == SOCKET_TYPE_RAW_IP)
2080  {
2081  uint_t i;
2082  IpAddr groupAddr;
2083 
2084  //Loop through multicast groups
2085  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
2086  {
2087  //Get current group address
2088  groupAddr = socket->multicastGroups[i].addr;
2089 
2090  //Valid multicast address?
2091  if(groupAddr.length != 0)
2092  {
2093  //Delete entry
2094  socket->multicastGroups[i].addr = IP_ADDR_UNSPECIFIED;
2095 
2096  //Update the multicast reception state of the interface
2098  }
2099  }
2100  }
2101 #endif
2102 
2103 #if (TCP_SUPPORT == ENABLED)
2104  //Connection-oriented socket?
2105  if(socket->type == SOCKET_TYPE_STREAM)
2106  {
2107  //Abort the current TCP connection
2108  tcpAbort(socket);
2109  }
2110 #endif
2111 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
2112  //Connectionless socket or raw socket?
2113  if(socket->type == SOCKET_TYPE_DGRAM ||
2114  socket->type == SOCKET_TYPE_RAW_IP ||
2115  socket->type == SOCKET_TYPE_RAW_ETH)
2116  {
2117  //Point to the first item in the receive queue
2118  SocketQueueItem *queueItem = socket->receiveQueue;
2119 
2120  //Purge the receive queue
2121  while(queueItem != NULL)
2122  {
2123  //Keep track of the next item in the queue
2124  SocketQueueItem *nextQueueItem = queueItem->next;
2125  //Free previously allocated memory
2126  netBufferFree(queueItem->buffer);
2127  //Point to the next item
2128  queueItem = nextQueueItem;
2129  }
2130 
2131  //Mark the socket as closed
2132  socket->type = SOCKET_TYPE_UNUSED;
2133  }
2134 #endif
2135 
2136  //Release exclusive access
2138 }
2139 
2140 
2141 /**
2142  * @brief Wait for one of a set of sockets to become ready to perform I/O
2143  *
2144  * This function determines the status of one or more sockets, waiting if
2145  * necessary, to perform synchronous I/O
2146  *
2147  * @param[in,out] eventDesc Set of entries specifying the events the user is interested in
2148  * @param[in] size Number of entries in the descriptor set
2149  * @param[in] extEvent External event that can abort the wait if necessary (optional)
2150  * @param[in] timeout Maximum time to wait before returning
2151  * @return Error code
2152  **/
2153 
2154 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent,
2155  systime_t timeout)
2156 {
2157  error_t error;
2158  uint_t i;
2159  bool_t status;
2160  OsEvent *event;
2161  OsEvent eventObject;
2162 
2163  //Check parameters
2164  if(eventDesc == NULL || size == 0)
2165  return ERROR_INVALID_PARAMETER;
2166 
2167  //Try to use the supplied event object to receive notifications
2168  if(extEvent == NULL)
2169  {
2170  //Create an event object only if necessary
2171  if(!osCreateEvent(&eventObject))
2172  {
2173  //Report an error
2174  return ERROR_OUT_OF_RESOURCES;
2175  }
2176 
2177  //Reference to the newly created event
2178  event = &eventObject;
2179  }
2180  else
2181  {
2182  //Reference to the external event
2183  event = extEvent;
2184  }
2185 
2186  //Loop through descriptors
2187  for(i = 0; i < size; i++)
2188  {
2189  //Valid socket handle?
2190  if(eventDesc[i].socket != NULL)
2191  {
2192  //Clear event flags
2193  eventDesc[i].eventFlags = 0;
2194 
2195  //Subscribe to the requested events
2196  socketRegisterEvents(eventDesc[i].socket, event,
2197  eventDesc[i].eventMask);
2198  }
2199  }
2200 
2201  //Block the current task until an event occurs
2202  status = osWaitForEvent(event, timeout);
2203 
2204  //Any event?
2205  if(status)
2206  {
2207  //Clear flag
2208  status = FALSE;
2209 
2210  //Loop through descriptors
2211  for(i = 0; i < size; i++)
2212  {
2213  //Valid socket handle?
2214  if(eventDesc[i].socket != NULL)
2215  {
2216  //Retrieve event flags for the current socket
2217  eventDesc[i].eventFlags = socketGetEvents(eventDesc[i].socket);
2218  //Clear unnecessary flags
2219  eventDesc[i].eventFlags &= eventDesc[i].eventMask;
2220 
2221  //Check whether the socket is ready to perform I/O
2222  if(eventDesc[i].eventFlags != 0)
2223  {
2224  status = TRUE;
2225  }
2226  }
2227  }
2228 
2229  //Any socket event in the signaled state?
2230  if(status)
2231  {
2232  error = NO_ERROR;
2233  }
2234  else
2235  {
2236  error = ERROR_WAIT_CANCELED;
2237  }
2238  }
2239  else
2240  {
2241  //Report a timeout error
2242  error = ERROR_TIMEOUT;
2243  }
2244 
2245  //Loop through descriptors
2246  for(i = 0; i < size; i++)
2247  {
2248  //Valid socket handle?
2249  if(eventDesc[i].socket != NULL)
2250  {
2251  //Unsubscribe previously registered events
2252  socketUnregisterEvents(eventDesc[i].socket);
2253  }
2254  }
2255 
2256  //Reset event object
2257  osResetEvent(event);
2258 
2259  //Release previously allocated resources
2260  if(extEvent == NULL)
2261  {
2262  osDeleteEvent(&eventObject);
2263  }
2264 
2265  //Return status code
2266  return error;
2267 }
2268 
2269 
2270 /**
2271  * @brief Resolve a host name into an IP address
2272  * @param[in] interface Underlying network interface (optional parameter)
2273  * @param[in] name Name of the host to be resolved
2274  * @param[out] ipAddr IP address corresponding to the specified host name
2275  * @param[in] flags Set of flags that influences the behavior of this function
2276  * @return Error code
2277  **/
2278 
2281 {
2282  error_t error;
2283  HostType type;
2285 
2286  //Default address type depends on TCP/IP stack configuration
2287 #if (IPV4_SUPPORT == ENABLED)
2288  type = HOST_TYPE_IPV4;
2289 #elif (IPV6_SUPPORT == ENABLED)
2290  type = HOST_TYPE_IPV6;
2291 #else
2292  type = HOST_TYPE_ANY;
2293 #endif
2294 
2295  //Default name resolution protocol depends on TCP/IP stack configuration
2296 #if (DNS_CLIENT_SUPPORT == ENABLED)
2298 #elif (MDNS_CLIENT_SUPPORT == ENABLED)
2300 #elif (NBNS_CLIENT_SUPPORT == ENABLED)
2302 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2304 #else
2306 #endif
2307 
2308  //Check parameters
2309  if(name == NULL || ipAddr == NULL)
2310  return ERROR_INVALID_PARAMETER;
2311 
2312  //Use default network interface?
2313  if(interface == NULL)
2314  {
2315  interface = netGetDefaultInterface();
2316  }
2317 
2318  //The specified name can be either an IP or a host name
2319  error = ipStringToAddr(name, ipAddr);
2320 
2321  //Perform name resolution if necessary
2322  if(error)
2323  {
2324  //The user may provide a hint to choose between IPv4 and IPv6
2325  if((flags & HOST_TYPE_IPV4) != 0)
2326  {
2327  type = HOST_TYPE_IPV4;
2328  }
2329  else if((flags & HOST_TYPE_IPV6) != 0)
2330  {
2331  type = HOST_TYPE_IPV6;
2332  }
2333  else
2334  {
2335  //Just for sanity
2336  }
2337 
2338  //The user may provide a hint to to select the desired protocol to be used
2339  if((flags & HOST_NAME_RESOLVER_DNS) != 0)
2340  {
2341  //Use DNS to resolve the specified host name
2343  }
2344  else if((flags & HOST_NAME_RESOLVER_MDNS) != 0)
2345  {
2346  //Use mDNS to resolve the specified host name
2348  }
2349  else if((flags & HOST_NAME_RESOLVER_NBNS) != 0)
2350  {
2351  //Use NBNS to resolve the specified host name
2353  }
2354  else if((flags & HOST_NAME_RESOLVER_LLMNR) != 0)
2355  {
2356  //Use LLMNR to resolve the specified host name
2358  }
2359  else
2360  {
2361  //Retrieve the length of the host name to be resolved
2362  size_t n = osStrlen(name);
2363 
2364  //Select the most suitable protocol
2365  if(n >= 6 && osStrcasecmp(name + n - 6, ".local") == 0)
2366  {
2367 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2368  //Use mDNS to resolve the specified host name
2370 #endif
2371  }
2372  else if(n <= 15 && osStrchr(name, '.') == NULL &&
2373  type == HOST_TYPE_IPV4)
2374  {
2375 #if (NBNS_CLIENT_SUPPORT == ENABLED)
2376  //Use NetBIOS Name Service to resolve the specified host name
2378 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2379  //Use LLMNR to resolve the specified host name
2381 #endif
2382  }
2383  else if(osStrchr(name, '.') == NULL)
2384  {
2385 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2386  //Use LLMNR to resolve the specified host name
2388 #endif
2389  }
2390  }
2391 
2392 #if (DNS_CLIENT_SUPPORT == ENABLED)
2393  //Use DNS protocol?
2395  {
2396  //Perform host name resolution
2397  error = dnsResolve(interface, name, type, ipAddr);
2398  }
2399  else
2400 #endif
2401 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2402  //Use mDNS protocol?
2404  {
2405  //Perform host name resolution
2406  error = mdnsClientResolve(interface, name, type, ipAddr);
2407  }
2408  else
2409 #endif
2410 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
2411  //Use NetBIOS Name Service protocol?
2413  {
2414  //Perform host name resolution
2415  error = nbnsResolve(interface, name, ipAddr);
2416  }
2417  else
2418 #endif
2419 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2420  //Use LLMNR protocol?
2422  {
2423  //Perform host name resolution
2424  error = llmnrResolve(interface, name, type, ipAddr);
2425  }
2426  else
2427 #endif
2428  //Invalid protocol?
2429  {
2430  //Just for sanity
2431  (void) protocol;
2432  //Report an error
2433  error = ERROR_INVALID_PARAMETER;
2434  }
2435  }
2436 
2437  //Return status code
2438  return error;
2439 }
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:675
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:54
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
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:2067
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:223
@ 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:1990
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:1639
#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:1697
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:1037
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:1719
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1899
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:2279
@ 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:2025
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:2154
#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:1958
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:974
error_t rawSocketReceiveEthPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an Ethernet packet from a raw socket.
Definition: raw_socket.c:930
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:220
#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:1741
error_t tcpShutdown(Socket *socket, uint_t how)
Shutdown gracefully reception, transmission, or both.
Definition: tcp.c:836
uint32_t ttl
Definition: dns_common.h:221
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:824
#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