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-2019 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 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include <string.h>
36 #include "core/net.h"
37 #include "core/socket.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 
52 /**
53  * @brief Socket related initialization
54  * @return Error code
55  **/
56 
58 {
59  uint_t i;
60  uint_t j;
61 
62  //Initialize socket descriptors
63  memset(socketTable, 0, sizeof(socketTable));
64 
65  //Loop through socket descriptors
66  for(i = 0; i < SOCKET_MAX_COUNT; i++)
67  {
68  //Set socket identifier
69  socketTable[i].descriptor = i;
70 
71  //Create an event object to track socket events
72  if(!osCreateEvent(&socketTable[i].event))
73  {
74  //Clean up side effects
75  for(j = 0; j < i; j++)
76  osDeleteEvent(&socketTable[j].event);
77 
78  //Report an error
80  }
81  }
82 
83  //Successful initialization
84  return NO_ERROR;
85 }
86 
87 
88 /**
89  * @brief Create a socket (UDP or TCP)
90  * @param[in] type Type specification for the new socket
91  * @param[in] protocol Protocol to be used
92  * @return Handle referencing the new socket
93  **/
94 
96 {
97  error_t error;
98  uint_t i;
99  uint16_t port;
100  Socket *socket;
101  OsEvent event;
102 
103  //Initialize socket handle
104  socket = NULL;
105 
106  //Get exclusive access
108 
109 #if (TCP_SUPPORT == ENABLED)
110  //Connection-oriented socket?
111  if(type == SOCKET_TYPE_STREAM)
112  {
113  //Always use TCP as underlying transport protocol
115  //Get an ephemeral port number
117  //Continue processing
118  error = NO_ERROR;
119  }
120  else
121 #endif
122 #if (UDP_SUPPORT == ENABLED)
123  //Connectionless socket?
124  if(type == SOCKET_TYPE_DGRAM)
125  {
126  //Always use UDP as underlying transport protocol
128  //Get an ephemeral port number
130  //Continue processing
131  error = NO_ERROR;
132  }
133  else
134 #endif
135 #if (RAW_SOCKET_SUPPORT == ENABLED)
136  //Raw socket?
138  {
139  //Port numbers are not relevant for raw sockets
140  port = 0;
141  //Continue processing
142  error = NO_ERROR;
143  }
144  else
145 #endif
146  {
147  //The socket type is not supported
148  error = ERROR_INVALID_PARAMETER;
149  }
150 
151  //Check status code
152  if(!error)
153  {
154  //Loop through socket descriptors
155  for(i = 0; i < SOCKET_MAX_COUNT; i++)
156  {
157  //Unused socket found?
159  {
160  //Save socket handle
161  socket = &socketTable[i];
162  //We are done
163  break;
164  }
165  }
166 
167 #if (TCP_SUPPORT == ENABLED)
168  //No more sockets available?
169  if(socket == NULL)
170  {
171  //Kill the oldest connection in the TIME-WAIT state
172  //whenever the socket table runs out of space
174  }
175 #endif
176 
177  //Check whether the current entry is free
178  if(socket != NULL)
179  {
180  //Save socket descriptor
181  i = socket->descriptor;
182  //Save event object instance
183  memcpy(&event, &socket->event, sizeof(OsEvent));
184 
185  //Clear associated structure
186  memset(socket, 0, sizeof(Socket));
187  //Reuse event objects and avoid recreating them whenever possible
188  memcpy(&socket->event, &event, sizeof(OsEvent));
189 
190  //Save socket characteristics
191  socket->descriptor = i;
192  socket->type = type;
193  socket->protocol = protocol;
194  socket->localPort = port;
195  socket->timeout = INFINITE_DELAY;
196 
197 #if (TCP_SUPPORT == ENABLED)
200 #endif
201  }
202  }
203 
204  //Release exclusive access
206 
207  //Return a handle to the freshly created socket
208  return socket;
209 }
210 
211 
212 /**
213  * @brief Set timeout value for blocking operations
214  * @param[in] socket Handle to a socket
215  * @param[in] timeout Maximum time to wait
216  * @return Error code
217  **/
218 
220 {
221  //Make sure the socket handle is valid
222  if(socket == NULL)
224 
225  //Get exclusive access
227  //Record timeout value
228  socket->timeout = timeout;
229  //Release exclusive access
231 
232  //No error to report
233  return NO_ERROR;
234 }
235 
236 
237 /**
238  * @brief Specify the size of the send buffer
239  * @param[in] socket Handle to a socket
240  * @param[in] size Desired buffer size in bytes
241  * @return Error code
242  **/
243 
245 {
246 #if (TCP_SUPPORT == ENABLED)
247  //Make sure the socket handle is valid
248  if(socket == NULL)
250  //Check parameter value
251  if(size < 1 || size > TCP_MAX_TX_BUFFER_SIZE)
253 
254  //This function shall be used with connection-oriented socket types
255  if(socket->type != SOCKET_TYPE_STREAM)
256  return ERROR_INVALID_SOCKET;
257  //The buffer size cannot be changed when the connection is established
259  return ERROR_INVALID_SOCKET;
260 
261  //Use the specified buffer size
262  socket->txBufferSize = size;
263  //No error to report
264  return NO_ERROR;
265 #else
266  return ERROR_NOT_IMPLEMENTED;
267 #endif
268 }
269 
270 
271 /**
272  * @brief Specify the size of the receive buffer
273  * @param[in] socket Handle to a socket
274  * @param[in] size Desired buffer size in bytes
275  * @return Error code
276  **/
277 
279 {
280 #if (TCP_SUPPORT == ENABLED)
281  //Make sure the socket handle is valid
282  if(socket == NULL)
284  //Check parameter value
285  if(size < 1 || size > TCP_MAX_RX_BUFFER_SIZE)
287 
288  //This function shall be used with connection-oriented socket types
289  if(socket->type != SOCKET_TYPE_STREAM)
290  return ERROR_INVALID_SOCKET;
291  //The buffer size cannot be changed when the connection is established
293  return ERROR_INVALID_SOCKET;
294 
295  //Use the specified buffer size
296  socket->rxBufferSize = size;
297  //No error to report
298  return NO_ERROR;
299 #else
300  return ERROR_NOT_IMPLEMENTED;
301 #endif
302 }
303 
304 
305 /**
306  * @brief Bind a socket to a particular network interface
307  * @param[in] socket Handle to a socket
308  * @param[in] interface Network interface to be used
309  * @return Error code
310  **/
311 
313 {
314  //Make sure the socket handle is valid
315  if(socket == NULL)
317 
318  //Explicitly associate the socket with the specified interface
319  socket->interface = interface;
320 
321  //No error to report
322  return NO_ERROR;
323 }
324 
325 
326 /**
327  * @brief Retrieve the underlying interface
328  * @param[in] socket Handle to a socket
329  * @return Pointer to the underlying network interface
330  **/
331 
333 {
334  NetInterface *interface = NULL;
335 
336  //Make sure the socket handle is valid
337  if(socket != NULL)
338  {
339  interface = socket->interface;
340  }
341 
342  //Return a pointer to the underlying network interface
343  return interface;
344 }
345 
346 
347 /**
348  * @brief Associate a local address with a socket
349  * @param[in] socket Handle to a socket
350  * @param[in] localIpAddr Local address to assign to the bound socket
351  * @param[in] localPort Local port number to assign to the bound socket
352  * @return Error code
353  **/
354 
355 error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
356 {
357  //Check input parameters
358  if(!socket || !localIpAddr)
360  //Make sure the socket type is correct
361  if(socket->type != SOCKET_TYPE_STREAM && socket->type != SOCKET_TYPE_DGRAM)
362  return ERROR_INVALID_SOCKET;
363 
364  //Associate the specified IP address and port number
365  socket->localIpAddr = *localIpAddr;
366  socket->localPort = localPort;
367 
368  //No error to report
369  return NO_ERROR;
370 }
371 
372 
373 /**
374  * @brief Establish a connection to a specified socket
375  * @param[in] socket Handle to an unconnected socket
376  * @param[in] remoteIpAddr IP address of the remote host
377  * @param[in] remotePort Remote port number that will be used to establish the connection
378  * @return Error code
379  **/
380 
381 error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
382 {
383  error_t error;
384 
385  //Check input parameters
386  if(!socket || !remoteIpAddr)
388 
389 #if (TCP_SUPPORT == ENABLED)
390  //Connection-oriented socket?
391  if(socket->type == SOCKET_TYPE_STREAM)
392  {
393  //Get exclusive access
395 
396  //Establish TCP connection
397  error = tcpConnect(socket, remoteIpAddr, remotePort);
398 
399  //Release exclusive access
401  }
402  else
403 #endif
404  //Connectionless socket?
405  if(socket->type == SOCKET_TYPE_DGRAM)
406  {
407  //Save port number and IP address of the remote host
408  socket->remoteIpAddr = *remoteIpAddr;
409  socket->remotePort = remotePort;
410  //No error to report
411  error = NO_ERROR;
412  }
413  //Raw socket?
414  else if(socket->type == SOCKET_TYPE_RAW_IP)
415  {
416  //Save the IP address of the remote host
417  socket->remoteIpAddr = *remoteIpAddr;
418  //No error to report
419  error = NO_ERROR;
420  }
421  //Socket type not supported...
422  else
423  {
424  //Invalid socket type
425  error = ERROR_INVALID_SOCKET;
426  }
427 
428  //Return status code
429  return error;
430 }
431 
432 
433 /**
434  * @brief Place a socket in the listening state
435  *
436  * Place a socket in a state in which it is listening for an incoming connection
437  *
438  * @param[in] socket Socket to place in the listening state
439  * @param[in] backlog backlog The maximum length of the pending connection queue.
440  * If this parameter is zero, then the default backlog value is used instead
441  * @return Error code
442  **/
443 
445 {
446 #if (TCP_SUPPORT == ENABLED)
447  error_t error;
448 
449  //Make sure the socket handle is valid
450  if(socket == NULL)
452  //This function shall be used with connection-oriented socket types
453  if(socket->type != SOCKET_TYPE_STREAM)
454  return ERROR_INVALID_SOCKET;
455 
456  //Get exclusive access
458 
459  //Start listening for an incoming connection
460  error = tcpListen(socket, backlog);
461 
462  //Release exclusive access
464 
465  //Return status code
466  return error;
467 #else
468  return ERROR_NOT_IMPLEMENTED;
469 #endif
470 }
471 
472 
473 /**
474  * @brief Permit an incoming connection attempt on a socket
475  * @param[in] socket Handle to a socket previously placed in a listening state
476  * @param[out] clientIpAddr IP address of the client
477  * @param[out] clientPort Port number used by the client
478  * @return Handle to the socket in which the actual connection is made
479  **/
480 
481 Socket *socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
482 {
483 #if (TCP_SUPPORT == ENABLED)
484  Socket *newSocket;
485 
486  //Make sure the socket handle is valid
487  if(socket == NULL)
488  return NULL;
489  //This function shall be used with connection-oriented socket types
490  if(socket->type != SOCKET_TYPE_STREAM)
491  return NULL;
492 
493  //Accept an incoming connection attempt
494  newSocket = tcpAccept(socket, clientIpAddr, clientPort);
495 
496  //Return a handle to the newly created socket
497  return newSocket;
498 #else
499  return NULL;
500 #endif
501 }
502 
503 
504 /**
505  * @brief Send data to a connected socket
506  * @param[in] socket Handle that identifies a connected socket
507  * @param[in] data Pointer to a buffer containing the data to be transmitted
508  * @param[in] length Number of data bytes to send
509  * @param[out] written Actual number of bytes written (optional parameter)
510  * @param[in] flags Set of flags that influences the behavior of this function
511  * @return Error code
512  **/
513 
515  size_t length, size_t *written, uint_t flags)
516 {
517  //Use default remote IP address for connectionless or raw sockets
518  return socketSendTo(socket, &socket->remoteIpAddr,
519  socket->remotePort, data, length, written, flags);
520 }
521 
522 
523 /**
524  * @brief Send a datagram to a specific destination
525  * @param[in] socket Handle that identifies a socket
526  * @param[in] destIpAddr IP address of the target host
527  * @param[in] destPort Target port number
528  * @param[in] data Pointer to a buffer containing the data to be transmitted
529  * @param[in] length Number of data bytes to send
530  * @param[out] written Actual number of bytes written (optional parameter)
531  * @param[in] flags Set of flags that influences the behavior of this function
532  * @return Error code
533  **/
534 
536  const void *data, size_t length, size_t *written, uint_t flags)
537 {
538  error_t error;
539 
540  //No data has been transmitted yet
541  if(written)
542  *written = 0;
543 
544  //Make sure the socket handle is valid
545  if(socket == NULL)
547 
548  //Get exclusive access
550 
551 #if (TCP_SUPPORT == ENABLED)
552  //Connection-oriented socket?
553  if(socket->type == SOCKET_TYPE_STREAM)
554  {
555  //For connection-oriented sockets, target address is ignored
556  error = tcpSend(socket, data, length, written, flags);
557  }
558  else
559 #endif
560 #if (UDP_SUPPORT == ENABLED)
561  //Connectionless socket?
562  if(socket->type == SOCKET_TYPE_DGRAM)
563  {
564  //Send UDP datagram
566  written, flags);
567  }
568  else
569 #endif
570 #if (RAW_SOCKET_SUPPORT == ENABLED)
571  //Raw socket?
572  if(socket->type == SOCKET_TYPE_RAW_IP)
573  {
574  //Send a raw IP packet
576  written, flags);
577  }
578  else if(socket->type == SOCKET_TYPE_RAW_ETH)
579  {
580  //Send a raw Ethernet packet
581  error = rawSocketSendEthPacket(socket, data, length, written);
582  }
583  else
584 #endif
585  //Socket type not supported...
586  {
587  //Invalid socket type
588  error = ERROR_INVALID_SOCKET;
589  }
590 
591  //Release exclusive access
593 
594  //Return status code
595  return error;
596 }
597 
598 
599 /**
600  * @brief Receive data from a connected socket
601  * @param[in] socket Handle that identifies a connected socket
602  * @param[out] data Buffer where to store the incoming data
603  * @param[in] size Maximum number of bytes that can be received
604  * @param[out] received Number of bytes that have been received
605  * @param[in] flags Set of flags that influences the behavior of this function
606  * @return Error code
607  **/
608 
610  size_t size, size_t *received, uint_t flags)
611 {
612  //For connection-oriented sockets, source and destination addresses are no use
613  return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received, flags);
614 }
615 
616 
617 /**
618  * @brief Receive a datagram from a connectionless socket
619  * @param[in] socket Handle that identifies a socket
620  * @param[out] srcIpAddr Source IP address (optional)
621  * @param[out] srcPort Source port number (optional)
622  * @param[out] data Buffer where to store the incoming data
623  * @param[in] size Maximum number of bytes that can be received
624  * @param[out] received Number of bytes that have been received
625  * @param[in] flags Set of flags that influences the behavior of this function
626  * @return Error code
627  **/
628 
630  void *data, size_t size, size_t *received, uint_t flags)
631 {
632  //Destination address is no use
633  return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size, received, flags);
634 }
635 
636 
637 /**
638  * @brief Receive a datagram
639  * @param[in] socket Handle that identifies a socket
640  * @param[out] srcIpAddr Source IP address (optional)
641  * @param[out] srcPort Source port number (optional)
642  * @param[out] destIpAddr Destination IP address (optional)
643  * @param[out] data Buffer where to store the incoming data
644  * @param[in] size Maximum number of bytes that can be received
645  * @param[out] received Number of bytes that have been received
646  * @param[in] flags Set of flags that influences the behavior of this function
647  * @return Error code
648  **/
649 
651  IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
652 {
653  error_t error;
654 
655  //Make sure the socket handle is valid
656  if(socket == NULL)
658 
659  //Get exclusive access
661 
662 #if (TCP_SUPPORT == ENABLED)
663  //Connection-oriented socket?
664  if(socket->type == SOCKET_TYPE_STREAM)
665  {
666  //Receive data
667  error = tcpReceive(socket, data, size, received, flags);
668 
669  //Output parameters
670  if(srcIpAddr)
671  *srcIpAddr = socket->remoteIpAddr;
672  if(srcPort)
673  *srcPort = socket->remotePort;
674  if(destIpAddr)
675  *destIpAddr = socket->localIpAddr;
676  }
677  else
678 #endif
679 #if (UDP_SUPPORT == ENABLED)
680  //Connectionless socket?
681  if(socket->type == SOCKET_TYPE_DGRAM)
682  {
683  //Receive UDP datagram
685  srcPort, destIpAddr, data, size, received, flags);
686  }
687  else
688 #endif
689 #if (RAW_SOCKET_SUPPORT == ENABLED)
690  //Raw socket?
691  if(socket->type == SOCKET_TYPE_RAW_IP)
692  {
693  //Receive a raw IP packet
695  srcIpAddr, destIpAddr, data, size, received, flags);
696  }
697  else if(socket->type == SOCKET_TYPE_RAW_ETH)
698  {
699  //Receive a raw Ethernet packet
700  error = rawSocketReceiveEthPacket(socket, data, size, received, flags);
701  }
702  else
703 #endif
704  //Socket type not supported...
705  {
706  //No data can be read
707  *received = 0;
708  //Invalid socket type
709  error = ERROR_INVALID_SOCKET;
710  }
711 
712  //Release exclusive access
714 
715  //Return status code
716  return error;
717 }
718 
719 
720 /**
721  * @brief Retrieve the local address for a given socket
722  * @param[in] socket Handle that identifies a socket
723  * @param[out] localIpAddr Local IP address (optional)
724  * @param[out] localPort Local port number (optional)
725  * @return Error code
726  **/
727 
728 error_t socketGetLocalAddr(Socket *socket, IpAddr *localIpAddr, uint16_t *localPort)
729 {
730  //Make sure the socket handle is valid
731  if(socket == NULL)
733 
734  //Retrieve local IP address
735  if(localIpAddr != NULL)
736  *localIpAddr = socket->localIpAddr;
737 
738  //Retrieve local port number
739  if(localPort != NULL)
740  *localPort = socket->localPort;
741 
742  //Successful processing
743  return NO_ERROR;
744 }
745 
746 
747 /**
748  * @brief Retrieve the address of the peer to which a socket is connected
749  * @param[in] socket Handle that identifies a socket
750  * @param[out] remoteIpAddr IP address of the remote host (optional)
751  * @param[out] remotePort Remote port number (optional)
752  * @return Error code
753  **/
754 
755 error_t socketGetRemoteAddr(Socket *socket, IpAddr *remoteIpAddr, uint16_t *remotePort)
756 {
757  //Make sure the socket handle is valid
758  if(socket == NULL)
760 
761  //Retrieve local IP address
762  if(remoteIpAddr != NULL)
763  *remoteIpAddr = socket->remoteIpAddr;
764 
765  //Retrieve local port number
766  if(remotePort != NULL)
767  *remotePort = socket->remotePort;
768 
769  //Successful processing
770  return NO_ERROR;
771 }
772 
773 
774 /**
775  * @brief Disable reception, transmission, or both
776  *
777  * Note that socketShutdown() does not close the socket, and resources attached
778  * to the socket will not be freed until socketClose() is invoked
779  *
780  * @param[in] socket Handle to a socket
781  * @param[in] how Flag that describes what types of operation will no longer be allowed
782  * @return Error code
783  **/
784 
786 {
787 #if (TCP_SUPPORT == ENABLED)
788  error_t error;
789 
790  //Make sure the socket handle is valid
791  if(socket == NULL)
793  //Make sure the socket type is correct
794  if(socket->type != SOCKET_TYPE_STREAM)
795  return ERROR_INVALID_SOCKET;
796  //Check flags
797  if((how != SOCKET_SD_SEND) && (how != SOCKET_SD_RECEIVE) && (how != SOCKET_SD_BOTH))
799 
800  //Get exclusive access
802 
803  //Graceful shutdown
804  error = tcpShutdown(socket, how);
805 
806  //Release exclusive access
808 
809  //Return status code
810  return error;
811 #else
812  return ERROR_NOT_IMPLEMENTED;
813 #endif
814 }
815 
816 
817 /**
818  * @brief Close an existing socket
819  * @param[in] socket Handle identifying the socket to close
820  **/
821 
823 {
824  //Make sure the socket handle is valid
825  if(socket == NULL)
826  return;
827 
828  //Get exclusive access
830 
831 #if (TCP_SUPPORT == ENABLED)
832  //Connection-oriented socket?
833  if(socket->type == SOCKET_TYPE_STREAM)
834  {
835  //Abort the current TCP connection
836  tcpAbort(socket);
837  }
838 #endif
839 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED)
840  //Connectionless socket or raw socket?
841  if(socket->type == SOCKET_TYPE_DGRAM ||
842  socket->type == SOCKET_TYPE_RAW_IP ||
843  socket->type == SOCKET_TYPE_RAW_ETH)
844  {
845  //Point to the first item in the receive queue
846  SocketQueueItem *queueItem = socket->receiveQueue;
847 
848  //Purge the receive queue
849  while(queueItem)
850  {
851  //Keep track of the next item in the queue
852  SocketQueueItem *nextQueueItem = queueItem->next;
853  //Free previously allocated memory
854  memPoolFree(queueItem->buffer);
855  //Point to the next item
856  queueItem = nextQueueItem;
857  }
858 
859  //Mark the socket as closed
860  socket->type = SOCKET_TYPE_UNUSED;
861  }
862 #endif
863 
864  //Release exclusive access
866 }
867 
868 
869 /**
870  * @brief Wait for one of a set of sockets to become ready to perform I/O
871  *
872  * The socketPoll function determines the status of one or more sockets,
873  * waiting if necessary, to perform synchronous I/O
874  *
875  * @param[in,out] eventDesc Set of entries specifying the events the user is interested in
876  * @param[in] size Number of entries in the descriptor set
877  * @param[in] extEvent External event that can abort the wait if necessary (optional)
878  * @param[in] timeout Maximum time to wait before returning
879  * @return Error code
880  **/
881 
882 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent,
883  systime_t timeout)
884 {
885  uint_t i;
886  bool_t status;
887  OsEvent *event;
888  OsEvent eventObject;
889 
890  //Check parameters
891  if(eventDesc == NULL || size == 0)
893 
894  //Try to use the supplied event object to receive notifications
895  if(!extEvent)
896  {
897  //Create an event object only if necessary
898  if(!osCreateEvent(&eventObject))
899  {
900  //Report an error
901  return ERROR_OUT_OF_RESOURCES;
902  }
903 
904  //Reference to the newly created event
905  event = &eventObject;
906  }
907  else
908  {
909  //Reference to the external event
910  event = extEvent;
911  }
912 
913  //Loop through descriptors
914  for(i = 0; i < size; i++)
915  {
916  //Valid socket handle?
917  if(eventDesc[i].socket != NULL)
918  {
919  //Clear event flags
920  eventDesc[i].eventFlags = 0;
921  //Subscribe to the requested events
922  socketRegisterEvents(eventDesc[i].socket, event, eventDesc[i].eventMask);
923  }
924  }
925 
926  //Block the current task until an event occurs
927  status = osWaitForEvent(event, timeout);
928 
929  //Loop through descriptors
930  for(i = 0; i < size; i++)
931  {
932  //Valid socket handle?
933  if(eventDesc[i].socket != NULL)
934  {
935  //Any socket event in the signaled state?
936  if(status)
937  {
938  //Retrieve event flags for the current socket
939  eventDesc[i].eventFlags = socketGetEvents(eventDesc[i].socket);
940  //Clear unnecessary flags
941  eventDesc[i].eventFlags &= eventDesc[i].eventMask;
942  }
943 
944  //Unsubscribe previously registered events
945  socketUnregisterEvents(eventDesc[i].socket);
946  }
947  }
948 
949  //Reset event object
950  osResetEvent(event);
951 
952  //Release previously allocated resources
953  if(!extEvent)
954  osDeleteEvent(&eventObject);
955 
956  //Return status code
957  return status ? NO_ERROR : ERROR_TIMEOUT;
958 }
959 
960 
961 /**
962  * @brief Subscribe to the specified socket events
963  * @param[in] socket Handle that identifies a socket
964  * @param[in] event Event object used to receive notifications
965  * @param[in] eventMask Logic OR of the requested socket events
966  **/
967 
969 {
970  //Valid socket handle?
971  if(socket != NULL)
972  {
973  //Get exclusive access
975 
976  //An user event may have been previously registered...
977  if(socket->userEvent != NULL)
978  socket->eventMask |= eventMask;
979  else
980  socket->eventMask = eventMask;
981 
982  //Suscribe to get notified of events
983  socket->userEvent = event;
984 
985 #if (TCP_SUPPORT == ENABLED)
986  //Handle TCP specific events
987  if(socket->type == SOCKET_TYPE_STREAM)
988  {
990  }
991 #endif
992 #if (UDP_SUPPORT == ENABLED)
993  //Handle UDP specific events
994  if(socket->type == SOCKET_TYPE_DGRAM)
995  {
997  }
998 #endif
999 #if (RAW_SOCKET_SUPPORT == ENABLED)
1000  //Handle events that are specific to raw sockets
1001  if(socket->type == SOCKET_TYPE_RAW_IP ||
1002  socket->type == SOCKET_TYPE_RAW_ETH)
1003  {
1005  }
1006 #endif
1007 
1008  //Release exclusive access
1010  }
1011 }
1012 
1013 
1014 /**
1015  * @brief Unsubscribe previously registered events
1016  * @param[in] socket Handle that identifies a socket
1017  **/
1018 
1020 {
1021  //Valid socket handle?
1022  if(socket != NULL)
1023  {
1024  //Get exclusive access
1026 
1027  //Unsuscribe socket events
1028  socket->userEvent = NULL;
1029 
1030  //Release exclusive access
1032  }
1033 }
1034 
1035 
1036 /**
1037  * @brief Retrieve event flags for a specified socket
1038  * @param[in] socket Handle that identifies a socket
1039  * @return Logic OR of events in the signaled state
1040  **/
1041 
1043 {
1044  uint_t eventFlags;
1045 
1046  //Valid socket handle?
1047  if(socket != NULL)
1048  {
1049  //Get exclusive access
1051 
1052  //Read event flags for the specified socket
1053  eventFlags = socket->eventFlags;
1054 
1055  //Release exclusive access
1057  }
1058  else
1059  {
1060  //The socket handle is not valid
1061  eventFlags = 0;
1062  }
1063 
1064  //Return the events in the signaled state
1065  return eventFlags;
1066 }
1067 
1068 
1069 /**
1070  * @brief Resolve a host name into an IP address
1071  * @param[in] interface Underlying network interface (optional parameter)
1072  * @param[in] name Name of the host to be resolved
1073  * @param[out] ipAddr IP address corresponding to the specified host name
1074  * @param[in] flags Set of flags that influences the behavior of this function
1075  * @return Error code
1076  **/
1077 
1079  const char_t *name, IpAddr *ipAddr, uint_t flags)
1080 {
1081  error_t error;
1082  HostType type;
1084 
1085  //Default address type depends on TCP/IP stack configuration
1086 #if (IPV4_SUPPORT == ENABLED)
1087  type = HOST_TYPE_IPV4;
1088 #elif (IPV6_SUPPORT == ENABLED)
1089  type = HOST_TYPE_IPV6;
1090 #else
1091  type = HOST_TYPE_ANY;
1092 #endif
1093 
1094  //Default name resolution protocol depends on TCP/IP stack configuration
1095 #if (DNS_CLIENT_SUPPORT == ENABLED)
1097 #elif (MDNS_CLIENT_SUPPORT == ENABLED)
1099 #elif (NBNS_CLIENT_SUPPORT == ENABLED)
1101 #elif (LLMNR_CLIENT_SUPPORT == ENABLED)
1103 #else
1105 #endif
1106 
1107  //Check parameters
1108  if(name == NULL || ipAddr == NULL)
1109  return ERROR_INVALID_PARAMETER;
1110 
1111  //Use default network interface?
1112  if(interface == NULL)
1113  interface = netGetDefaultInterface();
1114 
1115  //The specified name can be either an IP or a host name
1116  error = ipStringToAddr(name, ipAddr);
1117 
1118  //Perform name resolution if necessary
1119  if(error)
1120  {
1121  //The user may provide a hint to choose between IPv4 and IPv6
1122  if(flags & HOST_TYPE_IPV4)
1123  type = HOST_TYPE_IPV4;
1124  else if(flags & HOST_TYPE_IPV6)
1125  type = HOST_TYPE_IPV6;
1126 
1127  //The user may provide a hint to to select the desired protocol to be used
1129  {
1130  //Use DNS to resolve the specified host name
1132  }
1133  else if(flags & HOST_NAME_RESOLVER_MDNS)
1134  {
1135  //Use mDNS to resolve the specified host name
1137  }
1138  else if(flags & HOST_NAME_RESOLVER_NBNS)
1139  {
1140  //Use NBNS to resolve the specified host name
1142  }
1143  else if(flags & HOST_NAME_RESOLVER_LLMNR)
1144  {
1145  //Use LLMNR to resolve the specified host name
1147  }
1148  else
1149  {
1150  //Retrieve the length of the host name to be resolved
1151  size_t n = strlen(name);
1152 
1153  //Select the most suitable protocol
1154  if(n >= 6 && !strcasecmp(name + n - 6, ".local"))
1155  {
1156 #if (MDNS_CLIENT_SUPPORT == ENABLED)
1157  //Use mDNS to resolve the specified host name
1159 #endif
1160  }
1161  else if(n <= 15 && !strchr(name, '.') && type == HOST_TYPE_IPV4)
1162  {
1163 #if (NBNS_CLIENT_SUPPORT == ENABLED)
1164  //Use NetBIOS Name Service to resolve the specified host name
1166 #endif
1167  }
1168  else if(!strchr(name, '.'))
1169  {
1170 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
1171  //Use LLMNR to resolve the specified host name
1173 #endif
1174  }
1175  }
1176 
1177 #if (DNS_CLIENT_SUPPORT == ENABLED)
1178  //Use DNS protocol?
1180  {
1181  //Perform host name resolution
1182  error = dnsResolve(interface, name, type, ipAddr);
1183  }
1184  else
1185 #endif
1186 #if (MDNS_CLIENT_SUPPORT == ENABLED)
1187  //Use mDNS protocol?
1189  {
1190  //Perform host name resolution
1191  error = mdnsClientResolve(interface, name, type, ipAddr);
1192  }
1193  else
1194 #endif
1195 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
1196  //Use NetBIOS Name Service protocol?
1198  {
1199  //Perform host name resolution
1200  error = nbnsResolve(interface, name, ipAddr);
1201  }
1202  else
1203 #endif
1204 #if (LLMNR_CLIENT_SUPPORT == ENABLED)
1205  //Use LLMNR protocol?
1207  {
1208  //Perform host name resolution
1209  error = llmnrResolve(interface, name, type, ipAddr);
1210  }
1211  else
1212 #endif
1213  //Invalid protocol?
1214  {
1215  //Report an error
1216  error = ERROR_INVALID_PARAMETER;
1217  }
1218  }
1219 
1220  //Return status code
1221  return error;
1222 }
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:514
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:93
HostType
Host types.
Definition: socket.h:171
uint8_t length
Definition: dtls_misc.h:149
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:355
HostnameResolver
Name resolution protocols.
Definition: socket.h:183
int bool_t
Definition: compiler_port.h:49
void memPoolFree(void *p)
Release a memory block.
Definition: net_mem.c:166
@ HOST_NAME_RESOLVER_DNS
Definition: socket.h:186
void udpUpdateEvents(Socket *socket)
Update UDP related events.
Definition: udp.c:720
IP network address.
Definition: ip.h:71
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ HOST_TYPE_ANY
Definition: socket.h:173
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:574
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:822
Event object.
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ HOST_NAME_RESOLVER_LLMNR
Definition: socket.h:189
@ SOCKET_TYPE_DGRAM
Definition: socket.h:78
error_t udpReceiveDatagram(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
Receive data from a UDP socket.
Definition: udp.c:622
char_t name[]
uint16_t destPort
Definition: tcp.h:303
Ipv4Addr srcIpAddr
Definition: ipcp.h:77
struct _SocketQueueItem * next
Definition: socket.h:199
error_t tcpListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: tcp.c:236
@ SOCKET_TYPE_STREAM
Definition: socket.h:77
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:755
Structure describing socket events.
Definition: socket.h:307
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket.c:1042
error_t socketSetTxBufferSize(Socket *socket, size_t size)
Specify the size of the send buffer.
Definition: socket.c:244
#define TCP_DEFAULT_TX_BUFFER_SIZE
Definition: tcp.h:68
@ HOST_TYPE_IPV6
Definition: socket.h:175
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:682
@ SOCKET_SD_SEND
Definition: socket.h:142
error_t socketSetRxBufferSize(Socket *socket, size_t size)
Specify the size of the receive buffer.
Definition: socket.c:278
Helper functions for TCP.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
error_t dnsResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using DNS.
Definition: dns_client.c:54
char_t type
error_t
Error codes.
Definition: error.h:42
Socket * tcpKillOldestConnection(void)
Kill the oldest socket in the TIME-WAIT state.
Definition: tcp.c:961
#define TCP_MAX_RX_BUFFER_SIZE
Definition: tcp.h:89
error_t socketReceive(Socket *socket, void *data, size_t size, size_t *received, uint_t flags)
Receive data from a connected socket.
Definition: socket.c:609
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:449
uint8_t protocol
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:108
@ HOST_NAME_RESOLVER_MDNS
Definition: socket.h:187
NBNS client (NetBIOS Name Service)
TcpState tcpGetState(Socket *socket)
Get the current state of the TCP FSM.
Definition: tcp.c:937
void osDeleteEvent(OsEvent *event)
Delete an event object.
@ ERROR_INVALID_SOCKET
Definition: error.h:82
#define NetInterface
Definition: net.h:36
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:1782
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:629
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:1078
OsMutex netMutex
Definition: net.c:75
mDNS client (Multicast DNS)
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:381
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:79
void tcpUpdateEvents(Socket *socket)
Update TCP related events.
Definition: tcp_misc.c:1756
error_t llmnrResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using LLMNR.
Definition: llmnr_client.c:54
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:785
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:95
#define MIN(a, b)
Definition: os_port.h:62
@ HOST_TYPE_IPV4
Definition: socket.h:174
uint_t eventFlags
Returned events.
Definition: socket.h:311
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:882
void rawSocketUpdateEvents(Socket *socket)
Update event state for raw sockets.
Definition: raw_socket.c:780
#define TCP_MAX_TX_BUFFER_SIZE
Definition: tcp.h:75
uint16_t udpGetDynamicPort(void)
Get an ephemeral port number.
Definition: udp.c:89
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket.c:1019
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:481
DNS client (Domain Name System)
TCP/IP raw sockets.
error_t rawSocketSendIpPacket(Socket *socket, const IpAddr *destIpAddr, const void *data, size_t length, size_t *written, uint_t flags)
Send an raw IP packet.
Definition: raw_socket.c:411
@ TCP_STATE_CLOSED
Definition: tcp.h:233
uint16_t port
Definition: dns_common.h:223
Receive queue item.
Definition: socket.h:197
uint8_t flags
Definition: tcp.h:314
@ ERROR_TIMEOUT
Definition: error.h:94
char char_t
Definition: compiler_port.h:43
LLMNR client (Link-Local Multicast Name Resolution)
void socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
Subscribe to the specified socket events.
Definition: socket.c:968
uint16_t tcpGetDynamicPort(void)
Get an ephemeral port number.
Definition: tcp.c:75
error_t rawSocketReceiveIpPacket(Socket *socket, IpAddr *srcIpAddr, IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
Receive an IP packet from a raw socket.
Definition: raw_socket.c:644
error_t rawSocketSendEthPacket(Socket *socket, const void *data, size_t length, size_t *written)
Send an raw Ethernet packet.
Definition: raw_socket.c:524
error_t socketSetInterface(Socket *socket, NetInterface *interface)
Bind a socket to a particular network interface.
Definition: socket.c:312
error_t rawSocketReceiveEthPacket(Socket *socket, void *data, size_t size, size_t *received, uint_t flags)
Receive an Ethernet packet from a raw socket.
Definition: raw_socket.c:718
@ HOST_NAME_RESOLVER_ANY
Definition: socket.h:185
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
TCP (Transmission Control Protocol)
@ SOCKET_TYPE_UNUSED
Definition: socket.h:76
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
error_t socketGetLocalAddr(Socket *socket, IpAddr *localIpAddr, uint16_t *localPort)
Retrieve the local address for a given socket.
Definition: socket.c:728
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
@ SOCKET_SD_RECEIVE
Definition: socket.h:141
error_t tcpAbort(Socket *socket)
Abort an existing TCP connection.
Definition: tcp.c:873
error_t mdnsClientResolve(NetInterface *interface, const char_t *name, HostType type, IpAddr *ipAddr)
Resolve a host name using mDNS.
Definition: mdns_client.c:56
UDP (User Datagram Protocol)
#define Socket
Definition: socket.h:36
@ HOST_NAME_RESOLVER_NBNS
Definition: socket.h:188
NetInterface * socketGetInterface(Socket *socket)
Retrieve the underlying interface.
Definition: socket.c:332
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define strcasecmp
Socket API.
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:535
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:80
error_t tcpConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a TCP connection.
Definition: tcp.c:115
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:650
error_t tcpShutdown(Socket *socket, uint_t how)
Shutdown gracefully reception, transmission, or both.
Definition: tcp.c:722
uint16_t srcPort
Definition: tcp.h:302
Socket * tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a TCP socket.
Definition: tcp.c:263
#define TCP_DEFAULT_RX_BUFFER_SIZE
Definition: tcp.h:82
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
error_t udpSendDatagram(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a UDP datagram.
Definition: udp.c:401
#define SOCKET_MAX_COUNT
Definition: socket.h:45
@ SOCKET_SD_BOTH
Definition: socket.h:143
@ SOCKET_IP_PROTO_TCP
Definition: socket.h:92
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:219
uint32_t systime_t
Definition: compiler_port.h:46
uint8_t ipAddr[4]
Definition: mib_common.h:187
NetBuffer * buffer
Definition: socket.h:203
uint_t eventMask
Requested events.
Definition: socket.h:310
error_t socketInit(void)
Socket related initialization.
Definition: socket.c:57
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:74
error_t nbnsResolve(NetInterface *interface, const char_t *name, IpAddr *ipAddr)
Resolve a host name using NBNS.
Definition: nbns_client.c:53
Ipv4Addr destIpAddr
Definition: ipcp.h:78
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:444