Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
socket.c
00001 /** 00002 * @file socket.c 00003 * @brief Socket API 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL SOCKET_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <string.h> 00034 #include "core/net.h" 00035 #include "core/socket.h" 00036 #include "core/raw_socket.h" 00037 #include "core/udp.h" 00038 #include "core/tcp.h" 00039 #include "core/tcp_misc.h" 00040 #include "dns/dns_client.h" 00041 #include "mdns/mdns_client.h" 00042 #include "netbios/nbns_client.h" 00043 #include "debug.h" 00044 00045 //Socket table 00046 Socket socketTable[SOCKET_MAX_COUNT]; 00047 00048 00049 /** 00050 * @brief Socket related initialization 00051 * @return Error code 00052 **/ 00053 00054 error_t socketInit(void) 00055 { 00056 uint_t i; 00057 uint_t j; 00058 00059 //Initialize socket descriptors 00060 memset(socketTable, 0, sizeof(socketTable)); 00061 00062 //Loop through socket descriptors 00063 for(i = 0; i < SOCKET_MAX_COUNT; i++) 00064 { 00065 //Set socket identifier 00066 socketTable[i].descriptor = i; 00067 00068 //Create an event object to track socket events 00069 if(!osCreateEvent(&socketTable[i].event)) 00070 { 00071 //Clean up side effects 00072 for(j = 0; j < i; j++) 00073 osDeleteEvent(&socketTable[j].event); 00074 00075 //Report an error 00076 return ERROR_OUT_OF_RESOURCES; 00077 } 00078 } 00079 00080 //Successful initialization 00081 return NO_ERROR; 00082 } 00083 00084 00085 /** 00086 * @brief Create a socket (UDP or TCP) 00087 * @param[in] type Type specification for the new socket 00088 * @param[in] protocol Protocol to be used 00089 * @return Handle referencing the new socket 00090 **/ 00091 00092 Socket *socketOpen(uint_t type, uint_t protocol) 00093 { 00094 error_t error; 00095 uint_t i; 00096 uint16_t port; 00097 Socket *socket; 00098 OsEvent event; 00099 00100 //Initialize socket handle 00101 socket = NULL; 00102 00103 //Get exclusive access 00104 osAcquireMutex(&netMutex); 00105 00106 #if (TCP_SUPPORT == ENABLED) 00107 //Connection-oriented socket? 00108 if(type == SOCKET_TYPE_STREAM) 00109 { 00110 //Always use TCP as underlying transport protocol 00111 protocol = SOCKET_IP_PROTO_TCP; 00112 //Get an ephemeral port number 00113 port = tcpGetDynamicPort(); 00114 //Continue processing 00115 error = NO_ERROR; 00116 } 00117 else 00118 #endif 00119 #if (UDP_SUPPORT == ENABLED) 00120 //Connectionless socket? 00121 if(type == SOCKET_TYPE_DGRAM) 00122 { 00123 //Always use UDP as underlying transport protocol 00124 protocol = SOCKET_IP_PROTO_UDP; 00125 //Get an ephemeral port number 00126 port = udpGetDynamicPort(); 00127 //Continue processing 00128 error = NO_ERROR; 00129 } 00130 else 00131 #endif 00132 #if (RAW_SOCKET_SUPPORT == ENABLED) 00133 //Raw socket? 00134 if(type == SOCKET_TYPE_RAW_IP || type == SOCKET_TYPE_RAW_ETH) 00135 { 00136 //Port numbers are not relevant for raw sockets 00137 port = 0; 00138 //Continue processing 00139 error = NO_ERROR; 00140 } 00141 else 00142 #endif 00143 { 00144 //The socket type is not supported 00145 error = ERROR_INVALID_PARAMETER; 00146 } 00147 00148 //Check status code 00149 if(!error) 00150 { 00151 //Loop through socket descriptors 00152 for(i = 0; i < SOCKET_MAX_COUNT; i++) 00153 { 00154 //Unused socket found? 00155 if(socketTable[i].type == SOCKET_TYPE_UNUSED) 00156 { 00157 //Save socket handle 00158 socket = &socketTable[i]; 00159 //We are done 00160 break; 00161 } 00162 } 00163 00164 #if (TCP_SUPPORT == ENABLED) 00165 //No more sockets available? 00166 if(socket == NULL) 00167 { 00168 //Kill the oldest connection in the TIME-WAIT state 00169 //whenever the socket table runs out of space 00170 socket = tcpKillOldestConnection(); 00171 } 00172 #endif 00173 00174 //Check whether the current entry is free 00175 if(socket != NULL) 00176 { 00177 //Save socket descriptor 00178 i = socket->descriptor; 00179 //Save event object instance 00180 memcpy(&event, &socket->event, sizeof(OsEvent)); 00181 00182 //Clear associated structure 00183 memset(socket, 0, sizeof(Socket)); 00184 //Reuse event objects and avoid recreating them whenever possible 00185 memcpy(&socket->event, &event, sizeof(OsEvent)); 00186 00187 //Save socket characteristics 00188 socket->descriptor = i; 00189 socket->type = type; 00190 socket->protocol = protocol; 00191 socket->localPort = port; 00192 socket->timeout = INFINITE_DELAY; 00193 00194 #if (TCP_SUPPORT == ENABLED) 00195 socket->txBufferSize = MIN(TCP_DEFAULT_TX_BUFFER_SIZE, TCP_MAX_TX_BUFFER_SIZE); 00196 socket->rxBufferSize = MIN(TCP_DEFAULT_RX_BUFFER_SIZE, TCP_MAX_RX_BUFFER_SIZE); 00197 #endif 00198 } 00199 } 00200 00201 //Release exclusive access 00202 osReleaseMutex(&netMutex); 00203 00204 //Return a handle to the freshly created socket 00205 return socket; 00206 } 00207 00208 00209 /** 00210 * @brief Set timeout value for blocking operations 00211 * @param[in] socket Handle to a socket 00212 * @param[in] timeout Maximum time to wait 00213 * @return Error code 00214 **/ 00215 00216 error_t socketSetTimeout(Socket *socket, systime_t timeout) 00217 { 00218 //Make sure the socket handle is valid 00219 if(socket == NULL) 00220 return ERROR_INVALID_PARAMETER; 00221 00222 //Get exclusive access 00223 osAcquireMutex(&netMutex); 00224 //Record timeout value 00225 socket->timeout = timeout; 00226 //Release exclusive access 00227 osReleaseMutex(&netMutex); 00228 00229 //No error to report 00230 return NO_ERROR; 00231 } 00232 00233 00234 /** 00235 * @brief Specify the size of the send buffer 00236 * @param[in] socket Handle to a socket 00237 * @param[in] size Desired buffer size in bytes 00238 * @return Error code 00239 **/ 00240 00241 error_t socketSetTxBufferSize(Socket *socket, size_t size) 00242 { 00243 #if (TCP_SUPPORT == ENABLED) 00244 //Make sure the socket handle is valid 00245 if(socket == NULL) 00246 return ERROR_INVALID_PARAMETER; 00247 //Check parameter value 00248 if(size < 1 || size > TCP_MAX_TX_BUFFER_SIZE) 00249 return ERROR_INVALID_PARAMETER; 00250 00251 //This function shall be used with connection-oriented socket types 00252 if(socket->type != SOCKET_TYPE_STREAM) 00253 return ERROR_INVALID_SOCKET; 00254 //The buffer size cannot be changed when the connection is established 00255 if(tcpGetState(socket) != TCP_STATE_CLOSED) 00256 return ERROR_INVALID_SOCKET; 00257 00258 //Use the specified buffer size 00259 socket->txBufferSize = size; 00260 //No error to report 00261 return NO_ERROR; 00262 #else 00263 return ERROR_NOT_IMPLEMENTED; 00264 #endif 00265 } 00266 00267 00268 /** 00269 * @brief Specify the size of the receive buffer 00270 * @param[in] socket Handle to a socket 00271 * @param[in] size Desired buffer size in bytes 00272 * @return Error code 00273 **/ 00274 00275 error_t socketSetRxBufferSize(Socket *socket, size_t size) 00276 { 00277 #if (TCP_SUPPORT == ENABLED) 00278 //Make sure the socket handle is valid 00279 if(socket == NULL) 00280 return ERROR_INVALID_PARAMETER; 00281 //Check parameter value 00282 if(size < 1 || size > TCP_MAX_RX_BUFFER_SIZE) 00283 return ERROR_INVALID_PARAMETER; 00284 00285 //This function shall be used with connection-oriented socket types 00286 if(socket->type != SOCKET_TYPE_STREAM) 00287 return ERROR_INVALID_SOCKET; 00288 //The buffer size cannot be changed when the connection is established 00289 if(tcpGetState(socket) != TCP_STATE_CLOSED) 00290 return ERROR_INVALID_SOCKET; 00291 00292 //Use the specified buffer size 00293 socket->rxBufferSize = size; 00294 //No error to report 00295 return NO_ERROR; 00296 #else 00297 return ERROR_NOT_IMPLEMENTED; 00298 #endif 00299 } 00300 00301 00302 /** 00303 * @brief Bind a socket to a particular network interface 00304 * @param[in] socket Handle to a socket 00305 * @param[in] interface Network interface to be used 00306 * @return Error code 00307 **/ 00308 00309 error_t socketBindToInterface(Socket *socket, NetInterface *interface) 00310 { 00311 //Make sure the socket handle is valid 00312 if(socket == NULL) 00313 return ERROR_INVALID_PARAMETER; 00314 00315 //Explicitly associate the socket with the specified interface 00316 socket->interface = interface; 00317 00318 //No error to report 00319 return NO_ERROR; 00320 } 00321 00322 00323 /** 00324 * @brief Associate a local address with a socket 00325 * @param[in] socket Handle to a socket 00326 * @param[in] localIpAddr Local address to assign to the bound socket 00327 * @param[in] localPort Local port number to assign to the bound socket 00328 * @return Error code 00329 **/ 00330 00331 error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort) 00332 { 00333 //Check input parameters 00334 if(!socket || !localIpAddr) 00335 return ERROR_INVALID_PARAMETER; 00336 //Make sure the socket type is correct 00337 if(socket->type != SOCKET_TYPE_STREAM && socket->type != SOCKET_TYPE_DGRAM) 00338 return ERROR_INVALID_SOCKET; 00339 00340 //Associate the specified IP address and port number 00341 socket->localIpAddr = *localIpAddr; 00342 socket->localPort = localPort; 00343 00344 //No error to report 00345 return NO_ERROR; 00346 } 00347 00348 00349 /** 00350 * @brief Establish a connection to a specified socket 00351 * @param[in] socket Handle to an unconnected socket 00352 * @param[in] remoteIpAddr IP address of the remote host 00353 * @param[in] remotePort Remote port number that will be used to establish the connection 00354 * @return Error code 00355 **/ 00356 00357 error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort) 00358 { 00359 error_t error; 00360 00361 //Check input parameters 00362 if(!socket || !remoteIpAddr) 00363 return ERROR_INVALID_PARAMETER; 00364 00365 #if (TCP_SUPPORT == ENABLED) 00366 //Connection-oriented socket? 00367 if(socket->type == SOCKET_TYPE_STREAM) 00368 { 00369 //Get exclusive access 00370 osAcquireMutex(&netMutex); 00371 00372 //Establish TCP connection 00373 error = tcpConnect(socket, remoteIpAddr, remotePort); 00374 00375 //Release exclusive access 00376 osReleaseMutex(&netMutex); 00377 } 00378 else 00379 #endif 00380 //Connectionless socket? 00381 if(socket->type == SOCKET_TYPE_DGRAM) 00382 { 00383 //Save port number and IP address of the remote host 00384 socket->remoteIpAddr = *remoteIpAddr; 00385 socket->remotePort = remotePort; 00386 //No error to report 00387 error = NO_ERROR; 00388 } 00389 //Raw socket? 00390 else if(socket->type == SOCKET_TYPE_RAW_IP) 00391 { 00392 //Save the IP address of the remote host 00393 socket->remoteIpAddr = *remoteIpAddr; 00394 //No error to report 00395 error = NO_ERROR; 00396 } 00397 //Socket type not supported... 00398 else 00399 { 00400 //Invalid socket type 00401 error = ERROR_INVALID_SOCKET; 00402 } 00403 00404 //Return status code 00405 return error; 00406 } 00407 00408 00409 /** 00410 * @brief Place a socket in the listening state 00411 * 00412 * Place a socket in a state in which it is listening for an incoming connection 00413 * 00414 * @param[in] socket Socket to place in the listening state 00415 * @param[in] backlog backlog The maximum length of the pending connection queue. 00416 * If this parameter is zero, then the default backlog value is used instead 00417 * @return Error code 00418 **/ 00419 00420 error_t socketListen(Socket *socket, uint_t backlog) 00421 { 00422 #if (TCP_SUPPORT == ENABLED) 00423 error_t error; 00424 00425 //Make sure the socket handle is valid 00426 if(socket == NULL) 00427 return ERROR_INVALID_PARAMETER; 00428 //This function shall be used with connection-oriented socket types 00429 if(socket->type != SOCKET_TYPE_STREAM) 00430 return ERROR_INVALID_SOCKET; 00431 00432 //Get exclusive access 00433 osAcquireMutex(&netMutex); 00434 00435 //Start listening for an incoming connection 00436 error = tcpListen(socket, backlog); 00437 00438 //Release exclusive access 00439 osReleaseMutex(&netMutex); 00440 00441 //Return status code 00442 return error; 00443 #else 00444 return ERROR_NOT_IMPLEMENTED; 00445 #endif 00446 } 00447 00448 00449 /** 00450 * @brief Permit an incoming connection attempt on a socket 00451 * @param[in] socket Handle to a socket previously placed in a listening state 00452 * @param[out] clientIpAddr IP address of the client 00453 * @param[out] clientPort Port number used by the client 00454 * @return Handle to the socket in which the actual connection is made 00455 **/ 00456 00457 Socket *socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort) 00458 { 00459 #if (TCP_SUPPORT == ENABLED) 00460 Socket *newSocket; 00461 00462 //Make sure the socket handle is valid 00463 if(socket == NULL) 00464 return NULL; 00465 //This function shall be used with connection-oriented socket types 00466 if(socket->type != SOCKET_TYPE_STREAM) 00467 return NULL; 00468 00469 //Accept an incoming connection attempt 00470 newSocket = tcpAccept(socket, clientIpAddr, clientPort); 00471 00472 //Return a handle to the newly created socket 00473 return newSocket; 00474 #else 00475 return NULL; 00476 #endif 00477 } 00478 00479 00480 /** 00481 * @brief Send data to a connected socket 00482 * @param[in] socket Handle that identifies a connected socket 00483 * @param[in] data Pointer to a buffer containing the data to be transmitted 00484 * @param[in] length Number of data bytes to send 00485 * @param[out] written Actual number of bytes written (optional parameter) 00486 * @param[in] flags Set of flags that influences the behavior of this function 00487 * @return Error code 00488 **/ 00489 00490 error_t socketSend(Socket *socket, const void *data, 00491 size_t length, size_t *written, uint_t flags) 00492 { 00493 //Use default remote IP address for connectionless or raw sockets 00494 return socketSendTo(socket, &socket->remoteIpAddr, 00495 socket->remotePort, data, length, written, flags); 00496 } 00497 00498 00499 /** 00500 * @brief Send a datagram to a specific destination 00501 * @param[in] socket Handle that identifies a socket 00502 * @param[in] destIpAddr IP address of the target host 00503 * @param[in] destPort Target port number 00504 * @param[in] data Pointer to a buffer containing the data to be transmitted 00505 * @param[in] length Number of data bytes to send 00506 * @param[out] written Actual number of bytes written (optional parameter) 00507 * @param[in] flags Set of flags that influences the behavior of this function 00508 * @return Error code 00509 **/ 00510 00511 error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, 00512 const void *data, size_t length, size_t *written, uint_t flags) 00513 { 00514 error_t error; 00515 00516 //No data has been transmitted yet 00517 if(written) 00518 *written = 0; 00519 00520 //Make sure the socket handle is valid 00521 if(socket == NULL) 00522 return ERROR_INVALID_PARAMETER; 00523 00524 //Get exclusive access 00525 osAcquireMutex(&netMutex); 00526 00527 #if (TCP_SUPPORT == ENABLED) 00528 //Connection-oriented socket? 00529 if(socket->type == SOCKET_TYPE_STREAM) 00530 { 00531 //For connection-oriented sockets, target address is ignored 00532 error = tcpSend(socket, data, length, written, flags); 00533 } 00534 else 00535 #endif 00536 #if (UDP_SUPPORT == ENABLED) 00537 //Connectionless socket? 00538 if(socket->type == SOCKET_TYPE_DGRAM) 00539 { 00540 //Send UDP datagram 00541 error = udpSendDatagram(socket, destIpAddr, 00542 destPort, data, length, written); 00543 } 00544 else 00545 #endif 00546 #if (RAW_SOCKET_SUPPORT == ENABLED) 00547 //Raw socket? 00548 if(socket->type == SOCKET_TYPE_RAW_IP) 00549 { 00550 //Send a raw IP packet 00551 error = rawSocketSendIpPacket(socket, destIpAddr, data, length, written); 00552 } 00553 else if(socket->type == SOCKET_TYPE_RAW_ETH) 00554 { 00555 //Send a raw Ethernet packet 00556 error = rawSocketSendEthPacket(socket, data, length, written); 00557 } 00558 else 00559 #endif 00560 //Socket type not supported... 00561 { 00562 //Invalid socket type 00563 error = ERROR_INVALID_SOCKET; 00564 } 00565 00566 //Release exclusive access 00567 osReleaseMutex(&netMutex); 00568 00569 //Return status code 00570 return error; 00571 } 00572 00573 00574 /** 00575 * @brief Receive data from a connected socket 00576 * @param[in] socket Handle that identifies a connected socket 00577 * @param[out] data Buffer where to store the incoming data 00578 * @param[in] size Maximum number of bytes that can be received 00579 * @param[out] received Number of bytes that have been received 00580 * @param[in] flags Set of flags that influences the behavior of this function 00581 * @return Error code 00582 **/ 00583 00584 error_t socketReceive(Socket *socket, void *data, 00585 size_t size, size_t *received, uint_t flags) 00586 { 00587 //For connection-oriented sockets, source and destination addresses are no use 00588 return socketReceiveEx(socket, NULL, NULL, NULL, data, size, received, flags); 00589 } 00590 00591 00592 /** 00593 * @brief Receive a datagram from a connectionless socket 00594 * @param[in] socket Handle that identifies a socket 00595 * @param[out] srcIpAddr Source IP address (optional) 00596 * @param[out] srcPort Source port number (optional) 00597 * @param[out] data Buffer where to store the incoming data 00598 * @param[in] size Maximum number of bytes that can be received 00599 * @param[out] received Number of bytes that have been received 00600 * @param[in] flags Set of flags that influences the behavior of this function 00601 * @return Error code 00602 **/ 00603 00604 error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, 00605 void *data, size_t size, size_t *received, uint_t flags) 00606 { 00607 //Destination address is no use 00608 return socketReceiveEx(socket, srcIpAddr, srcPort, NULL, data, size, received, flags); 00609 } 00610 00611 00612 /** 00613 * @brief Receive a datagram 00614 * @param[in] socket Handle that identifies a socket 00615 * @param[out] srcIpAddr Source IP address (optional) 00616 * @param[out] srcPort Source port number (optional) 00617 * @param[out] destIpAddr Destination IP address (optional) 00618 * @param[out] data Buffer where to store the incoming data 00619 * @param[in] size Maximum number of bytes that can be received 00620 * @param[out] received Number of bytes that have been received 00621 * @param[in] flags Set of flags that influences the behavior of this function 00622 * @return Error code 00623 **/ 00624 00625 error_t socketReceiveEx(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, 00626 IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags) 00627 { 00628 error_t error; 00629 00630 //Make sure the socket handle is valid 00631 if(socket == NULL) 00632 return ERROR_INVALID_PARAMETER; 00633 00634 //Get exclusive access 00635 osAcquireMutex(&netMutex); 00636 00637 #if (TCP_SUPPORT == ENABLED) 00638 //Connection-oriented socket? 00639 if(socket->type == SOCKET_TYPE_STREAM) 00640 { 00641 //Receive data 00642 error = tcpReceive(socket, data, size, received, flags); 00643 00644 //Output parameters 00645 if(srcIpAddr) 00646 *srcIpAddr = socket->remoteIpAddr; 00647 if(srcPort) 00648 *srcPort = socket->remotePort; 00649 if(destIpAddr) 00650 *destIpAddr = socket->localIpAddr; 00651 } 00652 else 00653 #endif 00654 #if (UDP_SUPPORT == ENABLED) 00655 //Connectionless socket? 00656 if(socket->type == SOCKET_TYPE_DGRAM) 00657 { 00658 //Receive UDP datagram 00659 error = udpReceiveDatagram(socket, srcIpAddr, 00660 srcPort, destIpAddr, data, size, received, flags); 00661 } 00662 else 00663 #endif 00664 #if (RAW_SOCKET_SUPPORT == ENABLED) 00665 //Raw socket? 00666 if(socket->type == SOCKET_TYPE_RAW_IP) 00667 { 00668 //Receive a raw IP packet 00669 error = rawSocketReceiveIpPacket(socket, 00670 srcIpAddr, destIpAddr, data, size, received, flags); 00671 } 00672 else if(socket->type == SOCKET_TYPE_RAW_ETH) 00673 { 00674 //Receive a raw Ethernet packet 00675 error = rawSocketReceiveEthPacket(socket, data, size, received, flags); 00676 } 00677 else 00678 #endif 00679 //Socket type not supported... 00680 { 00681 //No data can be read 00682 *received = 0; 00683 //Invalid socket type 00684 error = ERROR_INVALID_SOCKET; 00685 } 00686 00687 //Release exclusive access 00688 osReleaseMutex(&netMutex); 00689 00690 //Return status code 00691 return error; 00692 } 00693 00694 00695 /** 00696 * @brief Retrieve the local address for a given socket 00697 * @param[in] socket Handle that identifies a socket 00698 * @param[out] localIpAddr Local IP address (optional) 00699 * @param[out] localPort Local port number (optional) 00700 * @return Error code 00701 **/ 00702 00703 error_t socketGetLocalAddr(Socket *socket, IpAddr *localIpAddr, uint16_t *localPort) 00704 { 00705 //Make sure the socket handle is valid 00706 if(socket == NULL) 00707 return ERROR_INVALID_PARAMETER; 00708 00709 //Retrieve local IP address 00710 if(localIpAddr != NULL) 00711 *localIpAddr = socket->localIpAddr; 00712 00713 //Retrieve local port number 00714 if(localPort != NULL) 00715 *localPort = socket->localPort; 00716 00717 //Successful processing 00718 return NO_ERROR; 00719 } 00720 00721 00722 /** 00723 * @brief Retrieve the address of the peer to which a socket is connected 00724 * @param[in] socket Handle that identifies a socket 00725 * @param[out] remoteIpAddr IP address of the remote host (optional) 00726 * @param[out] remotePort Remote port number (optional) 00727 * @return Error code 00728 **/ 00729 00730 error_t socketGetRemoteAddr(Socket *socket, IpAddr *remoteIpAddr, uint16_t *remotePort) 00731 { 00732 //Make sure the socket handle is valid 00733 if(socket == NULL) 00734 return ERROR_INVALID_PARAMETER; 00735 00736 //Retrieve local IP address 00737 if(remoteIpAddr != NULL) 00738 *remoteIpAddr = socket->remoteIpAddr; 00739 00740 //Retrieve local port number 00741 if(remotePort != NULL) 00742 *remotePort = socket->remotePort; 00743 00744 //Successful processing 00745 return NO_ERROR; 00746 } 00747 00748 00749 /** 00750 * @brief Disable reception, transmission, or both 00751 * 00752 * Note that socketShutdown() does not close the socket, and resources attached 00753 * to the socket will not be freed until socketClose() is invoked 00754 * 00755 * @param[in] socket Handle to a socket 00756 * @param[in] how Flag that describes what types of operation will no longer be allowed 00757 * @return Error code 00758 **/ 00759 00760 error_t socketShutdown(Socket *socket, uint_t how) 00761 { 00762 #if (TCP_SUPPORT == ENABLED) 00763 error_t error; 00764 00765 //Make sure the socket handle is valid 00766 if(socket == NULL) 00767 return ERROR_INVALID_PARAMETER; 00768 //Make sure the socket type is correct 00769 if(socket->type != SOCKET_TYPE_STREAM) 00770 return ERROR_INVALID_SOCKET; 00771 //Check flags 00772 if((how != SOCKET_SD_SEND) && (how != SOCKET_SD_RECEIVE) && (how != SOCKET_SD_BOTH)) 00773 return ERROR_INVALID_PARAMETER; 00774 00775 //Get exclusive access 00776 osAcquireMutex(&netMutex); 00777 00778 //Graceful shutdown 00779 error = tcpShutdown(socket, how); 00780 00781 //Release exclusive access 00782 osReleaseMutex(&netMutex); 00783 00784 //Return status code 00785 return error; 00786 #else 00787 return ERROR_NOT_IMPLEMENTED; 00788 #endif 00789 } 00790 00791 00792 /** 00793 * @brief Close an existing socket 00794 * @param[in] socket Handle identifying the socket to close 00795 **/ 00796 00797 void socketClose(Socket *socket) 00798 { 00799 //Make sure the socket handle is valid 00800 if(socket == NULL) 00801 return; 00802 00803 //Get exclusive access 00804 osAcquireMutex(&netMutex); 00805 00806 #if (TCP_SUPPORT == ENABLED) 00807 //Connection-oriented socket? 00808 if(socket->type == SOCKET_TYPE_STREAM) 00809 { 00810 //Abort the current TCP connection 00811 tcpAbort(socket); 00812 } 00813 #endif 00814 #if (UDP_SUPPORT == ENABLED || RAW_SOCKET_SUPPORT == ENABLED) 00815 //Connectionless socket or raw socket? 00816 if(socket->type == SOCKET_TYPE_DGRAM || 00817 socket->type == SOCKET_TYPE_RAW_IP || 00818 socket->type == SOCKET_TYPE_RAW_ETH) 00819 { 00820 //Point to the first item in the receive queue 00821 SocketQueueItem *queueItem = socket->receiveQueue; 00822 00823 //Purge the receive queue 00824 while(queueItem) 00825 { 00826 //Keep track of the next item in the queue 00827 SocketQueueItem *nextQueueItem = queueItem->next; 00828 //Free previously allocated memory 00829 memPoolFree(queueItem->buffer); 00830 //Point to the next item 00831 queueItem = nextQueueItem; 00832 } 00833 00834 //Mark the socket as closed 00835 socket->type = SOCKET_TYPE_UNUSED; 00836 } 00837 #endif 00838 00839 //Release exclusive access 00840 osReleaseMutex(&netMutex); 00841 } 00842 00843 00844 /** 00845 * @brief Wait for one of a set of sockets to become ready to perform I/O 00846 * 00847 * The socketPoll function determines the status of one or more sockets, 00848 * waiting if necessary, to perform synchronous I/O 00849 * 00850 * @param[in,out] eventDesc Set of entries specifying the events the user is interested in 00851 * @param[in] size Number of entries in the descriptor set 00852 * @param[in] extEvent External event that can abort the wait if necessary (optional) 00853 * @param[in] timeout Maximum time to wait before returning 00854 * @return Error code 00855 **/ 00856 00857 error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout) 00858 { 00859 uint_t i; 00860 bool_t status; 00861 OsEvent *event; 00862 OsEvent eventObject; 00863 00864 //Check parameters 00865 if(!eventDesc || !size) 00866 return ERROR_INVALID_PARAMETER; 00867 00868 //Try to use the supplied event object to receive notifications 00869 if(!extEvent) 00870 { 00871 //Create an event object only if necessary 00872 if(!osCreateEvent(&eventObject)) 00873 { 00874 //Report an error 00875 return ERROR_OUT_OF_RESOURCES; 00876 } 00877 00878 //Reference to the newly created event 00879 event = &eventObject; 00880 } 00881 else 00882 { 00883 //Reference to the external event 00884 event = extEvent; 00885 } 00886 00887 //Loop through descriptors 00888 for(i = 0; i < size; i++) 00889 { 00890 //Clear event flags 00891 eventDesc[i].eventFlags = 0; 00892 //Subscribe to the requested events 00893 socketRegisterEvents(eventDesc[i].socket, event, eventDesc[i].eventMask); 00894 } 00895 00896 //Block the current task until an event occurs 00897 status = osWaitForEvent(event, timeout); 00898 00899 //Any socket event is in the signaled state? 00900 if(status) 00901 { 00902 //Loop through descriptors 00903 for(i = 0; i < size; i++) 00904 { 00905 //Retrieve event flags for the current socket 00906 socketGetEvents(eventDesc[i].socket, &eventDesc[i].eventFlags); 00907 //Clear unnecessary flags 00908 eventDesc[i].eventFlags &= eventDesc[i].eventMask; 00909 } 00910 } 00911 00912 //Unsubscribe previously registered events 00913 for(i = 0; i < size; i++) 00914 socketUnregisterEvents(eventDesc[i].socket); 00915 00916 //Reset event object before exiting... 00917 osResetEvent(event); 00918 00919 //Release previously allocated resources 00920 if(!extEvent) 00921 osDeleteEvent(&eventObject); 00922 00923 //Return status code 00924 return status ? NO_ERROR : ERROR_TIMEOUT; 00925 } 00926 00927 00928 /** 00929 * @brief Subscribe to the specified socket events 00930 * @param[in] socket Handle that identifies a socket 00931 * @param[in] event Event object used to receive notifications 00932 * @param[in] eventMask Logic OR of the requested socket events 00933 * @return Error code 00934 **/ 00935 00936 error_t socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask) 00937 { 00938 //Make sure the socket handle is valid 00939 if(socket == NULL) 00940 return ERROR_INVALID_PARAMETER; 00941 00942 //Get exclusive access 00943 osAcquireMutex(&netMutex); 00944 00945 //An user event may have been previously registered... 00946 if(socket->userEvent != NULL) 00947 socket->eventMask |= eventMask; 00948 else 00949 socket->eventMask = eventMask; 00950 00951 //Suscribe to get notified of events 00952 socket->userEvent = event; 00953 00954 #if (TCP_SUPPORT == ENABLED) 00955 //Handle TCP specific events 00956 if(socket->type == SOCKET_TYPE_STREAM) 00957 { 00958 tcpUpdateEvents(socket); 00959 } 00960 #endif 00961 #if (UDP_SUPPORT == ENABLED) 00962 //Handle UDP specific events 00963 if(socket->type == SOCKET_TYPE_DGRAM) 00964 { 00965 udpUpdateEvents(socket); 00966 } 00967 #endif 00968 #if (RAW_SOCKET_SUPPORT == ENABLED) 00969 //Handle events that are specific to raw sockets 00970 if(socket->type == SOCKET_TYPE_RAW_IP || 00971 socket->type == SOCKET_TYPE_RAW_ETH) 00972 { 00973 rawSocketUpdateEvents(socket); 00974 } 00975 #endif 00976 00977 //Release exclusive access 00978 osReleaseMutex(&netMutex); 00979 //Successful processing 00980 return NO_ERROR; 00981 } 00982 00983 00984 /** 00985 * @brief Unsubscribe previously registered events 00986 * @param[in] socket Handle that identifies a socket 00987 * @return Error code 00988 **/ 00989 00990 error_t socketUnregisterEvents(Socket *socket) 00991 { 00992 //Make sure the socket handle is valid 00993 if(socket == NULL) 00994 return ERROR_INVALID_PARAMETER; 00995 00996 //Get exclusive access 00997 osAcquireMutex(&netMutex); 00998 00999 //Unsuscribe socket events 01000 socket->userEvent = NULL; 01001 01002 //Release exclusive access 01003 osReleaseMutex(&netMutex); 01004 //Successful processing 01005 return NO_ERROR; 01006 } 01007 01008 01009 /** 01010 * @brief Retrieve event flags for a specified socket 01011 * @param[in] socket Handle that identifies a socket 01012 * @param[out] eventFlags Logic OR of events in the signaled state 01013 * @return Error code 01014 **/ 01015 01016 error_t socketGetEvents(Socket *socket, uint_t *eventFlags) 01017 { 01018 //Make sure the socket handle is valid 01019 if(socket == NULL) 01020 { 01021 //Always return a valid value 01022 *eventFlags = 0; 01023 //Report an error 01024 return ERROR_INVALID_PARAMETER; 01025 } 01026 01027 //Get exclusive access 01028 osAcquireMutex(&netMutex); 01029 01030 //Read event flags for the specified socket 01031 *eventFlags = socket->eventFlags; 01032 01033 //Release exclusive access 01034 osReleaseMutex(&netMutex); 01035 //Successful processing 01036 return NO_ERROR; 01037 } 01038 01039 01040 /** 01041 * @brief Resolve a host name into an IP address 01042 * @param[in] interface Underlying network interface (optional parameter) 01043 * @param[in] name Name of the host to be resolved 01044 * @param[out] ipAddr IP address corresponding to the specified host name 01045 * @param[in] flags Set of flags that influences the behavior of this function 01046 * @return Error code 01047 **/ 01048 01049 error_t getHostByName(NetInterface *interface, 01050 const char_t *name, IpAddr *ipAddr, uint_t flags) 01051 { 01052 error_t error; 01053 01054 //Default address type depends on TCP/IP stack configuration 01055 #if (IPV4_SUPPORT == ENABLED) 01056 HostType type = HOST_TYPE_IPV4; 01057 #elif (IPV6_SUPPORT == ENABLED) 01058 HostType type = HOST_TYPE_IPV6; 01059 #else 01060 HostType type = HOST_TYPE_ANY; 01061 #endif 01062 01063 //Default name resolution protocol depends on TCP/IP stack configuration 01064 #if (DNS_CLIENT_SUPPORT == ENABLED) 01065 HostnameResolver protocol = HOST_NAME_RESOLVER_DNS; 01066 #elif (MDNS_CLIENT_SUPPORT == ENABLED) 01067 HostnameResolver protocol = HOST_NAME_RESOLVER_MDNS; 01068 #elif (NBNS_CLIENT_SUPPORT == ENABLED) 01069 HostnameResolver protocol = HOST_NAME_RESOLVER_NBNS; 01070 #else 01071 HostnameResolver protocol = HOST_NAME_RESOLVER_ANY; 01072 #endif 01073 01074 //Check parameters 01075 if(name == NULL || ipAddr == NULL) 01076 return ERROR_INVALID_PARAMETER; 01077 01078 //Use default network interface? 01079 if(interface == NULL) 01080 interface = netGetDefaultInterface(); 01081 01082 //The specified name can be either an IP or a host name 01083 error = ipStringToAddr(name, ipAddr); 01084 01085 //Perform name resolution if necessary 01086 if(error) 01087 { 01088 //The user may provide a hint to choose between IPv4 and IPv6 01089 if(flags & HOST_TYPE_IPV4) 01090 type = HOST_TYPE_IPV4; 01091 else if(flags & HOST_TYPE_IPV6) 01092 type = HOST_TYPE_IPV6; 01093 01094 //The user may provide a hint to to select the desired protocol to be used 01095 if(flags & HOST_NAME_RESOLVER_DNS) 01096 { 01097 //Use DNS to resolve the specified host name 01098 protocol = HOST_NAME_RESOLVER_DNS; 01099 } 01100 else if(flags & HOST_NAME_RESOLVER_MDNS) 01101 { 01102 //Use mDNS to resolve the specified host name 01103 protocol = HOST_NAME_RESOLVER_MDNS; 01104 } 01105 else if(flags & HOST_NAME_RESOLVER_NBNS) 01106 { 01107 //Use NBNS to resolve the specified host name 01108 protocol = HOST_NAME_RESOLVER_NBNS; 01109 } 01110 else 01111 { 01112 //Retrieve the length of the host name to be resolved 01113 size_t n = strlen(name); 01114 01115 //Select the most suitable protocol 01116 if(n >= 6 && !strcasecmp(name + n - 6, ".local")) 01117 { 01118 #if (MDNS_CLIENT_SUPPORT == ENABLED) 01119 //Use mDNS to resolve the specified host name 01120 protocol = HOST_NAME_RESOLVER_MDNS; 01121 #endif 01122 } 01123 else if(n <= 15 && !strchr(name, '.') && type == HOST_TYPE_IPV4) 01124 { 01125 #if (NBNS_CLIENT_SUPPORT == ENABLED) 01126 //Use NetBIOS Name Service to resolve the specified host name 01127 protocol = HOST_NAME_RESOLVER_NBNS; 01128 #endif 01129 } 01130 } 01131 01132 #if (DNS_CLIENT_SUPPORT == ENABLED) 01133 //Use DNS protocol? 01134 if(protocol == HOST_NAME_RESOLVER_DNS) 01135 { 01136 //Perform host name resolution 01137 error = dnsResolve(interface, name, type, ipAddr); 01138 } 01139 else 01140 #endif 01141 #if (MDNS_CLIENT_SUPPORT == ENABLED) 01142 //Use mDNS protocol? 01143 if(protocol == HOST_NAME_RESOLVER_MDNS) 01144 { 01145 //Perform host name resolution 01146 error = mdnsClientResolve(interface, name, type, ipAddr); 01147 } 01148 else 01149 #endif 01150 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) 01151 //Use NetBIOS Name Service protocol? 01152 if(protocol == HOST_NAME_RESOLVER_NBNS) 01153 { 01154 //Perform host name resolution 01155 error = nbnsResolve(interface, name, ipAddr); 01156 } 01157 else 01158 #endif 01159 //Invalid protocol? 01160 { 01161 //Report an error 01162 error = ERROR_INVALID_PARAMETER; 01163 } 01164 } 01165 01166 //Return status code 01167 return error; 01168 } 01169
Generated on Tue Jul 12 2022 17:10:16 by
