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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
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  //Check parameter value
1209  if(size < 1 || size > TCP_MAX_TX_BUFFER_SIZE)
1210  return ERROR_INVALID_PARAMETER;
1211 
1212  //This function shall be used with connection-oriented sockets
1213  if(socket->type != SOCKET_TYPE_STREAM)
1214  return ERROR_INVALID_SOCKET;
1215 
1216  //The buffer size cannot be changed when the connection is established
1218  return ERROR_INVALID_SOCKET;
1219 
1220  //Use the specified buffer size
1221  socket->txBufferSize = size;
1222  //No error to report
1223  return NO_ERROR;
1224 #else
1225  return ERROR_NOT_IMPLEMENTED;
1226 #endif
1227 }
1228 
1229 
1230 /**
1231  * @brief Specify the size of the TCP receive buffer
1232  * @param[in] socket Handle to a socket
1233  * @param[in] size Desired buffer size, in bytes
1234  * @return Error code
1235  **/
1236 
1238 {
1239 #if (TCP_SUPPORT == ENABLED)
1240  //Make sure the socket handle is valid
1241  if(socket == NULL)
1242  return ERROR_INVALID_PARAMETER;
1243 
1244  //Check parameter value
1245  if(size < 1 || size > TCP_MAX_RX_BUFFER_SIZE)
1246  return ERROR_INVALID_PARAMETER;
1247 
1248  //This function shall be used with connection-oriented sockets
1249  if(socket->type != SOCKET_TYPE_STREAM)
1250  return ERROR_INVALID_SOCKET;
1251 
1252  //The buffer size cannot be changed when the connection is established
1254  return ERROR_INVALID_SOCKET;
1255 
1256  //Use the specified buffer size
1257  socket->rxBufferSize = size;
1258  //No error to report
1259  return NO_ERROR;
1260 #else
1261  return ERROR_NOT_IMPLEMENTED;
1262 #endif
1263 }
1264 
1265 
1266 /**
1267  * @brief Bind a socket to a particular network interface
1268  * @param[in] socket Handle to a socket
1269  * @param[in] interface Network interface to be used
1270  * @return Error code
1271  **/
1272 
1274 {
1275  //Make sure the socket handle is valid
1276  if(socket == NULL)
1277  return ERROR_INVALID_PARAMETER;
1278 
1279  //Explicitly associate the socket with the specified interface
1280  socket->interface = interface;
1281 
1282  //No error to report
1283  return NO_ERROR;
1284 }
1285 
1286 
1287 /**
1288  * @brief Retrieve the underlying interface
1289  * @param[in] socket Handle to a socket
1290  * @return Pointer to the underlying network interface
1291  **/
1292 
1294 {
1295  NetInterface *interface = NULL;
1296 
1297  //Make sure the socket handle is valid
1298  if(socket != NULL)
1299  {
1300  interface = socket->interface;
1301  }
1302 
1303  //Return a pointer to the underlying network interface
1304  return interface;
1305 }
1306 
1307 
1308 /**
1309  * @brief Associate a local address with a socket
1310  * @param[in] socket Handle to a socket
1311  * @param[in] localIpAddr Local address to assign to the bound socket
1312  * @param[in] localPort Local port number to assign to the bound socket
1313  * @return Error code
1314  **/
1315 
1316 error_t socketBind(Socket *socket, const IpAddr *localIpAddr,
1317  uint16_t localPort)
1318 {
1319  //Check input parameters
1320  if(socket == NULL || localIpAddr == NULL)
1321  return ERROR_INVALID_PARAMETER;
1322 
1323  //Make sure the socket type is correct
1324  if(socket->type != SOCKET_TYPE_STREAM &&
1325  socket->type != SOCKET_TYPE_DGRAM &&
1326  socket->type != SOCKET_TYPE_RAW_IP)
1327  {
1328  return ERROR_INVALID_SOCKET;
1329  }
1330 
1331  //Associate the specified IP address and port number
1332  socket->localIpAddr = *localIpAddr;
1333  socket->localPort = localPort;
1334 
1335  //No error to report
1336  return NO_ERROR;
1337 }
1338 
1339 
1340 /**
1341  * @brief Establish a connection to a specified socket
1342  * @param[in] socket Handle to an unconnected socket
1343  * @param[in] remoteIpAddr IP address of the remote host
1344  * @param[in] remotePort Remote port number that will be used to establish
1345  * the connection
1346  * @return Error code
1347  **/
1348 
1349 error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr,
1350  uint16_t remotePort)
1351 {
1352  error_t error;
1353 
1354  //Check input parameters
1355  if(socket == NULL || remoteIpAddr == NULL)
1356  return ERROR_INVALID_PARAMETER;
1357 
1358 #if (TCP_SUPPORT == ENABLED)
1359  //Connection-oriented socket?
1360  if(socket->type == SOCKET_TYPE_STREAM)
1361  {
1362  //Get exclusive access
1364 
1365  //Establish TCP connection
1366  error = tcpConnect(socket, remoteIpAddr, remotePort);
1367 
1368  //Release exclusive access
1370  }
1371  else
1372 #endif
1373  //Connectionless socket?
1374  if(socket->type == SOCKET_TYPE_DGRAM)
1375  {
1376  //Save port number and IP address of the remote host
1377  socket->remoteIpAddr = *remoteIpAddr;
1378  socket->remotePort = remotePort;
1379  //No error to report
1380  error = NO_ERROR;
1381  }
1382  //Raw socket?
1383  else if(socket->type == SOCKET_TYPE_RAW_IP)
1384  {
1385  //Save the IP address of the remote host
1386  socket->remoteIpAddr = *remoteIpAddr;
1387  //No error to report
1388  error = NO_ERROR;
1389  }
1390  //Invalid socket type?
1391  else
1392  {
1393  //Report an error
1394  error = ERROR_INVALID_SOCKET;
1395  }
1396 
1397  //Return status code
1398  return error;
1399 }
1400 
1401 
1402 /**
1403  * @brief Place a socket in the listening state
1404  *
1405  * Place a socket in a state in which it is listening for an incoming connection
1406  *
1407  * @param[in] socket Socket to place in the listening state
1408  * @param[in] backlog backlog The maximum length of the pending connection queue.
1409  * If this parameter is zero, then the default backlog value is used instead
1410  * @return Error code
1411  **/
1412 
1414 {
1415 #if (TCP_SUPPORT == ENABLED)
1416  error_t error;
1417 
1418  //Make sure the socket handle is valid
1419  if(socket == NULL)
1420  return ERROR_INVALID_PARAMETER;
1421 
1422  //This function shall be used with connection-oriented sockets
1423  if(socket->type != SOCKET_TYPE_STREAM)
1424  return ERROR_INVALID_SOCKET;
1425 
1426  //Get exclusive access
1428 
1429  //Start listening for an incoming connection
1430  error = tcpListen(socket, backlog);
1431 
1432  //Release exclusive access
1434 
1435  //Return status code
1436  return error;
1437 #else
1438  return ERROR_NOT_IMPLEMENTED;
1439 #endif
1440 }
1441 
1442 
1443 /**
1444  * @brief Permit an incoming connection attempt on a socket
1445  * @param[in] socket Handle to a socket previously placed in a listening state
1446  * @param[out] clientIpAddr IP address of the client
1447  * @param[out] clientPort Port number used by the client
1448  * @return Handle to the socket in which the actual connection is made
1449  **/
1450 
1452  uint16_t *clientPort)
1453 {
1454 #if (TCP_SUPPORT == ENABLED)
1455  Socket *newSocket;
1456 
1457  //Make sure the socket handle is valid
1458  if(socket == NULL)
1459  return NULL;
1460 
1461  //This function shall be used with connection-oriented sockets
1462  if(socket->type != SOCKET_TYPE_STREAM)
1463  return NULL;
1464 
1465  //Accept an incoming connection attempt
1466  newSocket = tcpAccept(socket, clientIpAddr, clientPort);
1467 
1468  //Return a handle to the newly created socket
1469  return newSocket;
1470 #else
1471  return NULL;
1472 #endif
1473 }
1474 
1475 
1476 /**
1477  * @brief Send data to a connected socket
1478  * @param[in] socket Handle that identifies a connected socket
1479  * @param[in] data Pointer to a buffer containing the data to be transmitted
1480  * @param[in] length Number of data bytes to send
1481  * @param[out] written Actual number of bytes written (optional parameter)
1482  * @param[in] flags Set of flags that influences the behavior of this function
1483  * @return Error code
1484  **/
1485 
1486 error_t socketSend(Socket *socket, const void *data, size_t length,
1487  size_t *written, uint_t flags)
1488 {
1489  //Use default remote IP address for connectionless or raw sockets
1490  return socketSendTo(socket, &socket->remoteIpAddr, socket->remotePort,
1491  data, length, written, flags);
1492 }
1493 
1494 
1495 /**
1496  * @brief Send a datagram to a specific destination
1497  * @param[in] socket Handle that identifies a socket
1498  * @param[in] destIpAddr IP address of the target host
1499  * @param[in] destPort Target port number
1500  * @param[in] data Pointer to a buffer containing the data to be transmitted
1501  * @param[in] length Number of data bytes to send
1502  * @param[out] written Actual number of bytes written (optional parameter)
1503  * @param[in] flags Set of flags that influences the behavior of this function
1504  * @return Error code
1505  **/
1506 
1508  const void *data, size_t length, size_t *written, uint_t flags)
1509 {
1510  error_t error;
1511 
1512  //No data has been transmitted yet
1513  if(written != NULL)
1514  *written = 0;
1515 
1516  //Make sure the socket handle is valid
1517  if(socket == NULL)
1518  return ERROR_INVALID_PARAMETER;
1519 
1520  //Get exclusive access
1522 
1523 #if (TCP_SUPPORT == ENABLED)
1524  //Connection-oriented socket?
1525  if(socket->type == SOCKET_TYPE_STREAM)
1526  {
1527  //For connection-oriented sockets, target address is ignored
1528  error = tcpSend(socket, data, length, written, flags);
1529  }
1530  else
1531 #endif
1532  {
1534 
1535  //Initialize structure
1537 
1538  //Set destination IP address
1539  if(destIpAddr != NULL)
1540  {
1541  message.destIpAddr = *destIpAddr;
1542  }
1543 
1544  //Set destination port
1545  message.destPort = destPort;
1546 
1547 #if (UDP_SUPPORT == ENABLED)
1548  //Connectionless socket?
1549  if(socket->type == SOCKET_TYPE_DGRAM)
1550  {
1551  //Set data payload
1552  message.data = (uint8_t *) data;
1553  message.length = length;
1554 
1555  //Send UDP datagram
1556  error = udpSendDatagram(socket, &message, flags);
1557  }
1558  else
1559 #endif
1560 #if (RAW_SOCKET_SUPPORT == ENABLED)
1561  //Raw socket?
1562  if(socket->type == SOCKET_TYPE_RAW_IP)
1563  {
1564  //Set data payload
1565  message.data = (uint8_t *) data;
1566  message.length = length;
1567 
1568  //Send a raw IP packet
1570  }
1571  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1572  {
1573  //Sanity check
1574  if(length >= sizeof(EthHeader))
1575  {
1576  EthHeader *header;
1577 
1578  //Point to the Ethernet header
1579  header = (EthHeader *) data;
1580 
1581  //Set source and destination MAC addresses
1582  message.srcMacAddr = header->srcAddr;
1583  message.destMacAddr = header->destAddr;
1584 
1585  //Set the value of the EtherType field
1586  message.ethType = ntohs(header->type);
1587 
1588  //Set data payload
1589  message.data = (uint8_t *) data + sizeof(EthHeader);
1590  message.length = length - sizeof(EthHeader);
1591 
1592  //Send a raw Ethernet packet
1594  }
1595  else
1596  {
1597  //Report an error
1598  error = ERROR_INVALID_LENGTH;
1599  }
1600  }
1601  else
1602 #endif
1603  //Invalid socket type?
1604  {
1605  //Report an error
1606  error = ERROR_INVALID_SOCKET;
1607  }
1608 
1609  //Check status code
1610  if(!error)
1611  {
1612  //Total number of data bytes successfully transmitted
1613  if(written != NULL)
1614  *written = message.length;
1615  }
1616  }
1617 
1618  //Release exclusive access
1620 
1621  //Return status code
1622  return error;
1623 }
1624 
1625 
1626 /**
1627  * @brief Send a message to a connectionless socket
1628  * @param[in] socket Handle that identifies a socket
1629  * @param[in] message Pointer to the structure describing the message
1630  * @param[in] flags Set of flags that influences the behavior of this function
1631  * @return Error code
1632  **/
1633 
1635 {
1636  error_t error;
1637 
1638  //Make sure the socket handle is valid
1639  if(socket == NULL)
1640  return ERROR_INVALID_PARAMETER;
1641 
1642  //Get exclusive access
1644 
1645 #if (UDP_SUPPORT == ENABLED)
1646  //Connectionless socket?
1647  if(socket->type == SOCKET_TYPE_DGRAM)
1648  {
1649  //Send UDP datagram
1650  error = udpSendDatagram(socket, message, flags);
1651  }
1652  else
1653 #endif
1654 #if (RAW_SOCKET_SUPPORT == ENABLED)
1655  //Raw socket?
1656  if(socket->type == SOCKET_TYPE_RAW_IP)
1657  {
1658  //Send a raw IP packet
1660  }
1661  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1662  {
1663  //Send a raw Ethernet packet
1665  }
1666  else
1667 #endif
1668  //Invalid socket type?
1669  {
1670  //Report an error
1671  error = ERROR_INVALID_SOCKET;
1672  }
1673 
1674  //Release exclusive access
1676 
1677  //Return status code
1678  return error;
1679 }
1680 
1681 
1682 /**
1683  * @brief Receive data from a connected socket
1684  * @param[in] socket Handle that identifies a connected socket
1685  * @param[out] data Buffer where to store the incoming data
1686  * @param[in] size Maximum number of bytes that can be received
1687  * @param[out] received Number of bytes that have been received
1688  * @param[in] flags Set of flags that influences the behavior of this function
1689  * @return Error code
1690  **/
1691 
1693  size_t size, size_t *received, uint_t flags)
1694 {
1695  //For connection-oriented sockets, source and destination addresses are
1696  //no use
1697  return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received,
1698  flags);
1699 }
1700 
1701 
1702 /**
1703  * @brief Receive a datagram from a connectionless socket
1704  * @param[in] socket Handle that identifies a socket
1705  * @param[out] srcIpAddr Source IP address (optional)
1706  * @param[out] srcPort Source port number (optional)
1707  * @param[out] data Buffer where to store the incoming data
1708  * @param[in] size Maximum number of bytes that can be received
1709  * @param[out] received Number of bytes that have been received
1710  * @param[in] flags Set of flags that influences the behavior of this function
1711  * @return Error code
1712  **/
1713 
1715  void *data, size_t size, size_t *received, uint_t flags)
1716 {
1717  //Destination address is no use
1718  return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size,
1719  received, flags);
1720 }
1721 
1722 
1723 /**
1724  * @brief Receive a datagram
1725  * @param[in] socket Handle that identifies a socket
1726  * @param[out] srcIpAddr Source IP address (optional)
1727  * @param[out] srcPort Source port number (optional)
1728  * @param[out] destIpAddr Destination IP address (optional)
1729  * @param[out] data Buffer where to store the incoming data
1730  * @param[in] size Maximum number of bytes that can be received
1731  * @param[out] received Number of bytes that have been received
1732  * @param[in] flags Set of flags that influences the behavior of this function
1733  * @return Error code
1734  **/
1735 
1737  IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
1738 {
1739  error_t error;
1740 
1741  //No data has been received yet
1742  if(received != NULL)
1743  *received = 0;
1744 
1745  //Make sure the socket handle is valid
1746  if(socket == NULL)
1747  return ERROR_INVALID_PARAMETER;
1748 
1749  //Get exclusive access
1751 
1752 #if (TCP_SUPPORT == ENABLED)
1753  //Connection-oriented socket?
1754  if(socket->type == SOCKET_TYPE_STREAM)
1755  {
1756  //Receive data
1757  error = tcpReceive(socket, data, size, received, flags);
1758 
1759  //Save the source IP address
1760  if(srcIpAddr != NULL)
1761  {
1762  *srcIpAddr = socket->remoteIpAddr;
1763  }
1764 
1765  //Save the source port number
1766  if(srcPort != NULL)
1767  {
1768  *srcPort = socket->remotePort;
1769  }
1770 
1771  //Save the destination IP address
1772  if(destIpAddr != NULL)
1773  {
1774  *destIpAddr = socket->localIpAddr;
1775  }
1776  }
1777  else
1778 #endif
1779  {
1781 
1782  //Initialize structure
1784 
1785 #if (UDP_SUPPORT == ENABLED)
1786  //Connectionless socket?
1787  if(socket->type == SOCKET_TYPE_DGRAM)
1788  {
1789  //Set data buffer
1790  message.data = data;
1791  message.size = size;
1792 
1793  //Receive UDP datagram
1794  error = udpReceiveDatagram(socket, &message, flags);
1795  }
1796  else
1797 #endif
1798 #if (RAW_SOCKET_SUPPORT == ENABLED)
1799  //Raw socket?
1800  if(socket->type == SOCKET_TYPE_RAW_IP)
1801  {
1802  //Set data buffer
1803  message.data = data;
1804  message.size = size;
1805 
1806  //Receive a raw IP packet
1808  }
1809  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1810  {
1811  //Sanity check
1812  if(size >= sizeof(EthHeader))
1813  {
1814  //Set data buffer
1815  message.data = (uint8_t *) data + sizeof(EthHeader);
1816  message.size = size - sizeof(EthHeader);
1817 
1818  //Receive a raw Ethernet packet
1820 
1821  //Check status code
1822  if(!error)
1823  {
1824  EthHeader *header;
1825 
1826  //Point to the Ethernet header
1827  header = (EthHeader *) data;
1828 
1829  //Reconstruct Ethernet header
1830  header->destAddr = message.destMacAddr;
1831  header->srcAddr = message.srcMacAddr;
1832  header->type = htons(message.ethType);
1833 
1834  //Ajust the length of the frame
1835  message.length += sizeof(EthHeader);
1836  }
1837  }
1838  else
1839  {
1840  //Report an error
1841  error = ERROR_BUFFER_OVERFLOW;
1842  }
1843  }
1844  else
1845 #endif
1846  //Invalid socket type?
1847  {
1848  //Report an error
1849  error = ERROR_INVALID_SOCKET;
1850  }
1851 
1852  //Check status code
1853  if(!error)
1854  {
1855  //Save the source IP address
1856  if(srcIpAddr != NULL)
1857  {
1858  *srcIpAddr = message.srcIpAddr;
1859  }
1860 
1861  //Save the source port number
1862  if(srcPort != NULL)
1863  {
1864  *srcPort = message.srcPort;
1865  }
1866 
1867  //Save the destination IP address
1868  if(destIpAddr != NULL)
1869  {
1870  *destIpAddr = message.destIpAddr;
1871  }
1872 
1873  //Total number of data that have been received
1874  *received = message.length;
1875  }
1876  }
1877 
1878  //Release exclusive access
1880 
1881  //Return status code
1882  return error;
1883 }
1884 
1885 
1886 /**
1887  * @brief Receive a message from a connectionless socket
1888  * @param[in] socket Handle that identifies a socket
1889  * @param[in,out] message Pointer to the structure describing the message
1890  * @param[in] flags Set of flags that influences the behavior of this function
1891  * @return Error code
1892  **/
1893 
1895 {
1896  error_t error;
1897 
1898  //No data has been received yet
1899  message->length = 0;
1900 
1901  //Make sure the socket handle is valid
1902  if(socket == NULL)
1903  return ERROR_INVALID_PARAMETER;
1904 
1905  //Get exclusive access
1907 
1908 #if (UDP_SUPPORT == ENABLED)
1909  //Connectionless socket?
1910  if(socket->type == SOCKET_TYPE_DGRAM)
1911  {
1912  //Receive UDP datagram
1914  }
1915  else
1916 #endif
1917 #if (RAW_SOCKET_SUPPORT == ENABLED)
1918  //Raw socket?
1919  if(socket->type == SOCKET_TYPE_RAW_IP)
1920  {
1921  //Receive a raw IP packet
1923  }
1924  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1925  {
1926  //Receive a raw Ethernet packet
1928  }
1929  else
1930 #endif
1931  //Invalid socket type?
1932  {
1933  //Report an error
1934  error = ERROR_INVALID_SOCKET;
1935  }
1936 
1937  //Release exclusive access
1939 
1940  //Return status code
1941  return error;
1942 }
1943 
1944 
1945 /**
1946  * @brief Retrieve the local address for a given socket
1947  * @param[in] socket Handle that identifies a socket
1948  * @param[out] localIpAddr Local IP address (optional)
1949  * @param[out] localPort Local port number (optional)
1950  * @return Error code
1951  **/
1952 
1954  uint16_t *localPort)
1955 {
1956  //Make sure the socket handle is valid
1957  if(socket == NULL)
1958  return ERROR_INVALID_PARAMETER;
1959 
1960  //Retrieve local IP address
1961  if(localIpAddr != NULL)
1962  {
1963  *localIpAddr = socket->localIpAddr;
1964  }
1965 
1966  //Retrieve local port number
1967  if(localPort != NULL)
1968  {
1969  *localPort = socket->localPort;
1970  }
1971 
1972  //Successful processing
1973  return NO_ERROR;
1974 }
1975 
1976 
1977 /**
1978  * @brief Retrieve the address of the peer to which a socket is connected
1979  * @param[in] socket Handle that identifies a socket
1980  * @param[out] remoteIpAddr IP address of the remote host (optional)
1981  * @param[out] remotePort Remote port number (optional)
1982  * @return Error code
1983  **/
1984 
1986  uint16_t *remotePort)
1987 {
1988  //Make sure the socket handle is valid
1989  if(socket == NULL)
1990  return ERROR_INVALID_PARAMETER;
1991 
1992  //Retrieve local IP address
1993  if(remoteIpAddr != NULL)
1994  {
1995  *remoteIpAddr = socket->remoteIpAddr;
1996  }
1997 
1998  //Retrieve local port number
1999  if(remotePort != NULL)
2000  {
2001  *remotePort = socket->remotePort;
2002  }
2003 
2004  //Successful processing
2005  return NO_ERROR;
2006 }
2007 
2008 
2009 /**
2010  * @brief Disable reception, transmission, or both
2011  *
2012  * Note that socketShutdown() does not close the socket, and resources attached
2013  * to the socket will not be freed until socketClose() is invoked
2014  *
2015  * @param[in] socket Handle to a socket
2016  * @param[in] how Flag that describes what types of operation will no longer be allowed
2017  * @return Error code
2018  **/
2019 
2021 {
2022 #if (TCP_SUPPORT == ENABLED)
2023  error_t error;
2024 
2025  //Make sure the socket handle is valid
2026  if(socket == NULL)
2027  return ERROR_INVALID_PARAMETER;
2028 
2029  //Make sure the socket type is correct
2030  if(socket->type != SOCKET_TYPE_STREAM)
2031  return ERROR_INVALID_SOCKET;
2032 
2033  //Check flags
2034  if(how != SOCKET_SD_SEND && how != SOCKET_SD_RECEIVE &&
2035  how != SOCKET_SD_BOTH)
2036  {
2037  return ERROR_INVALID_PARAMETER;
2038  }
2039 
2040  //Get exclusive access
2042 
2043  //Graceful shutdown
2044  error = tcpShutdown(socket, how);
2045 
2046  //Release exclusive access
2048 
2049  //Return status code
2050  return error;
2051 #else
2052  return ERROR_NOT_IMPLEMENTED;
2053 #endif
2054 }
2055 
2056 
2057 /**
2058  * @brief Close an existing socket
2059  * @param[in] socket Handle identifying the socket to close
2060  **/
2061 
2063 {
2064  //Make sure the socket handle is valid
2065  if(socket == NULL)
2066  return;
2067 
2068  //Get exclusive access
2070 
2071 #if (SOCKET_MAX_MULTICAST_GROUPS > 0)
2072  //Connectionless or raw socket?
2073  if(socket->type == SOCKET_TYPE_DGRAM ||
2074  socket->type == SOCKET_TYPE_RAW_IP)
2075  {
2076  uint_t i;
2077  IpAddr groupAddr;
2078 
2079  //Loop through multicast groups
2080  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
2081  {
2082  //Get current group address
2083  groupAddr = socket->multicastGroups[i].addr;
2084 
2085  //Valid multicast address?
2086  if(groupAddr.length != 0)
2087  {
2088  //Delete entry
2089  socket->multicastGroups[i].addr = IP_ADDR_UNSPECIFIED;
2090 
2091  //Update the multicast reception state of the interface
2093  }
2094  }
2095  }
2096 #endif
2097 
2098 #if (TCP_SUPPORT == ENABLED)
2099  //Connection-oriented socket?
2100  if(socket->type == SOCKET_TYPE_STREAM)
2101  {
2102  //Abort the current TCP connection
2103  tcpAbort(socket);
2104  }
2105 #endif
2106 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
2107  //Connectionless socket or raw socket?
2108  if(socket->type == SOCKET_TYPE_DGRAM ||
2109  socket->type == SOCKET_TYPE_RAW_IP ||
2110  socket->type == SOCKET_TYPE_RAW_ETH)
2111  {
2112  //Point to the first item in the receive queue
2113  SocketQueueItem *queueItem = socket->receiveQueue;
2114 
2115  //Purge the receive queue
2116  while(queueItem != NULL)
2117  {
2118  //Keep track of the next item in the queue
2119  SocketQueueItem *nextQueueItem = queueItem->next;
2120  //Free previously allocated memory
2121  netBufferFree(queueItem->buffer);
2122  //Point to the next item
2123  queueItem = nextQueueItem;
2124  }
2125 
2126  //Mark the socket as closed
2127  socket->type = SOCKET_TYPE_UNUSED;
2128  }
2129 #endif
2130 
2131  //Release exclusive access
2133 }
2134 
2135 
2136 /**
2137  * @brief Wait for one of a set of sockets to become ready to perform I/O
2138  *
2139  * This function determines the status of one or more sockets, waiting if
2140  * necessary, to perform synchronous I/O
2141  *
2142  * @param[in,out] eventDesc Set of entries specifying the events the user is interested in
2143  * @param[in] size Number of entries in the descriptor set
2144  * @param[in] extEvent External event that can abort the wait if necessary (optional)
2145  * @param[in] timeout Maximum time to wait before returning
2146  * @return Error code
2147  **/
2148 
2149 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent,
2150  systime_t timeout)
2151 {
2152  error_t error;
2153  uint_t i;
2154  bool_t status;
2155  OsEvent *event;
2156  OsEvent eventObject;
2157 
2158  //Check parameters
2159  if(eventDesc == NULL || size == 0)
2160  return ERROR_INVALID_PARAMETER;
2161 
2162  //Try to use the supplied event object to receive notifications
2163  if(extEvent == NULL)
2164  {
2165  //Create an event object only if necessary
2166  if(!osCreateEvent(&eventObject))
2167  {
2168  //Report an error
2169  return ERROR_OUT_OF_RESOURCES;
2170  }
2171 
2172  //Reference to the newly created event
2173  event = &eventObject;
2174  }
2175  else
2176  {
2177  //Reference to the external event
2178  event = extEvent;
2179  }
2180 
2181  //Loop through descriptors
2182  for(i = 0; i < size; i++)
2183  {
2184  //Valid socket handle?
2185  if(eventDesc[i].socket != NULL)
2186  {
2187  //Clear event flags
2188  eventDesc[i].eventFlags = 0;
2189 
2190  //Subscribe to the requested events
2191  socketRegisterEvents(eventDesc[i].socket, event,
2192  eventDesc[i].eventMask);
2193  }
2194  }
2195 
2196  //Block the current task until an event occurs
2197  status = osWaitForEvent(event, timeout);
2198 
2199  //Any event?
2200  if(status)
2201  {
2202  //Clear flag
2203  status = FALSE;
2204 
2205  //Loop through descriptors
2206  for(i = 0; i < size; i++)
2207  {
2208  //Valid socket handle?
2209  if(eventDesc[i].socket != NULL)
2210  {
2211  //Retrieve event flags for the current socket
2212  eventDesc[i].eventFlags = socketGetEvents(eventDesc[i].socket);
2213  //Clear unnecessary flags
2214  eventDesc[i].eventFlags &= eventDesc[i].eventMask;
2215 
2216  //Check whether the socket is ready to perform I/O
2217  if(eventDesc[i].eventFlags != 0)
2218  {
2219  status = TRUE;
2220  }
2221  }
2222  }
2223 
2224  //Any socket event in the signaled state?
2225  if(status)
2226  {
2227  error = NO_ERROR;
2228  }
2229  else
2230  {
2231  error = ERROR_WAIT_CANCELED;
2232  }
2233  }
2234  else
2235  {
2236  //Report a timeout error
2237  error = ERROR_TIMEOUT;
2238  }
2239 
2240  //Loop through descriptors
2241  for(i = 0; i < size; i++)
2242  {
2243  //Valid socket handle?
2244  if(eventDesc[i].socket != NULL)
2245  {
2246  //Unsubscribe previously registered events
2247  socketUnregisterEvents(eventDesc[i].socket);
2248  }
2249  }
2250 
2251  //Reset event object
2252  osResetEvent(event);
2253 
2254  //Release previously allocated resources
2255  if(extEvent == NULL)
2256  {
2257  osDeleteEvent(&eventObject);
2258  }
2259 
2260  //Return status code
2261  return error;
2262 }
2263 
2264 
2265 /**
2266  * @brief Resolve a host name into an IP address
2267  * @param[in] interface Underlying network interface (optional parameter)
2268  * @param[in] name Name of the host to be resolved
2269  * @param[out] ipAddr IP address corresponding to the specified host name
2270  * @param[in] flags Set of flags that influences the behavior of this function
2271  * @return Error code
2272  **/
2273 
2276 {
2277  error_t error;
2278  HostType type;
2280 
2281  //Default address type depends on TCP/IP stack configuration
2282 #if (IPV4_SUPPORT == ENABLED)
2283  type = HOST_TYPE_IPV4;
2284 #elif (IPV6_SUPPORT == ENABLED)
2285  type = HOST_TYPE_IPV6;
2286 #else
2287  type = HOST_TYPE_ANY;
2288 #endif
2289 
2290  //Default name resolution protocol depends on TCP/IP stack configuration
2291 #if (DNS_CLIENT_SUPPORT == ENABLED)
2293 #elif (MDNS_CLIENT_SUPPORT == ENABLED)
2295 #elif (NBNS_CLIENT_SUPPORT == ENABLED)
2297 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2299 #else
2301 #endif
2302 
2303  //Check parameters
2304  if(name == NULL || ipAddr == NULL)
2305  return ERROR_INVALID_PARAMETER;
2306 
2307  //Use default network interface?
2308  if(interface == NULL)
2309  {
2310  interface = netGetDefaultInterface();
2311  }
2312 
2313  //The specified name can be either an IP or a host name
2314  error = ipStringToAddr(name, ipAddr);
2315 
2316  //Perform name resolution if necessary
2317  if(error)
2318  {
2319  //The user may provide a hint to choose between IPv4 and IPv6
2320  if((flags & HOST_TYPE_IPV4) != 0)
2321  {
2322  type = HOST_TYPE_IPV4;
2323  }
2324  else if((flags & HOST_TYPE_IPV6) != 0)
2325  {
2326  type = HOST_TYPE_IPV6;
2327  }
2328  else
2329  {
2330  //Just for sanity
2331  }
2332 
2333  //The user may provide a hint to to select the desired protocol to be used
2334  if((flags & HOST_NAME_RESOLVER_DNS) != 0)
2335  {
2336  //Use DNS to resolve the specified host name
2338  }
2339  else if((flags & HOST_NAME_RESOLVER_MDNS) != 0)
2340  {
2341  //Use mDNS to resolve the specified host name
2343  }
2344  else if((flags & HOST_NAME_RESOLVER_NBNS) != 0)
2345  {
2346  //Use NBNS to resolve the specified host name
2348  }
2349  else if((flags & HOST_NAME_RESOLVER_LLMNR) != 0)
2350  {
2351  //Use LLMNR to resolve the specified host name
2353  }
2354  else
2355  {
2356  //Retrieve the length of the host name to be resolved
2357  size_t n = osStrlen(name);
2358 
2359  //Select the most suitable protocol
2360  if(n >= 6 && osStrcasecmp(name + n - 6, ".local") == 0)
2361  {
2362 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2363  //Use mDNS to resolve the specified host name
2365 #endif
2366  }
2367  else if(n <= 15 && osStrchr(name, '.') == NULL &&
2368  type == HOST_TYPE_IPV4)
2369  {
2370 #if (NBNS_CLIENT_SUPPORT == ENABLED)
2371  //Use NetBIOS Name Service to resolve the specified host name
2373 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
2374  //Use LLMNR to resolve the specified host name
2376 #endif
2377  }
2378  else if(osStrchr(name, '.') == NULL)
2379  {
2380 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2381  //Use LLMNR to resolve the specified host name
2383 #endif
2384  }
2385  }
2386 
2387 #if (DNS_CLIENT_SUPPORT == ENABLED)
2388  //Use DNS protocol?
2390  {
2391  //Perform host name resolution
2392  error = dnsResolve(interface, name, type, ipAddr);
2393  }
2394  else
2395 #endif
2396 #if (MDNS_CLIENT_SUPPORT == ENABLED)
2397  //Use mDNS protocol?
2399  {
2400  //Perform host name resolution
2401  error = mdnsClientResolve(interface, name, type, ipAddr);
2402  }
2403  else
2404 #endif
2405 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
2406  //Use NetBIOS Name Service protocol?
2408  {
2409  //Perform host name resolution
2410  error = nbnsResolve(interface, name, ipAddr);
2411  }
2412  else
2413 #endif
2414 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
2415  //Use LLMNR protocol?
2417  {
2418  //Perform host name resolution
2419  error = llmnrResolve(interface, name, type, ipAddr);
2420  }
2421  else
2422 #endif
2423  //Invalid protocol?
2424  {
2425  //Just for sanity
2426  (void) protocol;
2427  //Report an error
2428  error = ERROR_INVALID_PARAMETER;
2429  }
2430  }
2431 
2432  //Return status code
2433  return error;
2434 }
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:1486
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:195
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:1316
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
int bool_t
Definition: compiler_port.h:53
uint8_t protocol
Definition: ipv4.h:326
@ 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:142
@ 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:659
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:2062
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:386
#define TCP_MAX_MSS
Definition: tcp.h:54
char_t name[]
uint16_t destPort
Definition: tcp.h:340
#define osStrlen(s)
Definition: os_port.h:165
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:294
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:1985
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:426
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:761
@ 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:1634
#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:526
error_t socketSetRxBufferSize(Socket *socket, size_t size)
Specify the size of the TCP receive buffer.
Definition: socket.c:1237
Helper functions for TCP.
void ipUpdateMulticastFilter(NetInterface *interface, const IpAddr *groupAddr)
Update IP multicast filter table.
Definition: ip.c:410
void socketDeleteMulticastGroupEntry(SocketMulticastGroup *group)
Delete a multicast group.
Definition: socket_misc.c:471
@ 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:1692
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:532
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:1021
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:467
#define osStrcasecmp(s1, s2)
Definition: os_port.h:183
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:1714
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1894
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:2274
@ 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:1349
@ 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:2020
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:368
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:429
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:2149
#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:1451
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:268
#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:485
uint8_t flags
Definition: tcp.h:351
#define MAX(a, b)
Definition: os_port.h:67
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:48
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:195
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:1273
@ 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:1953
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:958
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:1293
@ 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:1507
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
@ ERROR_ADDRESS_NOT_FOUND
Definition: error.h:258
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:1736
error_t tcpShutdown(Socket *socket, uint_t how)
Shutdown gracefully reception, transmission, or both.
Definition: tcp.c:820
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:321
unsigned int uint_t
Definition: compiler_port.h:50
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:250
#define osMemset(p, value, length)
Definition: os_port.h:135
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:435
@ 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:273
NetBuffer * buffer
Definition: socket.h:294
uint_t eventMask
Requested events.
Definition: socket.h:428
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:1413