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