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