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