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-2023 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.3.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/socket.h"
37 #include "core/socket_misc.h"
38 #include "core/raw_socket.h"
39 #include "core/udp.h"
40 #include "core/tcp.h"
41 #include "core/tcp_misc.h"
42 #include "dns/dns_client.h"
43 #include "mdns/mdns_client.h"
44 #include "netbios/nbns_client.h"
45 #include "llmnr/llmnr_client.h"
46 #include "debug.h"
47 
48 //Socket table
50 
51 //Default socket message
53 {
54  NULL, //Pointer to the payload
55  0, //Size of the payload, in bytes
56  0, //Actual length of the payload, in bytes
57  0, //Time-to-live value
58  0, //Type-of-service value
59  NULL, //Underlying network interface
60  {0}, //Source IP address
61  0, //Source port
62  {0}, //Destination IP address
63  0, //Destination port
64 #if (ETH_SUPPORT == ENABLED)
65  {{{0}}}, //Source MAC address
66  {{{0}}}, //Destination MAC address
67  0, //Ethernet type field
68 #endif
69 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
70  0, //Switch port identifier
71 #endif
72 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
73  -1, //Unique identifier for hardware time stamping
74  {0}, //Captured time stamp
75 #endif
76 };
77 
78 
79 /**
80  * @brief Socket related initialization
81  * @return Error code
82  **/
83 
85 {
86  uint_t i;
87  uint_t j;
88 
89  //Initialize socket descriptors
90  osMemset(socketTable, 0, sizeof(socketTable));
91 
92  //Loop through socket descriptors
93  for(i = 0; i < SOCKET_MAX_COUNT; i++)
94  {
95  //Set socket identifier
96  socketTable[i].descriptor = i;
97 
98  //Create an event object to track socket events
99  if(!osCreateEvent(&socketTable[i].event))
100  {
101  //Clean up side effects
102  for(j = 0; j < i; j++)
103  {
104  osDeleteEvent(&socketTable[j].event);
105  }
106 
107  //Report an error
108  return ERROR_OUT_OF_RESOURCES;
109  }
110  }
111 
112  //Successful initialization
113  return NO_ERROR;
114 }
115 
116 
117 /**
118  * @brief Create a socket (UDP or TCP)
119  * @param[in] type Type specification for the new socket
120  * @param[in] protocol Protocol to be used
121  * @return Handle referencing the new socket
122  **/
123 
125 {
126  Socket *socket;
127 
128  //Get exclusive access
130  //Allocate a new socket
132  //Release exclusive access
134 
135  //Return a handle to the freshly created socket
136  return socket;
137 }
138 
139 
140 /**
141  * @brief Set timeout value for blocking operations
142  * @param[in] socket Handle to a socket
143  * @param[in] timeout Maximum time to wait
144  * @return Error code
145  **/
146 
148 {
149  //Make sure the socket handle is valid
150  if(socket == NULL)
152 
153  //Get exclusive access
155  //Record timeout value
156  socket->timeout = timeout;
157  //Release exclusive access
159 
160  //No error to report
161  return NO_ERROR;
162 }
163 
164 
165 /**
166  * @brief Set TTL value for unicast datagrams
167  * @param[in] socket Handle to a socket
168  * @param[in] ttl Time-to-live value
169  * @return Error code
170  **/
171 
173 {
174  //Make sure the socket handle is valid
175  if(socket == NULL)
177 
178  //Get exclusive access
180  //Set TTL value
181  socket->ttl = ttl;
182  //Release exclusive access
184 
185  //No error to report
186  return NO_ERROR;
187 }
188 
189 
190 /**
191  * @brief Set TTL value for multicast datagrams
192  * @param[in] socket Handle to a socket
193  * @param[in] ttl Time-to-live value
194  * @return Error code
195  **/
196 
198 {
199  //Make sure the socket handle is valid
200  if(socket == NULL)
202 
203  //Get exclusive access
205  //Set TTL value
206  socket->multicastTtl = ttl;
207  //Release exclusive access
209 
210  //No error to report
211  return NO_ERROR;
212 }
213 
214 
215 /**
216  * @brief Set DSCP field
217  * @param[in] socket Handle to a socket
218  * @param[in] dscp Differentiated services codepoint
219  * @return Error code
220  **/
221 
223 {
224  //Make sure the socket handle is valid
225  if(socket == NULL)
227 
228  //The DSCP field is 6 bits wide
229  if(dscp >= 64)
231 
232  //Get exclusive access
234  //Set differentiated services codepoint
235  socket->tos = (dscp << 2) & 0xFF;
236  //Release exclusive access
238 
239  //No error to report
240  return NO_ERROR;
241 }
242 
243 
244 /**
245  * @brief Set VLAN priority
246  * @param[in] socket Handle to a socket
247  * @param[in] pcp VLAN priority value
248  * @return Error code
249  **/
250 
252 {
253 #if (ETH_VLAN_SUPPORT == ENABLED)
254  //Make sure the socket handle is valid
255  if(socket == NULL)
257 
258  //The PCP field is 3 bits wide
259  if(pcp >= 8)
261 
262  //Get exclusive access
264 
265  //The PCP field specifies the frame priority level. Different PCP values
266  //can be used to prioritize different classes of traffic
267  socket->vlanPcp = pcp;
268 
269  //Release exclusive access
271 
272  //No error to report
273  return NO_ERROR;
274 #else
275  //Not implemented
276  return ERROR_NOT_IMPLEMENTED;
277 #endif
278 }
279 
280 
281 /**
282  * @brief Set VLAN DEI flag
283  * @param[in] socket Handle to a socket
284  * @param[in] dei Drop eligible indicator
285  * @return Error code
286  **/
287 
289 {
290 #if (ETH_VLAN_SUPPORT == ENABLED)
291  //Make sure the socket handle is valid
292  if(socket == NULL)
294 
295  //Get exclusive access
297 
298  //The DEI flag may be used to indicate frames eligible to be dropped in
299  //the presence of congestion
300  socket->vlanDei = dei;
301 
302  //Release exclusive access
304 
305  //No error to report
306  return NO_ERROR;
307 #else
308  //Not implemented
309  return ERROR_NOT_IMPLEMENTED;
310 #endif
311 }
312 
313 
314 /**
315  * @brief Set VMAN priority
316  * @param[in] socket Handle to a socket
317  * @param[in] pcp VLAN priority value
318  * @return Error code
319  **/
320 
322 {
323 #if (ETH_VMAN_SUPPORT == ENABLED)
324  //Make sure the socket handle is valid
325  if(socket == NULL)
327 
328  //The PCP field is 3 bits wide
329  if(pcp >= 8)
331 
332  //Get exclusive access
334 
335  //The PCP field specifies the frame priority level. Different PCP values
336  //can be used to prioritize different classes of traffic
337  socket->vmanPcp = pcp;
338 
339  //Release exclusive access
341 
342  //No error to report
343  return NO_ERROR;
344 #else
345  //Not implemented
346  return ERROR_NOT_IMPLEMENTED;
347 #endif
348 }
349 
350 
351 /**
352  * @brief Set VMAN DEI flag
353  * @param[in] socket Handle to a socket
354  * @param[in] dei Drop eligible indicator
355  * @return Error code
356  **/
357 
359 {
360 #if (ETH_VMAN_SUPPORT == ENABLED)
361  //Make sure the socket handle is valid
362  if(socket == NULL)
364 
365  //Get exclusive access
367 
368  //The DEI flag may be used to indicate frames eligible to be dropped in
369  //the presence of congestion
370  socket->vmanDei = dei;
371 
372  //Release exclusive access
374 
375  //No error to report
376  return NO_ERROR;
377 #else
378  //Not implemented
379  return ERROR_NOT_IMPLEMENTED;
380 #endif
381 }
382 
383 
384 /**
385  * @brief Enable reception of broadcast messages
386  * @param[in] socket Handle to a socket
387  * @param[in] enabled Specifies whether broadcast messages should be accepted
388  * @return Error code
389  **/
390 
392 {
393  //Make sure the socket handle is valid
394  if(socket == NULL)
396 
397  //Get exclusive access
399 
400  //Check whether broadcast messages should be accepted
401  if(enabled)
402  {
403  socket->options |= SOCKET_OPTION_BROADCAST;
404  }
405  else
406  {
407  socket->options &= ~SOCKET_OPTION_BROADCAST;
408  }
409 
410  //Release exclusive access
412 
413  //Successful processing
414  return NO_ERROR;
415 }
416 
417 
418 /**
419  * @brief Join the specified host group
420  * @param[in] socket Handle to a socket
421  * @param[in] groupAddr IP address identifying the host group to join
422  * @return Error code
423  **/
424 
426 {
427  error_t error;
428  uint_t i;
429 
430  //Make sure the socket handle is valid
431  if(socket == NULL)
433 
434  //Get exclusive access
436 
437  //Loop through multicast groups
438  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
439  {
440  //Check whether the multicast address is a duplicate
441  if(ipCompAddr(&socket->multicastGroups[i], groupAddr))
442  {
443  break;
444  }
445  }
446 
447  //Multicast group already registered?
449  {
450  //Successful processing
451  error = NO_ERROR;
452  }
453  else
454  {
455  //Initialize status code
456  error = ERROR_OUT_OF_RESOURCES;
457 
458  //Loop through multicast groups
459  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
460  {
461  //Check whether the current entry is available for use
462  if(socket->multicastGroups[i].length == 0)
463  {
464  //Join the specified host group
465  error = ipJoinMulticastGroup(socket->interface, groupAddr);
466 
467  //Check status code
468  if(!error)
469  {
470  //Add a new entry
471  socket->multicastGroups[i] = *groupAddr;
472  }
473 
474  //Exit immediately
475  break;
476  }
477  }
478  }
479 
480  //Release exclusive access
482 
483  //Return status code
484  return error;
485 }
486 
487 
488 /**
489  * @brief Leave the specified host group
490  * @param[in] socket Handle to a socket
491  * @param[in] groupAddr IP address identifying the host group to leave
492  * @return Error code
493  **/
494 
496 {
497  uint_t i;
498 
499  //Make sure the socket handle is valid
500  if(socket == NULL)
502 
503  //Get exclusive access
505 
506  //Loop through multicast groups
507  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
508  {
509  //Matching multicast address?
510  if(ipCompAddr(&socket->multicastGroups[i], groupAddr))
511  {
512  //Drop membership
514  //Delete entry
515  socket->multicastGroups[i] = IP_ADDR_UNSPECIFIED;
516  }
517  }
518 
519  //Release exclusive access
521 
522  //Successful processing
523  return NO_ERROR;
524 }
525 
526 
527 /**
528  * @brief Enable TCP keep-alive
529  * @param[in] socket Handle to a socket
530  * @param[in] enabled Specifies whether TCP keep-alive is enabled
531  * @return Error code
532  **/
533 
535 {
536 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
537  //Make sure the socket handle is valid
538  if(socket == NULL)
540 
541  //Get exclusive access
543 
544  //Check whether TCP keep-alive mechanism should be enabled
545  if(enabled)
546  {
547  //Enable TCP keep-alive mechanism
548  socket->keepAliveEnabled = TRUE;
549  //Reset keep-alive probe counter
550  socket->keepAliveProbeCount = 0;
551  //Start keep-alive timer
552  socket->keepAliveTimestamp = osGetSystemTime();
553  }
554  else
555  {
556  //Disable TCP keep-alive mechanism
557  socket->keepAliveEnabled = FALSE;
558  }
559 
560  //Release exclusive access
562 
563  //Successful processing
564  return NO_ERROR;
565 #else
566  //Not implemented
567  return ERROR_NOT_IMPLEMENTED;
568 #endif
569 }
570 
571 
572 /**
573  * @brief Set TCP keep-alive parameters
574  * @param[in] socket Handle to a socket
575  * @param[in] idle Time interval between last data packet sent and first
576  * keep-alive probe
577  * @param[in] interval Time interval between subsequent keep-alive probes
578  * @param[in] maxProbes Number of unacknowledged keep-alive probes to send before
579  * considering the connection is dead
580  * @return Error code
581  **/
582 
584  systime_t interval, uint_t maxProbes)
585 {
586 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
587  //Check parameters
588  if(socket == NULL || idle == 0 || interval == 0 || maxProbes == 0)
589  {
591  }
592 
593  //Get exclusive access
595 
596  //Time interval between last data packet sent and first keep-alive probe
597  socket->keepAliveIdle = idle;
598 
599  //Time interval between subsequent keep-alive probes
600  socket->keepAliveInterval = interval;
601 
602  //Number of unacknowledged keep-alive probes to send before considering
603  //the connection is dead
604  socket->keepAliveMaxProbes = maxProbes;
605 
606  //Release exclusive access
608 
609  //Successful processing
610  return NO_ERROR;
611 #else
612  //Not implemented
613  return ERROR_NOT_IMPLEMENTED;
614 #endif
615 }
616 
617 
618 /**
619  * @brief Specify the maximum segment size for outgoing TCP packets
620  * @param[in] socket Handle to a socket
621  * @param[in] mss Maximum segment size, in bytes
622  * @return Error code
623  **/
624 
626 {
627 #if (TCP_SUPPORT == ENABLED)
628  //Make sure the socket handle is valid
629  if(socket == NULL)
631 
632  //Get exclusive access
634 
635  //TCP imposes its minimum and maximum bounds over the value provided
636  mss = MIN(mss, TCP_MAX_MSS);
637  mss = MAX(mss, TCP_MIN_MSS);
638 
639  //Set the maximum segment size for outgoing TCP packets. If this option
640  //is set before connection establishment, it also change the MSS value
641  //announced to the other end in the initial SYN packet
642  socket->mss = mss;
643 
644  //Release exclusive access
646 
647  //No error to report
648  return NO_ERROR;
649 #else
650  return ERROR_NOT_IMPLEMENTED;
651 #endif
652 }
653 
654 
655 /**
656  * @brief Specify the size of the TCP send buffer
657  * @param[in] socket Handle to a socket
658  * @param[in] size Desired buffer size, in bytes
659  * @return Error code
660  **/
661 
663 {
664 #if (TCP_SUPPORT == ENABLED)
665  //Make sure the socket handle is valid
666  if(socket == NULL)
668 
669  //Check parameter value
670  if(size < 1 || size > TCP_MAX_TX_BUFFER_SIZE)
672 
673  //This function shall be used with connection-oriented socket types
674  if(socket->type != SOCKET_TYPE_STREAM)
675  return ERROR_INVALID_SOCKET;
676 
677  //The buffer size cannot be changed when the connection is established
679  return ERROR_INVALID_SOCKET;
680 
681  //Use the specified buffer size
682  socket->txBufferSize = size;
683  //No error to report
684  return NO_ERROR;
685 #else
686  return ERROR_NOT_IMPLEMENTED;
687 #endif
688 }
689 
690 
691 /**
692  * @brief Specify the size of the TCP receive buffer
693  * @param[in] socket Handle to a socket
694  * @param[in] size Desired buffer size, in bytes
695  * @return Error code
696  **/
697 
699 {
700 #if (TCP_SUPPORT == ENABLED)
701  //Make sure the socket handle is valid
702  if(socket == NULL)
704 
705  //Check parameter value
706  if(size < 1 || size > TCP_MAX_RX_BUFFER_SIZE)
708 
709  //This function shall be used with connection-oriented socket types
710  if(socket->type != SOCKET_TYPE_STREAM)
711  return ERROR_INVALID_SOCKET;
712 
713  //The buffer size cannot be changed when the connection is established
715  return ERROR_INVALID_SOCKET;
716 
717  //Use the specified buffer size
718  socket->rxBufferSize = size;
719  //No error to report
720  return NO_ERROR;
721 #else
722  return ERROR_NOT_IMPLEMENTED;
723 #endif
724 }
725 
726 
727 /**
728  * @brief Bind a socket to a particular network interface
729  * @param[in] socket Handle to a socket
730  * @param[in] interface Network interface to be used
731  * @return Error code
732  **/
733 
735 {
736  //Make sure the socket handle is valid
737  if(socket == NULL)
739 
740  //Explicitly associate the socket with the specified interface
741  socket->interface = interface;
742 
743  //No error to report
744  return NO_ERROR;
745 }
746 
747 
748 /**
749  * @brief Retrieve the underlying interface
750  * @param[in] socket Handle to a socket
751  * @return Pointer to the underlying network interface
752  **/
753 
755 {
756  NetInterface *interface = NULL;
757 
758  //Make sure the socket handle is valid
759  if(socket != NULL)
760  {
761  interface = socket->interface;
762  }
763 
764  //Return a pointer to the underlying network interface
765  return interface;
766 }
767 
768 
769 /**
770  * @brief Associate a local address with a socket
771  * @param[in] socket Handle to a socket
772  * @param[in] localIpAddr Local address to assign to the bound socket
773  * @param[in] localPort Local port number to assign to the bound socket
774  * @return Error code
775  **/
776 
777 error_t socketBind(Socket *socket, const IpAddr *localIpAddr,
778  uint16_t localPort)
779 {
780  //Check input parameters
781  if(socket == NULL || localIpAddr == NULL)
783 
784  //Make sure the socket type is correct
785  if(socket->type != SOCKET_TYPE_STREAM &&
786  socket->type != SOCKET_TYPE_DGRAM &&
787  socket->type != SOCKET_TYPE_RAW_IP)
788  {
789  return ERROR_INVALID_SOCKET;
790  }
791 
792  //Associate the specified IP address and port number
793  socket->localIpAddr = *localIpAddr;
794  socket->localPort = localPort;
795 
796  //No error to report
797  return NO_ERROR;
798 }
799 
800 
801 /**
802  * @brief Establish a connection to a specified socket
803  * @param[in] socket Handle to an unconnected socket
804  * @param[in] remoteIpAddr IP address of the remote host
805  * @param[in] remotePort Remote port number that will be used to establish
806  * the connection
807  * @return Error code
808  **/
809 
810 error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr,
811  uint16_t remotePort)
812 {
813  error_t error;
814 
815  //Check input parameters
816  if(socket == NULL || remoteIpAddr == NULL)
818 
819 #if (TCP_SUPPORT == ENABLED)
820  //Connection-oriented socket?
821  if(socket->type == SOCKET_TYPE_STREAM)
822  {
823  //Get exclusive access
825 
826  //Establish TCP connection
827  error = tcpConnect(socket, remoteIpAddr, remotePort);
828 
829  //Release exclusive access
831  }
832  else
833 #endif
834  //Connectionless socket?
835  if(socket->type == SOCKET_TYPE_DGRAM)
836  {
837  //Save port number and IP address of the remote host
838  socket->remoteIpAddr = *remoteIpAddr;
839  socket->remotePort = remotePort;
840  //No error to report
841  error = NO_ERROR;
842  }
843  //Raw socket?
844  else if(socket->type == SOCKET_TYPE_RAW_IP)
845  {
846  //Save the IP address of the remote host
847  socket->remoteIpAddr = *remoteIpAddr;
848  //No error to report
849  error = NO_ERROR;
850  }
851  //Invalid socket type?
852  else
853  {
854  //Report an error
855  error = ERROR_INVALID_SOCKET;
856  }
857 
858  //Return status code
859  return error;
860 }
861 
862 
863 /**
864  * @brief Place a socket in the listening state
865  *
866  * Place a socket in a state in which it is listening for an incoming connection
867  *
868  * @param[in] socket Socket to place in the listening state
869  * @param[in] backlog backlog The maximum length of the pending connection queue.
870  * If this parameter is zero, then the default backlog value is used instead
871  * @return Error code
872  **/
873 
875 {
876 #if (TCP_SUPPORT == ENABLED)
877  error_t error;
878 
879  //Make sure the socket handle is valid
880  if(socket == NULL)
882  //This function shall be used with connection-oriented socket types
883  if(socket->type != SOCKET_TYPE_STREAM)
884  return ERROR_INVALID_SOCKET;
885 
886  //Get exclusive access
888 
889  //Start listening for an incoming connection
890  error = tcpListen(socket, backlog);
891 
892  //Release exclusive access
894 
895  //Return status code
896  return error;
897 #else
898  return ERROR_NOT_IMPLEMENTED;
899 #endif
900 }
901 
902 
903 /**
904  * @brief Permit an incoming connection attempt on a socket
905  * @param[in] socket Handle to a socket previously placed in a listening state
906  * @param[out] clientIpAddr IP address of the client
907  * @param[out] clientPort Port number used by the client
908  * @return Handle to the socket in which the actual connection is made
909  **/
910 
912  uint16_t *clientPort)
913 {
914 #if (TCP_SUPPORT == ENABLED)
915  Socket *newSocket;
916 
917  //Make sure the socket handle is valid
918  if(socket == NULL)
919  return NULL;
920  //This function shall be used with connection-oriented socket types
921  if(socket->type != SOCKET_TYPE_STREAM)
922  return NULL;
923 
924  //Accept an incoming connection attempt
925  newSocket = tcpAccept(socket, clientIpAddr, clientPort);
926 
927  //Return a handle to the newly created socket
928  return newSocket;
929 #else
930  return NULL;
931 #endif
932 }
933 
934 
935 /**
936  * @brief Send data to a connected socket
937  * @param[in] socket Handle that identifies a connected socket
938  * @param[in] data Pointer to a buffer containing the data to be transmitted
939  * @param[in] length Number of data bytes to send
940  * @param[out] written Actual number of bytes written (optional parameter)
941  * @param[in] flags Set of flags that influences the behavior of this function
942  * @return Error code
943  **/
944 
945 error_t socketSend(Socket *socket, const void *data, size_t length,
946  size_t *written, uint_t flags)
947 {
948  //Use default remote IP address for connectionless or raw sockets
949  return socketSendTo(socket, &socket->remoteIpAddr, socket->remotePort,
950  data, length, written, flags);
951 }
952 
953 
954 /**
955  * @brief Send a datagram to a specific destination
956  * @param[in] socket Handle that identifies a socket
957  * @param[in] destIpAddr IP address of the target host
958  * @param[in] destPort Target port number
959  * @param[in] data Pointer to a buffer containing the data to be transmitted
960  * @param[in] length Number of data bytes to send
961  * @param[out] written Actual number of bytes written (optional parameter)
962  * @param[in] flags Set of flags that influences the behavior of this function
963  * @return Error code
964  **/
965 
967  const void *data, size_t length, size_t *written, uint_t flags)
968 {
969  error_t error;
970 
971  //No data has been transmitted yet
972  if(written != NULL)
973  *written = 0;
974 
975  //Make sure the socket handle is valid
976  if(socket == NULL)
978 
979  //Get exclusive access
981 
982 #if (TCP_SUPPORT == ENABLED)
983  //Connection-oriented socket?
984  if(socket->type == SOCKET_TYPE_STREAM)
985  {
986  //For connection-oriented sockets, target address is ignored
987  error = tcpSend(socket, data, length, written, flags);
988  }
989  else
990 #endif
991  {
993 
994  //Initialize structure
996 
997  //Set destination IP address
998  if(destIpAddr != NULL)
999  {
1000  message.destIpAddr = *destIpAddr;
1001  }
1002 
1003  //Set destination port
1004  message.destPort = destPort;
1005 
1006 #if (UDP_SUPPORT == ENABLED)
1007  //Connectionless socket?
1008  if(socket->type == SOCKET_TYPE_DGRAM)
1009  {
1010  //Set data payload
1011  message.data = (uint8_t *) data;
1012  message.length = length;
1013 
1014  //Send UDP datagram
1015  error = udpSendDatagram(socket, &message, flags);
1016  }
1017  else
1018 #endif
1019 #if (RAW_SOCKET_SUPPORT == ENABLED)
1020  //Raw socket?
1021  if(socket->type == SOCKET_TYPE_RAW_IP)
1022  {
1023  //Set data payload
1024  message.data = (uint8_t *) data;
1025  message.length = length;
1026 
1027  //Send a raw IP packet
1029  }
1030  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1031  {
1032  //Sanity check
1033  if(length >= sizeof(EthHeader))
1034  {
1035  EthHeader *header;
1036 
1037  //Point to the Ethernet header
1038  header = (EthHeader *) data;
1039 
1040  //Set source and destination MAC addresses
1041  message.srcMacAddr = header->srcAddr;
1042  message.destMacAddr = header->destAddr;
1043 
1044  //Set the value of the EtherType field
1045  message.ethType = ntohs(header->type);
1046 
1047  //Set data payload
1048  message.data = (uint8_t *) data + sizeof(EthHeader);
1049  message.length = length - sizeof(EthHeader);
1050 
1051  //Send a raw Ethernet packet
1053  }
1054  else
1055  {
1056  //Report an error
1057  error = ERROR_INVALID_LENGTH;
1058  }
1059  }
1060  else
1061 #endif
1062  //Invalid socket type?
1063  {
1064  //Report an error
1065  error = ERROR_INVALID_SOCKET;
1066  }
1067 
1068  //Check status code
1069  if(!error)
1070  {
1071  //Total number of data bytes successfully transmitted
1072  if(written != NULL)
1073  *written = message.length;
1074  }
1075  }
1076 
1077  //Release exclusive access
1079 
1080  //Return status code
1081  return error;
1082 }
1083 
1084 
1085 /**
1086  * @brief Send a message to a connectionless socket
1087  * @param[in] socket Handle that identifies a socket
1088  * @param[in] message Pointer to the structure describing the message
1089  * @param[in] flags Set of flags that influences the behavior of this function
1090  * @return Error code
1091  **/
1092 
1094 {
1095  error_t error;
1096 
1097  //Make sure the socket handle is valid
1098  if(socket == NULL)
1099  return ERROR_INVALID_PARAMETER;
1100 
1101  //Get exclusive access
1103 
1104 #if (UDP_SUPPORT == ENABLED)
1105  //Connectionless socket?
1106  if(socket->type == SOCKET_TYPE_DGRAM)
1107  {
1108  //Send UDP datagram
1109  error = udpSendDatagram(socket, message, flags);
1110  }
1111  else
1112 #endif
1113 #if (RAW_SOCKET_SUPPORT == ENABLED)
1114  //Raw socket?
1115  if(socket->type == SOCKET_TYPE_RAW_IP)
1116  {
1117  //Send a raw IP packet
1119  }
1120  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1121  {
1122  //Send a raw Ethernet packet
1124  }
1125  else
1126 #endif
1127  //Invalid socket type?
1128  {
1129  //Report an error
1130  error = ERROR_INVALID_SOCKET;
1131  }
1132 
1133  //Release exclusive access
1135 
1136  //Return status code
1137  return error;
1138 }
1139 
1140 
1141 /**
1142  * @brief Receive data from a connected socket
1143  * @param[in] socket Handle that identifies a connected socket
1144  * @param[out] data Buffer where to store the incoming data
1145  * @param[in] size Maximum number of bytes that can be received
1146  * @param[out] received Number of bytes that have been received
1147  * @param[in] flags Set of flags that influences the behavior of this function
1148  * @return Error code
1149  **/
1150 
1152  size_t size, size_t *received, uint_t flags)
1153 {
1154  //For connection-oriented sockets, source and destination addresses are
1155  //no use
1156  return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received,
1157  flags);
1158 }
1159 
1160 
1161 /**
1162  * @brief Receive a datagram from a connectionless socket
1163  * @param[in] socket Handle that identifies a socket
1164  * @param[out] srcIpAddr Source IP address (optional)
1165  * @param[out] srcPort Source port number (optional)
1166  * @param[out] data Buffer where to store the incoming data
1167  * @param[in] size Maximum number of bytes that can be received
1168  * @param[out] received Number of bytes that have been received
1169  * @param[in] flags Set of flags that influences the behavior of this function
1170  * @return Error code
1171  **/
1172 
1174  void *data, size_t size, size_t *received, uint_t flags)
1175 {
1176  //Destination address is no use
1177  return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size,
1178  received, flags);
1179 }
1180 
1181 
1182 /**
1183  * @brief Receive a datagram
1184  * @param[in] socket Handle that identifies a socket
1185  * @param[out] srcIpAddr Source IP address (optional)
1186  * @param[out] srcPort Source port number (optional)
1187  * @param[out] destIpAddr Destination IP address (optional)
1188  * @param[out] data Buffer where to store the incoming data
1189  * @param[in] size Maximum number of bytes that can be received
1190  * @param[out] received Number of bytes that have been received
1191  * @param[in] flags Set of flags that influences the behavior of this function
1192  * @return Error code
1193  **/
1194 
1196  IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
1197 {
1198  error_t error;
1199 
1200  //No data has been received yet
1201  if(received != NULL)
1202  *received = 0;
1203 
1204  //Make sure the socket handle is valid
1205  if(socket == NULL)
1206  return ERROR_INVALID_PARAMETER;
1207 
1208  //Get exclusive access
1210 
1211 #if (TCP_SUPPORT == ENABLED)
1212  //Connection-oriented socket?
1213  if(socket->type == SOCKET_TYPE_STREAM)
1214  {
1215  //Receive data
1216  error = tcpReceive(socket, data, size, received, flags);
1217 
1218  //Save the source IP address
1219  if(srcIpAddr != NULL)
1220  {
1221  *srcIpAddr = socket->remoteIpAddr;
1222  }
1223 
1224  //Save the source port number
1225  if(srcPort != NULL)
1226  {
1227  *srcPort = socket->remotePort;
1228  }
1229 
1230  //Save the destination IP address
1231  if(destIpAddr != NULL)
1232  {
1233  *destIpAddr = socket->localIpAddr;
1234  }
1235  }
1236  else
1237 #endif
1238  {
1240 
1241  //Initialize structure
1243 
1244 #if (UDP_SUPPORT == ENABLED)
1245  //Connectionless socket?
1246  if(socket->type == SOCKET_TYPE_DGRAM)
1247  {
1248  //Set data buffer
1249  message.data = data;
1250  message.size = size;
1251 
1252  //Receive UDP datagram
1253  error = udpReceiveDatagram(socket, &message, flags);
1254  }
1255  else
1256 #endif
1257 #if (RAW_SOCKET_SUPPORT == ENABLED)
1258  //Raw socket?
1259  if(socket->type == SOCKET_TYPE_RAW_IP)
1260  {
1261  //Set data buffer
1262  message.data = data;
1263  message.size = size;
1264 
1265  //Receive a raw IP packet
1267  }
1268  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1269  {
1270  //Sanity check
1271  if(size >= sizeof(EthHeader))
1272  {
1273  //Set data buffer
1274  message.data = (uint8_t *) data + sizeof(EthHeader);
1275  message.size = size - sizeof(EthHeader);
1276 
1277  //Receive a raw Ethernet packet
1279 
1280  //Check status code
1281  if(!error)
1282  {
1283  EthHeader *header;
1284 
1285  //Point to the Ethernet header
1286  header = (EthHeader *) data;
1287 
1288  //Reconstruct Ethernet header
1289  header->destAddr = message.destMacAddr;
1290  header->srcAddr = message.srcMacAddr;
1291  header->type = htons(message.ethType);
1292 
1293  //Ajuste the length of the frame
1294  message.length += sizeof(EthHeader);
1295  }
1296  }
1297  else
1298  {
1299  //Report an error
1300  error = ERROR_BUFFER_OVERFLOW;
1301  }
1302  }
1303  else
1304 #endif
1305  //Invalid socket type?
1306  {
1307  //Report an error
1308  error = ERROR_INVALID_SOCKET;
1309  }
1310 
1311  //Check status code
1312  if(!error)
1313  {
1314  //Save the source IP address
1315  if(srcIpAddr != NULL)
1316  {
1317  *srcIpAddr = message.srcIpAddr;
1318  }
1319 
1320  //Save the source port number
1321  if(srcPort != NULL)
1322  {
1323  *srcPort = message.srcPort;
1324  }
1325 
1326  //Save the destination IP address
1327  if(destIpAddr != NULL)
1328  {
1329  *destIpAddr = message.destIpAddr;
1330  }
1331 
1332  //Total number of data that have been received
1333  *received = message.length;
1334  }
1335  }
1336 
1337  //Release exclusive access
1339 
1340  //Return status code
1341  return error;
1342 }
1343 
1344 
1345 /**
1346  * @brief Receive a message from a connectionless socket
1347  * @param[in] socket Handle that identifies a socket
1348  * @param[in,out] message Pointer to the structure describing the message
1349  * @param[in] flags Set of flags that influences the behavior of this function
1350  * @return Error code
1351  **/
1352 
1354 {
1355  error_t error;
1356 
1357  //No data has been received yet
1358  message->length = 0;
1359 
1360  //Make sure the socket handle is valid
1361  if(socket == NULL)
1362  return ERROR_INVALID_PARAMETER;
1363 
1364  //Get exclusive access
1366 
1367 #if (UDP_SUPPORT == ENABLED)
1368  //Connectionless socket?
1369  if(socket->type == SOCKET_TYPE_DGRAM)
1370  {
1371  //Receive UDP datagram
1373  }
1374  else
1375 #endif
1376 #if (RAW_SOCKET_SUPPORT == ENABLED)
1377  //Raw socket?
1378  if(socket->type == SOCKET_TYPE_RAW_IP)
1379  {
1380  //Receive a raw IP packet
1382  }
1383  else if(socket->type == SOCKET_TYPE_RAW_ETH)
1384  {
1385  //Receive a raw Ethernet packet
1387  }
1388  else
1389 #endif
1390  //Invalid socket type?
1391  {
1392  //Report an error
1393  error = ERROR_INVALID_SOCKET;
1394  }
1395 
1396  //Release exclusive access
1398 
1399  //Return status code
1400  return error;
1401 }
1402 
1403 
1404 /**
1405  * @brief Retrieve the local address for a given socket
1406  * @param[in] socket Handle that identifies a socket
1407  * @param[out] localIpAddr Local IP address (optional)
1408  * @param[out] localPort Local port number (optional)
1409  * @return Error code
1410  **/
1411 
1413  uint16_t *localPort)
1414 {
1415  //Make sure the socket handle is valid
1416  if(socket == NULL)
1417  return ERROR_INVALID_PARAMETER;
1418 
1419  //Retrieve local IP address
1420  if(localIpAddr != NULL)
1421  {
1422  *localIpAddr = socket->localIpAddr;
1423  }
1424 
1425  //Retrieve local port number
1426  if(localPort != NULL)
1427  {
1428  *localPort = socket->localPort;
1429  }
1430 
1431  //Successful processing
1432  return NO_ERROR;
1433 }
1434 
1435 
1436 /**
1437  * @brief Retrieve the address of the peer to which a socket is connected
1438  * @param[in] socket Handle that identifies a socket
1439  * @param[out] remoteIpAddr IP address of the remote host (optional)
1440  * @param[out] remotePort Remote port number (optional)
1441  * @return Error code
1442  **/
1443 
1445  uint16_t *remotePort)
1446 {
1447  //Make sure the socket handle is valid
1448  if(socket == NULL)
1449  return ERROR_INVALID_PARAMETER;
1450 
1451  //Retrieve local IP address
1452  if(remoteIpAddr != NULL)
1453  {
1454  *remoteIpAddr = socket->remoteIpAddr;
1455  }
1456 
1457  //Retrieve local port number
1458  if(remotePort != NULL)
1459  {
1460  *remotePort = socket->remotePort;
1461  }
1462 
1463  //Successful processing
1464  return NO_ERROR;
1465 }
1466 
1467 
1468 /**
1469  * @brief Disable reception, transmission, or both
1470  *
1471  * Note that socketShutdown() does not close the socket, and resources attached
1472  * to the socket will not be freed until socketClose() is invoked
1473  *
1474  * @param[in] socket Handle to a socket
1475  * @param[in] how Flag that describes what types of operation will no longer be allowed
1476  * @return Error code
1477  **/
1478 
1480 {
1481 #if (TCP_SUPPORT == ENABLED)
1482  error_t error;
1483 
1484  //Make sure the socket handle is valid
1485  if(socket == NULL)
1486  return ERROR_INVALID_PARAMETER;
1487  //Make sure the socket type is correct
1488  if(socket->type != SOCKET_TYPE_STREAM)
1489  return ERROR_INVALID_SOCKET;
1490  //Check flags
1491  if((how != SOCKET_SD_SEND) && (how != SOCKET_SD_RECEIVE) && (how != SOCKET_SD_BOTH))
1492  return ERROR_INVALID_PARAMETER;
1493 
1494  //Get exclusive access
1496 
1497  //Graceful shutdown
1498  error = tcpShutdown(socket, how);
1499 
1500  //Release exclusive access
1502 
1503  //Return status code
1504  return error;
1505 #else
1506  return ERROR_NOT_IMPLEMENTED;
1507 #endif
1508 }
1509 
1510 
1511 /**
1512  * @brief Close an existing socket
1513  * @param[in] socket Handle identifying the socket to close
1514  **/
1515 
1517 {
1518  uint_t i;
1519 
1520  //Make sure the socket handle is valid
1521  if(socket == NULL)
1522  return;
1523 
1524  //Get exclusive access
1526 
1527  //Loop through multicast groups
1528  for(i = 0; i < SOCKET_MAX_MULTICAST_GROUPS; i++)
1529  {
1530  //Valid multicast address?
1531  if(socket->multicastGroups[i].length != 0)
1532  {
1533  //Drop membership
1534  ipLeaveMulticastGroup(socket->interface, &socket->multicastGroups[i]);
1535  //Delete entry
1536  socket->multicastGroups[i] = IP_ADDR_UNSPECIFIED;
1537  }
1538  }
1539 
1540 #if (TCP_SUPPORT == ENABLED)
1541  //Connection-oriented socket?
1542  if(socket->type == SOCKET_TYPE_STREAM)
1543  {
1544  //Abort the current TCP connection
1545  tcpAbort(socket);
1546  }
1547 #endif
1548 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
1549  //Connectionless socket or raw socket?
1550  if(socket->type == SOCKET_TYPE_DGRAM ||
1551  socket->type == SOCKET_TYPE_RAW_IP ||
1552  socket->type == SOCKET_TYPE_RAW_ETH)
1553  {
1554  //Point to the first item in the receive queue
1555  SocketQueueItem *queueItem = socket->receiveQueue;
1556 
1557  //Purge the receive queue
1558  while(queueItem)
1559  {
1560  //Keep track of the next item in the queue
1561  SocketQueueItem *nextQueueItem = queueItem->next;
1562  //Free previously allocated memory
1563  netBufferFree(queueItem->buffer);
1564  //Point to the next item
1565  queueItem = nextQueueItem;
1566  }
1567 
1568  //Mark the socket as closed
1569  socket->type = SOCKET_TYPE_UNUSED;
1570  }
1571 #endif
1572 
1573  //Release exclusive access
1575 }
1576 
1577 
1578 /**
1579  * @brief Wait for one of a set of sockets to become ready to perform I/O
1580  *
1581  * This function determines the status of one or more sockets, waiting if
1582  * necessary, to perform synchronous I/O
1583  *
1584  * @param[in,out] eventDesc Set of entries specifying the events the user is interested in
1585  * @param[in] size Number of entries in the descriptor set
1586  * @param[in] extEvent External event that can abort the wait if necessary (optional)
1587  * @param[in] timeout Maximum time to wait before returning
1588  * @return Error code
1589  **/
1590 
1591 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent,
1592  systime_t timeout)
1593 {
1594  error_t error;
1595  uint_t i;
1596  bool_t status;
1597  OsEvent *event;
1598  OsEvent eventObject;
1599 
1600  //Check parameters
1601  if(eventDesc == NULL || size == 0)
1602  return ERROR_INVALID_PARAMETER;
1603 
1604  //Try to use the supplied event object to receive notifications
1605  if(extEvent == NULL)
1606  {
1607  //Create an event object only if necessary
1608  if(!osCreateEvent(&eventObject))
1609  {
1610  //Report an error
1611  return ERROR_OUT_OF_RESOURCES;
1612  }
1613 
1614  //Reference to the newly created event
1615  event = &eventObject;
1616  }
1617  else
1618  {
1619  //Reference to the external event
1620  event = extEvent;
1621  }
1622 
1623  //Loop through descriptors
1624  for(i = 0; i < size; i++)
1625  {
1626  //Valid socket handle?
1627  if(eventDesc[i].socket != NULL)
1628  {
1629  //Clear event flags
1630  eventDesc[i].eventFlags = 0;
1631 
1632  //Subscribe to the requested events
1633  socketRegisterEvents(eventDesc[i].socket, event,
1634  eventDesc[i].eventMask);
1635  }
1636  }
1637 
1638  //Block the current task until an event occurs
1639  status = osWaitForEvent(event, timeout);
1640 
1641  //Any event?
1642  if(status)
1643  {
1644  //Clear flag
1645  status = FALSE;
1646 
1647  //Loop through descriptors
1648  for(i = 0; i < size; i++)
1649  {
1650  //Valid socket handle?
1651  if(eventDesc[i].socket != NULL)
1652  {
1653  //Retrieve event flags for the current socket
1654  eventDesc[i].eventFlags = socketGetEvents(eventDesc[i].socket);
1655  //Clear unnecessary flags
1656  eventDesc[i].eventFlags &= eventDesc[i].eventMask;
1657 
1658  //Check whether the socket is ready to perform I/O
1659  if(eventDesc[i].eventFlags != 0)
1660  {
1661  status = TRUE;
1662  }
1663  }
1664  }
1665 
1666  //Any socket event in the signaled state?
1667  if(status)
1668  {
1669  error = NO_ERROR;
1670  }
1671  else
1672  {
1673  error = ERROR_WAIT_CANCELED;
1674  }
1675  }
1676  else
1677  {
1678  //Report a timeout error
1679  error = ERROR_TIMEOUT;
1680  }
1681 
1682  //Loop through descriptors
1683  for(i = 0; i < size; i++)
1684  {
1685  //Valid socket handle?
1686  if(eventDesc[i].socket != NULL)
1687  {
1688  //Unsubscribe previously registered events
1689  socketUnregisterEvents(eventDesc[i].socket);
1690  }
1691  }
1692 
1693  //Reset event object
1694  osResetEvent(event);
1695 
1696  //Release previously allocated resources
1697  if(extEvent == NULL)
1698  {
1699  osDeleteEvent(&eventObject);
1700  }
1701 
1702  //Return status code
1703  return error;
1704 }
1705 
1706 
1707 /**
1708  * @brief Resolve a host name into an IP address
1709  * @param[in] interface Underlying network interface (optional parameter)
1710  * @param[in] name Name of the host to be resolved
1711  * @param[out] ipAddr IP address corresponding to the specified host name
1712  * @param[in] flags Set of flags that influences the behavior of this function
1713  * @return Error code
1714  **/
1715 
1718 {
1719  error_t error;
1720  HostType type;
1722 
1723  //Default address type depends on TCP/IP stack configuration
1724 #if (IPV4_SUPPORT == ENABLED)
1725  type = HOST_TYPE_IPV4;
1726 #elif (IPV6_SUPPORT == ENABLED)
1727  type = HOST_TYPE_IPV6;
1728 #else
1729  type = HOST_TYPE_ANY;
1730 #endif
1731 
1732  //Default name resolution protocol depends on TCP/IP stack configuration
1733 #if (DNS_CLIENT_SUPPORT == ENABLED)
1735 #elif (MDNS_CLIENT_SUPPORT == ENABLED)
1737 #elif (NBNS_CLIENT_SUPPORT == ENABLED)
1739 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
1741 #else
1743 #endif
1744 
1745  //Check parameters
1746  if(name == NULL || ipAddr == NULL)
1747  return ERROR_INVALID_PARAMETER;
1748 
1749  //Use default network interface?
1750  if(interface == NULL)
1751  {
1752  interface = netGetDefaultInterface();
1753  }
1754 
1755  //The specified name can be either an IP or a host name
1756  error = ipStringToAddr(name, ipAddr);
1757 
1758  //Perform name resolution if necessary
1759  if(error)
1760  {
1761  //The user may provide a hint to choose between IPv4 and IPv6
1762  if((flags & HOST_TYPE_IPV4) != 0)
1763  {
1764  type = HOST_TYPE_IPV4;
1765  }
1766  else if((flags & HOST_TYPE_IPV6) != 0)
1767  {
1768  type = HOST_TYPE_IPV6;
1769  }
1770  else
1771  {
1772  //Just for sanity
1773  }
1774 
1775  //The user may provide a hint to to select the desired protocol to be used
1776  if((flags & HOST_NAME_RESOLVER_DNS) != 0)
1777  {
1778  //Use DNS to resolve the specified host name
1780  }
1781  else if((flags & HOST_NAME_RESOLVER_MDNS) != 0)
1782  {
1783  //Use mDNS to resolve the specified host name
1785  }
1786  else if((flags & HOST_NAME_RESOLVER_NBNS) != 0)
1787  {
1788  //Use NBNS to resolve the specified host name
1790  }
1791  else if((flags & HOST_NAME_RESOLVER_LLMNR) != 0)
1792  {
1793  //Use LLMNR to resolve the specified host name
1795  }
1796  else
1797  {
1798  //Retrieve the length of the host name to be resolved
1799  size_t n = osStrlen(name);
1800 
1801  //Select the most suitable protocol
1802  if(n >= 6 && !osStrcasecmp(name + n - 6, ".local"))
1803  {
1804 #if (MDNS_CLIENT_SUPPORT == ENABLED)
1805  //Use mDNS to resolve the specified host name
1807 #endif
1808  }
1809  else if(n <= 15 && !osStrchr(name, '.') && type == HOST_TYPE_IPV4)
1810  {
1811 #if (NBNS_CLIENT_SUPPORT == ENABLED)
1812  //Use NetBIOS Name Service to resolve the specified host name
1814 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
1815  //Use LLMNR to resolve the specified host name
1817 #endif
1818  }
1819  else if(!osStrchr(name, '.'))
1820  {
1821 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
1822  //Use LLMNR to resolve the specified host name
1824 #endif
1825  }
1826  }
1827 
1828 #if (DNS_CLIENT_SUPPORT == ENABLED)
1829  //Use DNS protocol?
1831  {
1832  //Perform host name resolution
1833  error = dnsResolve(interface, name, type, ipAddr);
1834  }
1835  else
1836 #endif
1837 #if (MDNS_CLIENT_SUPPORT == ENABLED)
1838  //Use mDNS protocol?
1840  {
1841  //Perform host name resolution
1842  error = mdnsClientResolve(interface, name, type, ipAddr);
1843  }
1844  else
1845 #endif
1846 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
1847  //Use NetBIOS Name Service protocol?
1849  {
1850  //Perform host name resolution
1851  error = nbnsResolve(interface, name, ipAddr);
1852  }
1853  else
1854 #endif
1855 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
1856  //Use LLMNR protocol?
1858  {
1859  //Perform host name resolution
1860  error = llmnrResolve(interface, name, type, ipAddr);
1861  }
1862  else
1863 #endif
1864  //Invalid protocol?
1865  {
1866  //Just for sanity
1867  (void) protocol;
1868  //Report an error
1869  error = ERROR_INVALID_PARAMETER;
1870  }
1871  }
1872 
1873  //Return status code
1874  return error;
1875 }
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
uint8_t message[]
Definition: chap.h:152
uint8_t type
Definition: coap_common.h:174
unsigned int uint_t
Definition: compiler_port.h:50
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
#define htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
uint8_t n
error_t dnsResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using DNS.
Definition: dns_client.c:54
DNS client (Domain Name System)
uint32_t ttl
Definition: dns_common.h:219
error_t
Error codes.
Definition: error.h:43
@ ERROR_WAIT_CANCELED
Definition: error.h:73
@ ERROR_INVALID_SOCKET
Definition: error.h:83
@ ERROR_TIMEOUT
Definition: error.h:95
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t data[]
Definition: ethernet.h:220
EthHeader
Definition: ethernet.h:221
Ipv4Addr groupAddr
Definition: igmp_common.h:169
error_t ipLeaveMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Leave the specified host group.
Definition: ip.c:454
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:794
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:52
error_t ipJoinMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Join the specified host group.
Definition: ip.c:408
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:315
Ipv4Addr ipAddr
Definition: ipcp.h:103
Ipv4Addr destIpAddr
Definition: ipcp.h:78
Ipv4Addr srcIpAddr
Definition: ipcp.h:77
uint8_t protocol
Definition: ipv4.h:294
error_t llmnrResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using LLMNR.
Definition: llmnr_client.c:53
LLMNR client (Link-Local Multicast Name Resolution)
error_t mdnsClientResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using mDNS.
Definition: mdns_client.c:55
mDNS client (Multicast DNS)
error_t nbnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr)
Resolve a host name using NBNS.
Definition: nbns_client.c:53
NBNS client (NetBIOS Name Service)
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:414
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
#define osMemset(p, value, length)
Definition: os_port.h:137
#define osStrcasecmp(s1, s2)
Definition: os_port.h:185
#define MIN(a, b)
Definition: os_port.h:65
#define osStrchr(s, c)
Definition: os_port.h:197
#define osStrlen(s)
Definition: os_port.h:167
#define TRUE
Definition: os_port.h:52
#define FALSE
Definition: os_port.h:48
#define MAX(a, b)
Definition: os_port.h:69
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
systime_t osGetSystemTime(void)
Retrieve system time.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
uint32_t systime_t
System time.
error_t rawSocketReceiveEthPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an Ethernet packet from a raw socket.
Definition: raw_socket.c:893
error_t rawSocketSendIpPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw IP packet.
Definition: raw_socket.c:517
error_t rawSocketSendEthPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw Ethernet packet.
Definition: raw_socket.c:695
error_t rawSocketReceiveIpPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an IP packet from a raw socket.
Definition: raw_socket.c:787
TCP/IP raw sockets.
char_t name[]
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:911
error_t socketSetInterface(Socket *socket, NetInterface *interface)
Bind a socket to a particular network interface.
Definition: socket.c:734
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:52
error_t socketInit(void)
Socket related initialization.
Definition: socket.c:84
error_t socketJoinMulticastGroup(Socket *socket, const IpAddr *groupAddr)
Join the specified host group.
Definition: socket.c:425
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:1173
error_t socketSetVmanPcp(Socket *socket, uint8_t pcp)
Set VMAN priority.
Definition: socket.c:321
error_t socketSetVlanDei(Socket *socket, bool_t dei)
Set VLAN DEI flag.
Definition: socket.c:288
error_t socketSetMulticastTtl(Socket *socket, uint8_t ttl)
Set TTL value for multicast datagrams.
Definition: socket.c:197
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:777
error_t socketLeaveMulticastGroup(Socket *socket, const IpAddr *groupAddr)
Leave the specified host group.
Definition: socket.c:495
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:1591
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:966
NetInterface * socketGetInterface(Socket *socket)
Retrieve the underlying interface.
Definition: socket.c:754
error_t socketSetTtl(Socket *socket, uint8_t ttl)
Set TTL value for unicast datagrams.
Definition: socket.c:172
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:1195
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:1151
error_t socketEnableBroadcast(Socket *socket, bool_t enabled)
Enable reception of broadcast messages.
Definition: socket.c:391
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:874
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:1716
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:124
error_t socketSetDscp(Socket *socket, uint8_t dscp)
Set DSCP field.
Definition: socket.c:222
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:945
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:147
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:1516
error_t socketSetKeepAliveParams(Socket *socket, systime_t idle, systime_t interval, uint_t maxProbes)
Set TCP keep-alive parameters.
Definition: socket.c:583
error_t socketSetVlanPcp(Socket *socket, uint8_t pcp)
Set VLAN priority.
Definition: socket.c:251
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:1479
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
error_t socketEnableKeepAlive(Socket *socket, bool_t enabled)
Enable TCP keep-alive.
Definition: socket.c:534
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1353
error_t socketSetRxBufferSize(Socket *socket, size_t size)
Specify the size of the TCP receive buffer.
Definition: socket.c:698
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1093
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:1444
error_t socketSetMaxSegmentSize(Socket *socket, size_t mss)
Specify the maximum segment size for outgoing TCP packets.
Definition: socket.c:625
error_t socketSetTxBufferSize(Socket *socket, size_t size)
Specify the size of the TCP send buffer.
Definition: socket.c:662
error_t socketGetLocalAddr(Socket *socket, IpAddr *localIpAddr, uint16_t *localPort)
Retrieve the local address for a given socket.
Definition: socket.c:1412
error_t socketSetVmanDei(Socket *socket, bool_t dei)
Set VMAN DEI flag.
Definition: socket.c:358
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:810
Socket API.
@ SOCKET_SD_BOTH
Definition: socket.h:151
@ SOCKET_SD_SEND
Definition: socket.h:150
@ SOCKET_SD_RECEIVE
Definition: socket.h:149
@ SOCKET_OPTION_BROADCAST
Definition: socket.h:183
@ SOCKET_TYPE_DGRAM
Definition: socket.h:86
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:87
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:88
@ SOCKET_TYPE_UNUSED
Definition: socket.h:84
@ SOCKET_TYPE_STREAM
Definition: socket.h:85
#define Socket
Definition: socket.h:36
HostType
Host types.
Definition: socket.h:202
@ HOST_TYPE_IPV6
Definition: socket.h:205
@ HOST_TYPE_ANY
Definition: socket.h:203
@ HOST_TYPE_IPV4
Definition: socket.h:204
#define SOCKET_MAX_COUNT
Definition: socket.h:46
HostnameResolver
Name resolution protocols.
Definition: socket.h:214
@ HOST_NAME_RESOLVER_NBNS
Definition: socket.h:218
@ HOST_NAME_RESOLVER_DNS
Definition: socket.h:216
@ HOST_NAME_RESOLVER_MDNS
Definition: socket.h:217
@ HOST_NAME_RESOLVER_ANY
Definition: socket.h:215
@ HOST_NAME_RESOLVER_LLMNR
Definition: socket.h:219
#define SOCKET_MAX_MULTICAST_GROUPS
Definition: socket.h:53
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
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:250
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:273
Helper functions for sockets.
Receive queue item.
Definition: socket.h:259
NetBuffer * buffer
Definition: socket.h:265
struct _SocketQueueItem * next
Definition: socket.h:260
IP network address.
Definition: ip.h:72
Event object.
Structure describing socket events.
Definition: socket.h:395
uint_t eventMask
Requested events.
Definition: socket.h:397
uint_t eventFlags
Returned events.
Definition: socket.h:398
Message and ancillary data.
Definition: socket.h:228
error_t tcpAbort(Socket *socket)
Abort an existing TCP connection.
Definition: tcp.c:957
TcpState tcpGetState(Socket *socket)
Get the current state of the TCP FSM.
Definition: tcp.c:1020
Socket * tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a TCP socket.
Definition: tcp.c:320
error_t tcpShutdown(Socket *socket, uint_t how)
Shutdown gracefully reception, transmission, or both.
Definition: tcp.c:819
error_t tcpListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: tcp.c:293
error_t tcpConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a TCP connection.
Definition: tcp.c:146
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:531
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:658
TCP (Transmission Control Protocol)
uint8_t length
Definition: tcp.h:366
#define TCP_MAX_RX_BUFFER_SIZE
Definition: tcp.h:89
@ TCP_STATE_CLOSED
Definition: tcp.h:268
#define TCP_MAX_MSS
Definition: tcp.h:54
#define TCP_MAX_TX_BUFFER_SIZE
Definition: tcp.h:75
uint8_t flags
Definition: tcp.h:349
#define TCP_MIN_MSS
Definition: tcp.h:61
uint16_t destPort
Definition: tcp.h:338
Helper functions for TCP.
error_t udpReceiveDatagram(Socket *socket, SocketMsg *message, uint_t flags)
Receive data from a UDP socket.
Definition: udp.c:784
error_t udpSendDatagram(Socket *socket, const SocketMsg *message, uint_t flags)
Send a UDP datagram.
Definition: udp.c:492
UDP (User Datagram Protocol)