Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
bsd_socket.c
Go to the documentation of this file.
00001 /** 00002 * @file bsd_socket.c 00003 * @brief BSD 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 BSD_SOCKET_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <string.h> 00034 #include "core/net.h" 00035 #include "core/bsd_socket.h" 00036 #include "core/socket.h" 00037 #include "debug.h" 00038 00039 //Check TCP/IP stack configuration 00040 #if (BSD_SOCKET_SUPPORT == ENABLED) 00041 00042 //Common IPv6 addresses 00043 const in6_addr in6addr_any = 00044 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; 00045 00046 const in6_addr in6addr_loopback = 00047 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}; 00048 00049 00050 /** 00051 * @brief Translate error code 00052 * @param[in] error Error code to be translated 00053 * @return BSD error code 00054 **/ 00055 00056 int_t socketTranslateErrorCode(error_t error) 00057 { 00058 int_t ret; 00059 00060 //Translate error code 00061 switch(error) 00062 { 00063 case NO_ERROR: 00064 ret = 0; 00065 break; 00066 case ERROR_TIMEOUT: 00067 ret = EWOULDBLOCK; 00068 break; 00069 case ERROR_INVALID_PARAMETER: 00070 ret = EINVAL; 00071 break; 00072 case ERROR_CONNECTION_RESET: 00073 ret = ECONNRESET; 00074 break; 00075 case ERROR_ALREADY_CONNECTED: 00076 ret = EISCONN; 00077 break; 00078 case ERROR_NOT_CONNECTED: 00079 ret = ENOTCONN; 00080 break; 00081 case ERROR_CONNECTION_CLOSING: 00082 ret = ESHUTDOWN; 00083 break; 00084 case ERROR_CONNECTION_FAILED: 00085 ret = ECONNREFUSED; 00086 break; 00087 default: 00088 ret = EFAULT; 00089 break; 00090 } 00091 00092 //Return BSD status code 00093 return ret; 00094 } 00095 00096 00097 /** 00098 * @brief Create a socket that is bound to a specific transport service provider 00099 * @param[in] family Address family 00100 * @param[in] type Type specification for the new socket 00101 * @param[in] protocol Protocol to be used 00102 * @return On success, a file descriptor for the new socket is returned. 00103 * On failure, SOCKET_ERROR is returned 00104 **/ 00105 00106 int_t socket(int_t family, int_t type, int_t protocol) 00107 { 00108 Socket *sock; 00109 00110 //Check address family 00111 if(family == AF_INET || family == AF_INET6) 00112 { 00113 //Create a socket 00114 sock = socketOpen(type, protocol); 00115 } 00116 else if(family == AF_PACKET) 00117 { 00118 //Create a socket 00119 sock = socketOpen(SOCKET_TYPE_RAW_ETH, ntohs(protocol)); 00120 } 00121 else 00122 { 00123 //The address family is not valid 00124 return SOCKET_ERROR; 00125 } 00126 00127 //Failed to create a new socket? 00128 if(!sock) 00129 { 00130 //Report an error 00131 return SOCKET_ERROR; 00132 } 00133 00134 //Return the socket descriptor 00135 return sock->descriptor; 00136 } 00137 00138 00139 /** 00140 * @brief Associate a local address with a socket 00141 * @param[in] s Descriptor identifying an unbound socket 00142 * @param[in] addr Local address to assign to the bound socket 00143 * @param[in] addrlen Length in bytes of the address 00144 * @return If no error occurs, bind returns SOCKET_SUCCESS. 00145 * Otherwise, it returns SOCKET_ERROR 00146 **/ 00147 00148 int_t bind(int_t s, const sockaddr *addr, socklen_t addrlen) 00149 { 00150 error_t error; 00151 uint16_t port; 00152 IpAddr ipAddr; 00153 Socket *sock; 00154 00155 //Make sure the socket descriptor is valid 00156 if(s < 0 || s >= SOCKET_MAX_COUNT) 00157 { 00158 return SOCKET_ERROR; 00159 } 00160 00161 //Point to the socket structure 00162 sock = &socketTable[s]; 00163 00164 //Check the length of the address 00165 if(addrlen < (socklen_t) sizeof(sockaddr)) 00166 { 00167 //Report an error 00168 sock->errnoCode = EINVAL; 00169 return SOCKET_ERROR; 00170 } 00171 00172 #if (IPV4_SUPPORT == ENABLED) 00173 //IPv4 address? 00174 if(addr->sa_family == AF_INET && addrlen >= (socklen_t) sizeof(sockaddr_in)) 00175 { 00176 //Point to the IPv4 address information 00177 sockaddr_in *sa = (sockaddr_in *) addr; 00178 //Get port number 00179 port = ntohs(sa->sin_port); 00180 00181 //Copy IPv4 address 00182 if(sa->sin_addr.s_addr == INADDR_ANY) 00183 { 00184 ipAddr.length = 0; 00185 ipAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR; 00186 } 00187 else 00188 { 00189 ipAddr.length = sizeof(Ipv4Addr); 00190 ipAddr.ipv4Addr = sa->sin_addr.s_addr; 00191 } 00192 } 00193 else 00194 #endif 00195 #if (IPV6_SUPPORT == ENABLED) 00196 //IPv6 address? 00197 if(addr->sa_family == AF_INET6 && addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00198 { 00199 //Point to the IPv6 address information 00200 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00201 //Get port number 00202 port = ntohs(sa->sin6_port); 00203 00204 //Copy IPv6 address 00205 if(ipv6CompAddr(sa->sin6_addr.s6_addr, &in6addr_any)) 00206 { 00207 ipAddr.length = 0; 00208 ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR; 00209 } 00210 else 00211 { 00212 ipAddr.length = sizeof(Ipv6Addr); 00213 ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr); 00214 } 00215 } 00216 else 00217 #endif 00218 //Invalid address? 00219 { 00220 //Report an error 00221 sock->errnoCode = EINVAL; 00222 return SOCKET_ERROR; 00223 } 00224 00225 //Associate the local address with the socket 00226 error = socketBind(sock, &ipAddr, port); 00227 00228 //Any error to report? 00229 if(error) 00230 { 00231 sock->errnoCode = socketTranslateErrorCode(error); 00232 return SOCKET_ERROR; 00233 } 00234 00235 //Successful processing 00236 return SOCKET_SUCCESS; 00237 } 00238 00239 00240 /** 00241 * @brief Establish a connection to a specified socket 00242 * @param[in] s Descriptor identifying an unconnected socket 00243 * @param[in] addr Address to which the connection should be established 00244 * @param[in] addrlen Length in bytes of the address 00245 * @return If no error occurs, connect returns SOCKET_SUCCESS. 00246 * Otherwise, it returns SOCKET_ERROR 00247 **/ 00248 00249 int_t connect(int_t s, const sockaddr *addr, socklen_t addrlen) 00250 { 00251 error_t error; 00252 uint16_t port; 00253 IpAddr ipAddr; 00254 Socket *sock; 00255 00256 //Make sure the socket descriptor is valid 00257 if(s < 0 || s >= SOCKET_MAX_COUNT) 00258 { 00259 return SOCKET_ERROR; 00260 } 00261 00262 //Point to the socket structure 00263 sock = &socketTable[s]; 00264 00265 //Check the length of the address 00266 if(addrlen < (socklen_t) sizeof(sockaddr)) 00267 { 00268 sock->errnoCode = EINVAL; 00269 return SOCKET_ERROR; 00270 } 00271 00272 #if (IPV4_SUPPORT == ENABLED) 00273 //IPv4 address? 00274 if(addr->sa_family == AF_INET && addrlen >= (socklen_t) sizeof(sockaddr_in)) 00275 { 00276 //Point to the IPv4 address information 00277 sockaddr_in *sa = (sockaddr_in *) addr; 00278 //Get port number 00279 port = ntohs(sa->sin_port); 00280 00281 //Copy IPv4 address 00282 if(sa->sin_addr.s_addr == INADDR_ANY) 00283 { 00284 ipAddr.length = 0; 00285 ipAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR; 00286 } 00287 else 00288 { 00289 ipAddr.length = sizeof(Ipv4Addr); 00290 ipAddr.ipv4Addr = sa->sin_addr.s_addr; 00291 } 00292 } 00293 else 00294 #endif 00295 #if (IPV6_SUPPORT == ENABLED) 00296 //IPv6 address? 00297 if(addr->sa_family == AF_INET6 && addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00298 { 00299 //Point to the IPv6 address information 00300 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00301 //Get port number 00302 port = ntohs(sa->sin6_port); 00303 00304 //Copy IPv6 address 00305 if(ipv6CompAddr(sa->sin6_addr.s6_addr, &in6addr_any)) 00306 { 00307 ipAddr.length = 0; 00308 ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR; 00309 } 00310 else 00311 { 00312 ipAddr.length = sizeof(Ipv6Addr); 00313 ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr); 00314 } 00315 } 00316 else 00317 #endif 00318 //Invalid address? 00319 { 00320 //Report an error 00321 sock->errnoCode = EINVAL; 00322 return SOCKET_ERROR; 00323 } 00324 00325 //Establish connection 00326 error = socketConnect(sock, &ipAddr, port); 00327 00328 //Any error to report? 00329 if(error) 00330 { 00331 sock->errnoCode = socketTranslateErrorCode(error); 00332 return SOCKET_ERROR; 00333 } 00334 00335 //Successful processing 00336 return SOCKET_SUCCESS; 00337 } 00338 00339 00340 /** 00341 * @brief Place a socket in the listening state 00342 * 00343 * Place a socket in a state in which it is listening for an incoming connection 00344 * 00345 * @param[in] s Descriptor identifying a bound, unconnected socket 00346 * @param[in] backlog Maximum length of the queue of pending connections 00347 * @return If no error occurs, listen returns SOCKET_SUCCESS. 00348 * Otherwise, it returns SOCKET_ERROR 00349 **/ 00350 00351 int_t listen(int_t s, int_t backlog) 00352 { 00353 error_t error; 00354 Socket *sock; 00355 00356 //Make sure the socket descriptor is valid 00357 if(s < 0 || s >= SOCKET_MAX_COUNT) 00358 { 00359 return SOCKET_ERROR; 00360 } 00361 00362 //Point to the socket structure 00363 sock = &socketTable[s]; 00364 00365 //Place the socket in the listening state 00366 error = socketListen(sock, backlog); 00367 00368 //Any error to report? 00369 if(error) 00370 { 00371 sock->errnoCode = socketTranslateErrorCode(error); 00372 return SOCKET_ERROR; 00373 } 00374 00375 //Successful processing 00376 return SOCKET_SUCCESS; 00377 } 00378 00379 00380 /** 00381 * @brief Permit an incoming connection attempt on a socket 00382 * @param[in] s Descriptor that identifies a socket in the listening state 00383 * @param[out] addr Address of the connecting entity (optional) 00384 * @param[in,out] addrlen Length in bytes of the address (optional) 00385 * @return If no error occurs, accept returns a descriptor for the new socket. 00386 * Otherwise, it returns SOCKET_ERROR 00387 **/ 00388 00389 int_t accept(int_t s, sockaddr *addr, socklen_t *addrlen) 00390 { 00391 uint16_t port; 00392 IpAddr ipAddr; 00393 Socket *sock; 00394 Socket *newSock; 00395 00396 //Make sure the socket descriptor is valid 00397 if(s < 0 || s >= SOCKET_MAX_COUNT) 00398 { 00399 return SOCKET_ERROR; 00400 } 00401 00402 //Point to the socket structure 00403 sock = &socketTable[s]; 00404 00405 //Permit an incoming connection attempt on a socket 00406 newSock = socketAccept(sock, &ipAddr, &port); 00407 00408 //No connection request is pending in the SYN queue? 00409 if(newSock == NULL) 00410 { 00411 //Report an error 00412 sock->errnoCode = EWOULDBLOCK; 00413 return SOCKET_ERROR; 00414 } 00415 00416 //The address is optional 00417 if(addr != NULL && addrlen != NULL) 00418 { 00419 #if (IPV4_SUPPORT == ENABLED) 00420 //IPv4 address? 00421 if(ipAddr.length == sizeof(Ipv4Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in)) 00422 { 00423 //Point to the IPv4 address information 00424 sockaddr_in *sa = (sockaddr_in *) addr; 00425 00426 //Set address family and port number 00427 sa->sin_family = AF_INET; 00428 sa->sin_port = htons(port); 00429 //Copy IPv4 address 00430 sa->sin_addr.s_addr = ipAddr.ipv4Addr; 00431 00432 //Return the actual length of the address 00433 *addrlen = sizeof(sockaddr_in); 00434 } 00435 else 00436 #endif 00437 #if (IPV6_SUPPORT == ENABLED) 00438 //IPv6 address? 00439 if(ipAddr.length == sizeof(Ipv6Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00440 { 00441 //Point to the IPv6 address information 00442 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00443 00444 //Set address family and port number 00445 sa->sin6_family = AF_INET6; 00446 sa->sin6_port = htons(port); 00447 //Copy IPv6 address 00448 ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr); 00449 00450 //Return the actual length of the address 00451 *addrlen = sizeof(sockaddr_in6); 00452 } 00453 else 00454 #endif 00455 //Invalid address? 00456 { 00457 //Close socket 00458 socketClose(newSock); 00459 //Report an error 00460 sock->errnoCode = EINVAL; 00461 return SOCKET_ERROR; 00462 } 00463 } 00464 00465 //Return the descriptor to the new socket 00466 return newSock->descriptor; 00467 } 00468 00469 00470 /** 00471 * @brief Send data to a connected socket 00472 * @param[in] s Descriptor that identifies a connected socket 00473 * @param[in] data Pointer to a buffer containing the data to be transmitted 00474 * @param[in] length Number of bytes to be transmitted 00475 * @param[in] flags Set of flags that influences the behavior of this function 00476 * @return If no error occurs, send returns the total number of bytes sent, 00477 * which can be less than the number requested to be sent in the 00478 * length parameter. Otherwise, a value of SOCKET_ERROR is returned 00479 **/ 00480 00481 int_t send(int_t s, const void *data, size_t length, int_t flags) 00482 { 00483 error_t error; 00484 size_t written; 00485 Socket *sock; 00486 00487 //Make sure the socket descriptor is valid 00488 if(s < 0 || s >= SOCKET_MAX_COUNT) 00489 { 00490 return SOCKET_ERROR; 00491 } 00492 00493 //Point to the socket structure 00494 sock = &socketTable[s]; 00495 00496 //Send data 00497 error = socketSend(sock, data, length, &written, flags << 8); 00498 00499 //Any error to report? 00500 if(error == ERROR_TIMEOUT) 00501 { 00502 //Check whether some data has been written 00503 if(written > 0) 00504 { 00505 //If a timeout error occurs and some data has been written, the 00506 //count of bytes transferred so far is returned... 00507 } 00508 else 00509 { 00510 //If no data has been written, a value of SOCKET_ERROR is returned 00511 sock->errnoCode = socketTranslateErrorCode(error); 00512 return SOCKET_ERROR; 00513 } 00514 } 00515 else if(error != NO_ERROR) 00516 { 00517 //Otherwise, a value of SOCKET_ERROR is returned 00518 sock->errnoCode = socketTranslateErrorCode(error); 00519 return SOCKET_ERROR; 00520 } 00521 00522 //Return the number of bytes transferred so far 00523 return written; 00524 } 00525 00526 00527 /** 00528 * @brief Send a datagram to a specific destination 00529 * @param[in] s Descriptor that identifies a socket 00530 * @param[in] data Pointer to a buffer containing the data to be transmitted 00531 * @param[in] length Number of bytes to be transmitted 00532 * @param[in] flags Set of flags that influences the behavior of this function 00533 * @param[in] addr Destination address 00534 * @param[in] addrlen Length in bytes of the destination address 00535 * @return If no error occurs, sendto returns the total number of bytes sent, 00536 * which can be less than the number requested to be sent in the 00537 * length parameter. Otherwise, a value of SOCKET_ERROR is returned 00538 **/ 00539 00540 int_t sendto(int_t s, const void *data, size_t length, 00541 int_t flags, const sockaddr *addr, socklen_t addrlen) 00542 { 00543 error_t error; 00544 size_t written; 00545 uint16_t port; 00546 IpAddr ipAddr; 00547 Socket *sock; 00548 00549 //Make sure the socket descriptor is valid 00550 if(s < 0 || s >= SOCKET_MAX_COUNT) 00551 { 00552 return SOCKET_ERROR; 00553 } 00554 00555 //Point to the socket structure 00556 sock = &socketTable[s]; 00557 00558 //Check the length of the address 00559 if(addrlen < (socklen_t) sizeof(sockaddr)) 00560 { 00561 //Report an error 00562 sock->errnoCode = EINVAL; 00563 return SOCKET_ERROR; 00564 } 00565 00566 #if (IPV4_SUPPORT == ENABLED) 00567 //IPv4 address? 00568 if(addr->sa_family == AF_INET && addrlen >= (socklen_t) sizeof(sockaddr_in)) 00569 { 00570 //Point to the IPv4 address information 00571 sockaddr_in *sa = (sockaddr_in *) addr; 00572 00573 //Get port number 00574 port = ntohs(sa->sin_port); 00575 //Copy IPv4 address 00576 ipAddr.length = sizeof(Ipv4Addr); 00577 ipAddr.ipv4Addr = sa->sin_addr.s_addr; 00578 } 00579 else 00580 #endif 00581 #if (IPV6_SUPPORT == ENABLED) 00582 //IPv6 address? 00583 if(addr->sa_family == AF_INET6 && addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00584 { 00585 //Point to the IPv6 address information 00586 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00587 00588 //Get port number 00589 port = ntohs(sa->sin6_port); 00590 //Copy IPv6 address 00591 ipAddr.length = sizeof(Ipv6Addr); 00592 ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr); 00593 } 00594 else 00595 #endif 00596 //Invalid address? 00597 { 00598 //Report an error 00599 sock->errnoCode = EINVAL; 00600 return SOCKET_ERROR; 00601 } 00602 00603 //Send data 00604 error = socketSendTo(sock, &ipAddr, port, data, length, &written, flags << 8); 00605 00606 //Any error to report? 00607 if(error == ERROR_TIMEOUT) 00608 { 00609 //Check whether some data has been written 00610 if(written > 0) 00611 { 00612 //If a timeout error occurs and some data has been written, the 00613 //count of bytes transferred so far is returned... 00614 } 00615 else 00616 { 00617 //If no data has been written, a value of SOCKET_ERROR is returned 00618 sock->errnoCode = socketTranslateErrorCode(error); 00619 return SOCKET_ERROR; 00620 } 00621 } 00622 else if(error != NO_ERROR) 00623 { 00624 //Otherwise, a value of SOCKET_ERROR is returned 00625 sock->errnoCode = socketTranslateErrorCode(error); 00626 return SOCKET_ERROR; 00627 } 00628 00629 //Return the number of bytes transferred so far 00630 return written; 00631 } 00632 00633 00634 /** 00635 * @brief Receive data from a connected socket 00636 * @param[in] s Descriptor that identifies a connected socket 00637 * @param[out] data Buffer where to store the incoming data 00638 * @param[in] size Maximum number of bytes that can be received 00639 * @param[in] flags Set of flags that influences the behavior of this function 00640 * @return If no error occurs, recv returns the number of bytes received. If the 00641 * connection has been gracefully closed, the return value is zero. 00642 * Otherwise, a value of SOCKET_ERROR is returned 00643 **/ 00644 00645 int_t recv(int_t s, void *data, size_t size, int_t flags) 00646 { 00647 error_t error; 00648 size_t received; 00649 Socket *sock; 00650 00651 //Make sure the socket descriptor is valid 00652 if(s < 0 || s >= SOCKET_MAX_COUNT) 00653 { 00654 return SOCKET_ERROR; 00655 } 00656 00657 //Point to the socket structure 00658 sock = &socketTable[s]; 00659 00660 //Receive data 00661 error = socketReceive(sock, data, size, &received, flags << 8); 00662 00663 //Any error to report? 00664 if(error == ERROR_END_OF_STREAM) 00665 { 00666 //If the connection has been gracefully closed, the return value is zero 00667 return 0; 00668 } 00669 else if(error != NO_ERROR) 00670 { 00671 //Otherwise, a value of SOCKET_ERROR is returned 00672 sock->errnoCode = socketTranslateErrorCode(error); 00673 return SOCKET_ERROR; 00674 } 00675 00676 //Return the number of bytes received 00677 return received; 00678 } 00679 00680 00681 /** 00682 * @brief Receive a datagram 00683 * @param[in] s Descriptor that identifies a socket 00684 * @param[out] data Buffer where to store the incoming data 00685 * @param[in] size Maximum number of bytes that can be received 00686 * @param[in] flags Set of flags that influences the behavior of this function 00687 * @param[out] addr Source address upon return (optional) 00688 * @param[in,out] addrlen Length in bytes of the address (optional) 00689 * @return If no error occurs, recvfrom returns the number of bytes received. 00690 * If the connection has been gracefully closed, the return value is 00691 * zero. Otherwise, a value of SOCKET_ERROR is returned 00692 **/ 00693 00694 int_t recvfrom(int_t s, void *data, size_t size, 00695 int_t flags, sockaddr *addr, socklen_t *addrlen) 00696 { 00697 error_t error; 00698 size_t received; 00699 uint16_t port; 00700 IpAddr ipAddr; 00701 Socket *sock; 00702 00703 //Make sure the socket descriptor is valid 00704 if(s < 0 || s >= SOCKET_MAX_COUNT) 00705 { 00706 return SOCKET_ERROR; 00707 } 00708 00709 //Point to the socket structure 00710 sock = &socketTable[s]; 00711 00712 //Receive data 00713 error = socketReceiveFrom(sock, &ipAddr, &port, data, size, &received, flags << 8); 00714 00715 //Any error to report? 00716 if(error == ERROR_END_OF_STREAM) 00717 { 00718 //If the connection has been gracefully closed, the return value is zero 00719 return 0; 00720 } 00721 else if(error != NO_ERROR) 00722 { 00723 //Otherwise, a value of SOCKET_ERROR is returned 00724 sock->errnoCode = socketTranslateErrorCode(error); 00725 return SOCKET_ERROR; 00726 } 00727 00728 //The address is optional 00729 if(addr != NULL && addrlen != NULL) 00730 { 00731 #if (IPV4_SUPPORT == ENABLED) 00732 //IPv4 address? 00733 if(ipAddr.length == sizeof(Ipv4Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in)) 00734 { 00735 //Point to the IPv4 address information 00736 sockaddr_in *sa = (sockaddr_in *) addr; 00737 00738 //Set address family and port number 00739 sa->sin_family = AF_INET; 00740 sa->sin_port = htons(port); 00741 //Copy IPv4 address 00742 sa->sin_addr.s_addr = ipAddr.ipv4Addr; 00743 00744 //Return the actual length of the address 00745 *addrlen = sizeof(sockaddr_in); 00746 } 00747 else 00748 #endif 00749 #if (IPV6_SUPPORT == ENABLED) 00750 //IPv6 address? 00751 if(ipAddr.length == sizeof(Ipv6Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00752 { 00753 //Point to the IPv6 address information 00754 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00755 00756 //Set address family and port number 00757 sa->sin6_family = AF_INET6; 00758 sa->sin6_port = htons(port); 00759 //Copy IPv6 address 00760 ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr); 00761 00762 //Return the actual length of the address 00763 *addrlen = sizeof(sockaddr_in6); 00764 } 00765 else 00766 #endif 00767 //Invalid address? 00768 { 00769 //Report an error 00770 sock->errnoCode = EINVAL; 00771 return SOCKET_ERROR; 00772 } 00773 } 00774 00775 //Return the number of bytes received 00776 return received; 00777 } 00778 00779 00780 /** 00781 * @brief Retrieves the local name for a socket 00782 * @param[in] s Descriptor identifying a socket 00783 * @param[out] addr Address of the socket 00784 * @param[in,out] addrlen Length in bytes of the address 00785 * @return If no error occurs, getsockname returns SOCKET_SUCCESS 00786 * Otherwise, it returns SOCKET_ERROR 00787 **/ 00788 00789 int_t getsockname(int_t s, sockaddr *addr, socklen_t *addrlen) 00790 { 00791 int_t ret; 00792 Socket *sock; 00793 00794 //Make sure the socket descriptor is valid 00795 if(s < 0 || s >= SOCKET_MAX_COUNT) 00796 { 00797 return SOCKET_ERROR; 00798 } 00799 00800 //Point to the socket structure 00801 sock = &socketTable[s]; 00802 00803 //Get exclusive access 00804 osAcquireMutex(&netMutex); 00805 00806 //Check whether the socket has been bound to an address 00807 if(sock->localIpAddr.length != 0) 00808 { 00809 #if (IPV4_SUPPORT == ENABLED) 00810 //IPv4 address? 00811 if(sock->localIpAddr.length == sizeof(Ipv4Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in)) 00812 { 00813 //Point to the IPv4 address information 00814 sockaddr_in *sa = (sockaddr_in *) addr; 00815 00816 //Set address family and port number 00817 sa->sin_family = AF_INET; 00818 sa->sin_port = htons(sock->localPort); 00819 00820 //Copy IPv4 address 00821 sa->sin_addr.s_addr = sock->localIpAddr.ipv4Addr; 00822 00823 //Return the actual length of the address 00824 *addrlen = sizeof(sockaddr_in); 00825 //Successful processing 00826 ret = SOCKET_SUCCESS; 00827 } 00828 else 00829 #endif 00830 #if (IPV6_SUPPORT == ENABLED) 00831 //IPv6 address? 00832 if(sock->localIpAddr.length == sizeof(Ipv6Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00833 { 00834 //Point to the IPv6 address information 00835 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00836 00837 //Set address family and port number 00838 sa->sin6_family = AF_INET6; 00839 sa->sin6_port = htons(sock->localPort); 00840 00841 //Copy IPv6 address 00842 ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->localIpAddr.ipv6Addr); 00843 00844 //Return the actual length of the address 00845 *addrlen = sizeof(sockaddr_in6); 00846 //Successful processing 00847 ret = SOCKET_SUCCESS; 00848 } 00849 else 00850 #endif 00851 { 00852 //The specified length is not valid 00853 sock->errnoCode = EINVAL; 00854 ret = SOCKET_ERROR; 00855 } 00856 } 00857 else 00858 { 00859 //The socket is not bound to any address 00860 sock->errnoCode = ENOTCONN; 00861 ret = SOCKET_ERROR; 00862 } 00863 00864 //Release exclusive access 00865 osReleaseMutex(&netMutex); 00866 00867 //return status code 00868 return ret; 00869 } 00870 00871 00872 /** 00873 * @brief Retrieves the address of the peer to which a socket is connected 00874 * @param[in] s Descriptor identifying a socket 00875 * @param[out] addr Address of the peer 00876 * @param[in,out] addrlen Length in bytes of the address 00877 * @return If no error occurs, getpeername returns SOCKET_SUCCESS 00878 * Otherwise, it returns SOCKET_ERROR 00879 **/ 00880 00881 int_t getpeername(int_t s, sockaddr *addr, socklen_t *addrlen) 00882 { 00883 int_t ret; 00884 Socket *sock; 00885 00886 //Make sure the socket descriptor is valid 00887 if(s < 0 || s >= SOCKET_MAX_COUNT) 00888 { 00889 return SOCKET_ERROR; 00890 } 00891 00892 //Point to the socket structure 00893 sock = &socketTable[s]; 00894 00895 //Get exclusive access 00896 osAcquireMutex(&netMutex); 00897 00898 //Check whether the socket is connected to a peer 00899 if(sock->remoteIpAddr.length != 0) 00900 { 00901 #if (IPV4_SUPPORT == ENABLED) 00902 //IPv4 address? 00903 if(sock->remoteIpAddr.length == sizeof(Ipv4Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in)) 00904 { 00905 //Point to the IPv4 address information 00906 sockaddr_in *sa = (sockaddr_in *) addr; 00907 00908 //Set address family and port number 00909 sa->sin_family = AF_INET; 00910 sa->sin_port = htons(sock->remotePort); 00911 00912 //Copy IPv4 address 00913 sa->sin_addr.s_addr = sock->remoteIpAddr.ipv4Addr; 00914 00915 //Return the actual length of the address 00916 *addrlen = sizeof(sockaddr_in); 00917 //Successful processing 00918 ret = SOCKET_SUCCESS; 00919 } 00920 else 00921 #endif 00922 #if (IPV6_SUPPORT == ENABLED) 00923 //IPv6 address? 00924 if(sock->remoteIpAddr.length == sizeof(Ipv6Addr) && *addrlen >= (socklen_t) sizeof(sockaddr_in6)) 00925 { 00926 //Point to the IPv6 address information 00927 sockaddr_in6 *sa = (sockaddr_in6 *) addr; 00928 00929 //Set address family and port number 00930 sa->sin6_family = AF_INET6; 00931 sa->sin6_port = htons(sock->remotePort); 00932 00933 //Copy IPv6 address 00934 ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->remoteIpAddr.ipv6Addr); 00935 00936 //Return the actual length of the address 00937 *addrlen = sizeof(sockaddr_in6); 00938 //Successful processing 00939 ret = SOCKET_SUCCESS; 00940 } 00941 else 00942 #endif 00943 { 00944 //The specified length is not valid 00945 sock->errnoCode = EINVAL; 00946 ret = SOCKET_ERROR; 00947 } 00948 } 00949 else 00950 { 00951 //The socket is not connected to any peer 00952 sock->errnoCode = ENOTCONN; 00953 ret = SOCKET_ERROR; 00954 } 00955 00956 //Release exclusive access 00957 osReleaseMutex(&netMutex); 00958 00959 //return status code 00960 return ret; 00961 } 00962 00963 00964 /** 00965 * @brief The setsockopt function sets a socket option 00966 * @param[in] s Descriptor that identifies a socket 00967 * @param[in] level The level at which the option is defined 00968 * @param[in] optname The socket option for which the value is to be set 00969 * @param[in] optval A pointer to the buffer in which the value for the requested option is specified 00970 * @param[in] optlen The size, in bytes, of the buffer pointed to by the optval parameter 00971 * @return If no error occurs, setsockopt returns SOCKET_SUCCESS 00972 * Otherwise, it returns SOCKET_ERROR 00973 **/ 00974 00975 int_t setsockopt(int_t s, int_t level, int_t optname, 00976 const void *optval, socklen_t optlen) 00977 { 00978 int_t ret; 00979 int_t *val; 00980 timeval *t; 00981 Socket *sock; 00982 00983 //Make sure the socket descriptor is valid 00984 if(s < 0 || s >= SOCKET_MAX_COUNT) 00985 { 00986 return SOCKET_ERROR; 00987 } 00988 00989 //Point to the socket structure 00990 sock = &socketTable[s]; 00991 00992 //Make sure the option is valid 00993 if(optval != NULL) 00994 { 00995 //Level at which the option is defined? 00996 if(level == SOL_SOCKET) 00997 { 00998 //Check option type 00999 switch(optname) 01000 { 01001 //The socket can be bound to an address which is already in use 01002 case SO_REUSEADDR: 01003 //Ignore the specified option 01004 ret = SOCKET_SUCCESS; 01005 //We are done 01006 break; 01007 01008 //Allow transmission and receipt of broadcast messages 01009 case SO_BROADCAST: 01010 //Ignore the specified option 01011 ret = SOCKET_SUCCESS; 01012 //We are done 01013 break; 01014 01015 //Set send buffer size 01016 case SO_SNDBUF: 01017 //Check the length of the option 01018 if(optlen >= (socklen_t) sizeof(int_t)) 01019 { 01020 //Cast the option value to the relevant type 01021 val = (int_t *) optval; 01022 //Adjust the size of the send buffer 01023 socketSetTxBufferSize(sock, *val); 01024 //Successful processing 01025 ret = SOCKET_SUCCESS; 01026 } 01027 else 01028 { 01029 //The option length is not valid 01030 sock->errnoCode = EFAULT; 01031 ret = SOCKET_ERROR; 01032 } 01033 01034 //We are done 01035 break; 01036 01037 //Set receive buffer size 01038 case SO_RCVBUF: 01039 //Check the length of the option 01040 if(optlen >= (socklen_t) sizeof(int_t)) 01041 { 01042 //Cast the option value to the relevant type 01043 val = (int_t *) optval; 01044 //Adjust the size of the receive buffer 01045 socketSetRxBufferSize(sock, *val); 01046 //Successful processing 01047 ret = SOCKET_SUCCESS; 01048 } 01049 else 01050 { 01051 //The option length is not valid 01052 sock->errnoCode = EFAULT; 01053 ret = SOCKET_ERROR; 01054 } 01055 01056 //We are done 01057 break; 01058 01059 //Set send timeout or receive timeout 01060 case SO_SNDTIMEO: 01061 case SO_RCVTIMEO: 01062 //Check the length of the option 01063 if(optlen >= (socklen_t) sizeof(timeval)) 01064 { 01065 //Cast the option value to the relevant type 01066 t = (timeval *) optval; 01067 01068 //If the specified value is of zero, I/O operations shall not time out 01069 if(!t->tv_sec && !t->tv_usec) 01070 socketSetTimeout(sock, INFINITE_DELAY); 01071 else 01072 socketSetTimeout(sock, t->tv_sec * 1000 + t->tv_usec / 1000); 01073 01074 //Successful processing 01075 ret = SOCKET_SUCCESS; 01076 } 01077 else 01078 { 01079 //The option length is not valid 01080 sock->errnoCode = EFAULT; 01081 ret = SOCKET_ERROR; 01082 } 01083 01084 //We are done 01085 break; 01086 01087 //Unknown option 01088 default: 01089 //Report an error 01090 sock->errnoCode = ENOPROTOOPT; 01091 ret = SOCKET_ERROR; 01092 break; 01093 } 01094 } 01095 else 01096 { 01097 //The specified level is not valid 01098 sock->errnoCode = EINVAL; 01099 ret = SOCKET_ERROR; 01100 } 01101 } 01102 else 01103 { 01104 //The option is not valid 01105 sock->errnoCode = EFAULT; 01106 ret = SOCKET_ERROR; 01107 } 01108 01109 //return status code 01110 return ret; 01111 } 01112 01113 01114 /** 01115 * @brief The getsockopt function retrieves a socket option 01116 * @param[in] s Descriptor that identifies a socket 01117 * @param[in] level The level at which the option is defined 01118 * @param[in] optname The socket option for which the value is to be retrieved 01119 * @param[out] optval A pointer to the buffer in which the value for the requested option is to be returned 01120 * @param[in,out] optlen The size, in bytes, of the buffer pointed to by the optval parameter 01121 * @return If no error occurs, getsockopt returns SOCKET_SUCCESS 01122 * Otherwise, it returns SOCKET_ERROR 01123 **/ 01124 01125 int_t getsockopt(int_t s, int_t level, int_t optname, 01126 void *optval, socklen_t *optlen) 01127 { 01128 int_t ret; 01129 int_t *val; 01130 timeval *t; 01131 Socket *sock; 01132 01133 //Make sure the socket descriptor is valid 01134 if(s < 0 || s >= SOCKET_MAX_COUNT) 01135 { 01136 return SOCKET_ERROR; 01137 } 01138 01139 //Point to the socket structure 01140 sock = &socketTable[s]; 01141 01142 //Get exclusive access 01143 osAcquireMutex(&netMutex); 01144 01145 //Make sure the option is valid 01146 if(optval != NULL) 01147 { 01148 //Level at which the option is defined? 01149 if(level == SOL_SOCKET) 01150 { 01151 //Check option type 01152 switch(optname) 01153 { 01154 #if (TCP_SUPPORT == ENABLED) 01155 //Get send buffer size 01156 case SO_SNDBUF: 01157 //Check the length of the option 01158 if(*optlen >= (socklen_t) sizeof(int_t)) 01159 { 01160 //Cast the option value to the relevant type 01161 val = (int_t *) optval; 01162 //Return the size of the send buffer 01163 *val = sock->txBufferSize; 01164 //Return the actual length of the option 01165 *optlen = sizeof(int_t); 01166 //Successful processing 01167 ret = SOCKET_SUCCESS; 01168 } 01169 else 01170 { 01171 //The option length is not valid 01172 sock->errnoCode = EFAULT; 01173 ret = SOCKET_ERROR; 01174 } 01175 01176 //We are done 01177 break; 01178 01179 //Get receive buffer size 01180 case SO_RCVBUF: 01181 //Check the length of the option 01182 if(*optlen >= (socklen_t) sizeof(int_t)) 01183 { 01184 //Cast the option value to the relevant type 01185 val = (int_t *) optval; 01186 //Return the size of the receive buffer 01187 *val = sock->rxBufferSize; 01188 //Return the actual length of the option 01189 *optlen = sizeof(int_t); 01190 //Successful processing 01191 ret = SOCKET_SUCCESS; 01192 } 01193 else 01194 { 01195 //The option length is not valid 01196 sock->errnoCode = EFAULT; 01197 ret = SOCKET_ERROR; 01198 } 01199 01200 //We are done 01201 break; 01202 #endif 01203 //Get send timeout or receive timeout 01204 case SO_SNDTIMEO: 01205 case SO_RCVTIMEO: 01206 //Check the length of the option 01207 if(*optlen >= (socklen_t) sizeof(timeval)) 01208 { 01209 //Cast the option value to the relevant type 01210 t = (timeval *) optval; 01211 01212 //Return the timeout value 01213 if(sock->timeout == INFINITE_DELAY) 01214 { 01215 t->tv_sec = 0; 01216 t->tv_usec = 0; 01217 } 01218 else 01219 { 01220 t->tv_sec = sock->timeout / 1000; 01221 t->tv_usec = (sock->timeout % 1000) * 1000; 01222 } 01223 01224 //Return the actual length of the option 01225 *optlen = sizeof(timeval); 01226 //Successful processing 01227 ret = SOCKET_SUCCESS; 01228 } 01229 else 01230 { 01231 //The option length is not valid 01232 sock->errnoCode = EFAULT; 01233 ret = SOCKET_ERROR; 01234 } 01235 01236 //We are done 01237 break; 01238 01239 //Get error status 01240 case SO_ERROR: 01241 //Check the length of the option 01242 if(*optlen >= (socklen_t) sizeof(int_t)) 01243 { 01244 //Cast the option value to the relevant type 01245 val = (int_t *) optval; 01246 //Return the error code 01247 *val = sock->errnoCode; 01248 //Return the actual length of the option 01249 *optlen = sizeof(int_t); 01250 //Successful processing 01251 ret = SOCKET_SUCCESS; 01252 } 01253 else 01254 { 01255 //The option length is not valid 01256 sock->errnoCode = EFAULT; 01257 ret = SOCKET_ERROR; 01258 } 01259 01260 //We are done 01261 break; 01262 01263 //Unknown option 01264 default: 01265 //Report an error 01266 sock->errnoCode = ENOPROTOOPT; 01267 ret = SOCKET_ERROR; 01268 break; 01269 } 01270 } 01271 else 01272 { 01273 //The specified level is not valid 01274 sock->errnoCode = EINVAL; 01275 ret = SOCKET_ERROR; 01276 } 01277 } 01278 else 01279 { 01280 //The option is not valid 01281 sock->errnoCode = EFAULT; 01282 ret = SOCKET_ERROR; 01283 } 01284 01285 //Release exclusive access 01286 osReleaseMutex(&netMutex); 01287 01288 //return status code 01289 return ret; 01290 } 01291 01292 01293 /** 01294 * @brief Control the I/O mode of a socket 01295 * @param[in] s Descriptor that identifies a socket 01296 * @param[in] cmd A command to perform on the socket 01297 * @param[in,out] arg A pointer to a parameter 01298 * @return If no error occurs, setsockopt returns SOCKET_SUCCESS 01299 * Otherwise, it returns SOCKET_ERROR 01300 **/ 01301 01302 int_t ioctlsocket(int_t s, uint32_t cmd, void *arg) 01303 { 01304 int_t ret; 01305 int_t *val; 01306 Socket *sock; 01307 01308 //Make sure the socket descriptor is valid 01309 if(s < 0 || s >= SOCKET_MAX_COUNT) 01310 { 01311 return SOCKET_ERROR; 01312 } 01313 01314 //Point to the socket structure 01315 sock = &socketTable[s]; 01316 01317 //Get exclusive access 01318 osAcquireMutex(&netMutex); 01319 01320 //Make sure the parameter is valid 01321 if(arg != NULL) 01322 { 01323 //Check command type 01324 switch(cmd) 01325 { 01326 #if (TCP_SUPPORT == ENABLED) 01327 //Get the number of characters waiting to be read 01328 case FIONREAD: 01329 //Cast the parameter to the relevant type 01330 val = (int_t *) arg; 01331 //Return the number of characters in the receive buffer 01332 *val = sock->rcvUser; 01333 //Successful processing 01334 ret = SOCKET_SUCCESS; 01335 break; 01336 #endif 01337 //Enable or disable non-blocking mode 01338 case FIONBIO: 01339 //Cast the parameter to the relevant type 01340 val = (int_t *) arg; 01341 //Enable blocking or non-blocking operation 01342 sock->timeout = (*val != 0) ? 0 : INFINITE_DELAY; 01343 //Successful processing 01344 ret = SOCKET_SUCCESS; 01345 break; 01346 01347 //Unknown command? 01348 default: 01349 //Report an error 01350 sock->errnoCode = EINVAL; 01351 ret = SOCKET_ERROR; 01352 break; 01353 } 01354 } 01355 else 01356 { 01357 //The parameter is not valid 01358 sock->errnoCode = EFAULT; 01359 ret = SOCKET_ERROR; 01360 } 01361 01362 //Release exclusive access 01363 osReleaseMutex(&netMutex); 01364 01365 //return status code 01366 return ret; 01367 } 01368 01369 01370 /** 01371 * @brief Perform specific operation 01372 * @param[in] s Descriptor that identifies a socket 01373 * @param[in] cmd A command to perform on the socket 01374 * @param[in,out] arg A pointer to a parameter 01375 * @return If no error occurs, setsockopt returns SOCKET_SUCCESS 01376 * Otherwise, it returns SOCKET_ERROR 01377 **/ 01378 01379 int_t fcntl(int_t s, int_t cmd, void *arg) 01380 { 01381 int_t ret; 01382 int_t *flags; 01383 Socket *sock; 01384 01385 //Make sure the socket descriptor is valid 01386 if(s < 0 || s >= SOCKET_MAX_COUNT) 01387 { 01388 return SOCKET_ERROR; 01389 } 01390 01391 //Point to the socket structure 01392 sock = &socketTable[s]; 01393 01394 //Get exclusive access 01395 osAcquireMutex(&netMutex); 01396 01397 //Make sure the parameter is valid 01398 if(arg != NULL) 01399 { 01400 //Check command type 01401 switch(cmd) 01402 { 01403 //Get the file status flags? 01404 case F_GETFL: 01405 //Cast the parameter to the relevant type 01406 flags = (int_t *) arg; 01407 //Check whether non-blocking mode is currently enabled 01408 *flags = (sock->timeout == 0) ? O_NONBLOCK : 0; 01409 //Successful processing 01410 ret = SOCKET_SUCCESS; 01411 break; 01412 01413 //Set the file status flags? 01414 case F_SETFL: 01415 //Cast the parameter to the relevant type 01416 flags = (int_t *) arg; 01417 //Enable blocking or non-blocking operation 01418 sock->timeout = (*flags & O_NONBLOCK) ? 0 : INFINITE_DELAY; 01419 //Successful processing 01420 ret = SOCKET_SUCCESS; 01421 break; 01422 01423 //Unknown command? 01424 default: 01425 //Report an error 01426 sock->errnoCode = EINVAL; 01427 ret = SOCKET_ERROR; 01428 break; 01429 } 01430 } 01431 else 01432 { 01433 //Report an error 01434 sock->errnoCode = EFAULT; 01435 ret = SOCKET_ERROR; 01436 } 01437 01438 //Release exclusive access 01439 osReleaseMutex(&netMutex); 01440 01441 //return status code 01442 return ret; 01443 } 01444 01445 01446 /** 01447 * @brief The shutdown function disables sends or receives on a socket 01448 * @param[in] s Descriptor that identifies a socket 01449 * @param[in] how A flag that describes what types of operation will no longer be allowed 01450 * @return If no error occurs, shutdown returns SOCKET_SUCCESS 01451 * Otherwise, it returns SOCKET_ERROR 01452 **/ 01453 01454 int_t shutdown(int_t s, int_t how) 01455 { 01456 error_t error; 01457 Socket *sock; 01458 01459 //Make sure the socket descriptor is valid 01460 if(s < 0 || s >= SOCKET_MAX_COUNT) 01461 { 01462 return SOCKET_ERROR; 01463 } 01464 01465 //Point to the socket structure 01466 sock = &socketTable[s]; 01467 01468 //Shut down socket 01469 error = socketShutdown(sock, how); 01470 01471 //Any error to report? 01472 if(error) 01473 { 01474 sock->errnoCode = socketTranslateErrorCode(error); 01475 return SOCKET_ERROR; 01476 } 01477 01478 //Successful processing 01479 return SOCKET_SUCCESS; 01480 } 01481 01482 01483 /** 01484 * @brief The closesocket function closes an existing socket 01485 * @param[in] s Descriptor that identifies a socket 01486 * @return If no error occurs, closesocket returns SOCKET_SUCCESS 01487 * Otherwise, it returns SOCKET_ERROR 01488 **/ 01489 01490 int_t closesocket(int_t s) 01491 { 01492 Socket *sock; 01493 01494 //Make sure the socket descriptor is valid 01495 if(s < 0 || s >= SOCKET_MAX_COUNT) 01496 { 01497 return SOCKET_ERROR; 01498 } 01499 01500 //Point to the socket structure 01501 sock = &socketTable[s]; 01502 01503 //Close socket 01504 socketClose(sock); 01505 01506 //Successful processing 01507 return SOCKET_SUCCESS; 01508 } 01509 01510 01511 /** 01512 * @brief Determine the status of one or more sockets 01513 * 01514 * The select function determines the status of one or more sockets, 01515 * waiting if necessary, to perform synchronous I/O 01516 * 01517 * @param[in] nfds Unused parameter included only for compatibility with Berkeley socket 01518 * @param[in,out] readfds An optional pointer to a set of sockets to be checked for readability 01519 * @param[in,out] writefds An optional pointer to a set of sockets to be checked for writability 01520 * @param[in,out] exceptfds An optional pointer to a set of sockets to be checked for errors 01521 * @param[in] timeout The maximum time for select to wait. Set the timeout 01522 * parameter to null for blocking operations 01523 * @return The select function returns the total number of socket handles that 01524 * are ready and contained in the fd_set structures, zero if the time 01525 * limit expired, or SOCKET_ERROR if an error occurred 01526 **/ 01527 01528 int_t select(int_t nfds, fd_set *readfds, fd_set *writefds, 01529 fd_set *exceptfds, const timeval *timeout) 01530 { 01531 int_t i; 01532 int_t j; 01533 int_t n; 01534 int_t s; 01535 systime_t time; 01536 uint_t eventMask; 01537 uint_t eventFlags; 01538 OsEvent event; 01539 fd_set *fds; 01540 01541 //Parse all the descriptor sets 01542 for(i = 0; i < 3; i ++) 01543 { 01544 //Select the suitable descriptor set 01545 switch(i) 01546 { 01547 case 0: 01548 //Set of sockets to be checked for readability 01549 fds = readfds; 01550 break; 01551 case 1: 01552 //Set of sockets to be checked for writability 01553 fds = writefds; 01554 break; 01555 default: 01556 //Set of sockets to be checked for errors 01557 fds = exceptfds; 01558 break; 01559 } 01560 01561 //Each descriptor is optional and may be omitted 01562 if(fds != NULL) 01563 { 01564 //Parse the current set of sockets 01565 for(j = 0; j < fds->fd_count; j++) 01566 { 01567 //Invalid socket descriptor? 01568 if(fds->fd_array[j] < 0 || fds->fd_array[j] >= SOCKET_MAX_COUNT) 01569 { 01570 //Report an error 01571 return SOCKET_ERROR; 01572 } 01573 } 01574 } 01575 } 01576 01577 //Create an event object to get notified of socket events 01578 if(!osCreateEvent(&event)) 01579 { 01580 //Failed to create event 01581 return SOCKET_ERROR; 01582 } 01583 01584 //Parse all the descriptor sets 01585 for(i = 0; i < 3; i ++) 01586 { 01587 //Select the suitable descriptor set 01588 switch(i) 01589 { 01590 case 0: 01591 //Set of sockets to be checked for readability 01592 fds = readfds; 01593 eventMask = SOCKET_EVENT_RX_READY; 01594 break; 01595 case 1: 01596 //Set of sockets to be checked for writability 01597 fds = writefds; 01598 eventMask = SOCKET_EVENT_TX_READY; 01599 break; 01600 default: 01601 //Set of sockets to be checked for errors 01602 fds = exceptfds; 01603 eventMask = SOCKET_EVENT_CLOSED; 01604 break; 01605 } 01606 01607 //Each descriptor is optional and may be omitted 01608 if(fds != NULL) 01609 { 01610 //Parse the current set of sockets 01611 for(j = 0; j < fds->fd_count; j++) 01612 { 01613 //Get the descriptor associated with the current entry 01614 s = fds->fd_array[j]; 01615 //Subscribe to the requested events 01616 socketRegisterEvents(&socketTable[s], &event, eventMask); 01617 } 01618 } 01619 } 01620 01621 //Retrieve timeout value 01622 if(timeout != NULL) 01623 time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; 01624 else 01625 time = INFINITE_DELAY; 01626 01627 //Block the current task until an event occurs 01628 osWaitForEvent(&event, time); 01629 01630 //Count the number of events in the signaled state 01631 n = 0; 01632 01633 //Parse all the descriptor sets 01634 for(i = 0; i < 3; i ++) 01635 { 01636 //Select the suitable descriptor set 01637 switch(i) 01638 { 01639 case 0: 01640 //Set of sockets to be checked for readability 01641 fds = readfds; 01642 eventMask = SOCKET_EVENT_RX_READY; 01643 break; 01644 case 1: 01645 //Set of sockets to be checked for writability 01646 fds = writefds; 01647 eventMask = SOCKET_EVENT_TX_READY; 01648 break; 01649 default: 01650 //Set of sockets to be checked for errors 01651 fds = exceptfds; 01652 eventMask = SOCKET_EVENT_CLOSED; 01653 break; 01654 } 01655 01656 //Each descriptor is optional and may be omitted 01657 if(fds != NULL) 01658 { 01659 //Parse the current set of sockets 01660 for(j = 0; j < fds->fd_count; ) 01661 { 01662 //Get the descriptor associated with the current entry 01663 s = fds->fd_array[j]; 01664 //Retrieve event flags for the current socket 01665 socketGetEvents(&socketTable[s], &eventFlags); 01666 //Unsubscribe previously registered events 01667 socketUnregisterEvents(&socketTable[s]); 01668 01669 //Event flag is set? 01670 if(eventFlags & eventMask) 01671 { 01672 //Track the number of events in the signaled state 01673 n++; 01674 //Jump to the next socket descriptor 01675 j++; 01676 } 01677 else 01678 { 01679 //Remove descriptor from the current set 01680 selectFdClr(fds, s); 01681 } 01682 } 01683 } 01684 } 01685 01686 //Delete event object 01687 osDeleteEvent(&event); 01688 //Return the number of events in the signaled state 01689 return n; 01690 } 01691 01692 01693 /** 01694 * @brief Initializes a descriptor set 01695 * @param[in] fds Pointer to a descriptor set 01696 **/ 01697 01698 void selectFdZero(fd_set *fds) 01699 { 01700 //Reset the descriptor count 01701 fds->fd_count = 0; 01702 } 01703 01704 01705 /** 01706 * @brief Add a descriptor to an existing set 01707 * @param[in] fds Pointer to a descriptor set 01708 * @param[in] s Descriptor that identifies the socket to add 01709 **/ 01710 01711 void selectFdSet(fd_set *fds, int_t s) 01712 { 01713 int_t i; 01714 01715 //Loop through descriptors 01716 for(i = 0; i < fds->fd_count; i++) 01717 { 01718 //The specified descriptor is already set? 01719 if(fds->fd_array[i] == s) 01720 return; 01721 } 01722 01723 //Ensure the descriptor set is not full 01724 if(i < FD_SETSIZE) 01725 { 01726 //The specified descriptor can be safely added 01727 fds->fd_array[i] = s; 01728 //Adjust the size of the descriptor set 01729 fds->fd_count++; 01730 } 01731 } 01732 01733 01734 /** 01735 * @brief Remove a descriptor from an existing set 01736 * @param[in] fds Pointer to a descriptor set 01737 * @param[in] s Descriptor that identifies the socket to remove 01738 **/ 01739 01740 void selectFdClr(fd_set *fds, int_t s) 01741 { 01742 int_t i; 01743 int_t j; 01744 01745 //Loop through descriptors 01746 for(i = 0; i < fds->fd_count; i++) 01747 { 01748 //Specified descriptor found? 01749 if(fds->fd_array[i] == s) 01750 { 01751 //Adjust the size of the descriptor set 01752 fds->fd_count--; 01753 01754 //Remove the entry from the descriptor set 01755 for(j = i; j < fds->fd_count; j++) 01756 fds->fd_array[j] = fds->fd_array[j + 1]; 01757 01758 //Return immediately 01759 return; 01760 } 01761 } 01762 } 01763 01764 01765 /** 01766 * @brief Check whether a descriptor is set 01767 * @param[in] fds Pointer to a descriptor set 01768 * @param[in] s Descriptor that identifies the socket to test 01769 * @return Nonzero if s is a member of the set. Otherwise, zero 01770 **/ 01771 01772 int_t selectFdIsSet(fd_set *fds, int_t s) 01773 { 01774 int_t i; 01775 01776 //Loop through descriptors 01777 for(i = 0; i < fds->fd_count; i++) 01778 { 01779 //Check whether the specified descriptor is set 01780 if(fds->fd_array[i] == s) 01781 return TRUE; 01782 } 01783 01784 //The specified descriptor is not currently set 01785 return FALSE; 01786 } 01787 01788 01789 /** 01790 * @brief Retrieve host address corresponding to a host name 01791 * @param[in] name Name of the host to resolve 01792 * @param[out] info Address of the specified host 01793 * @return If no error occurs, gethostbyname returns 0. Otherwise 01794 * it returns an appropriate error code 01795 **/ 01796 01797 int_t gethostbyname(const char_t *name, hostent *info) 01798 { 01799 error_t error; 01800 IpAddr ipAddr; 01801 01802 //Check input parameters 01803 if(name == NULL || info == NULL) 01804 return ERROR_INVALID_PARAMETER; 01805 01806 //Resolve host address 01807 error = getHostByName(NULL, name, &ipAddr, 0); 01808 //Address resolution failed? 01809 if(error) 01810 return error; 01811 01812 #if (IPV4_SUPPORT == ENABLED) 01813 //IPv4 address? 01814 if(ipAddr.length == sizeof(Ipv4Addr)) 01815 { 01816 //Set address family 01817 info->h_addrtype = AF_INET; 01818 //Copy IPv4 address 01819 info->h_length = sizeof(Ipv4Addr); 01820 ipv4CopyAddr(info->h_addr, &ipAddr.ipv4Addr); 01821 } 01822 else 01823 #endif 01824 #if (IPV6_SUPPORT == ENABLED) 01825 //IPv6 address? 01826 if(ipAddr.length == sizeof(Ipv6Addr)) 01827 { 01828 //Set address family 01829 info->h_addrtype = AF_INET6; 01830 //Copy IPv6 address 01831 info->h_length = sizeof(Ipv6Addr); 01832 ipv6CopyAddr(info->h_addr, &ipAddr.ipv6Addr); 01833 } 01834 else 01835 #endif 01836 //Invalid address? 01837 { 01838 //Report an error 01839 return ERROR_FAILURE; 01840 } 01841 01842 //Successful processing 01843 return NO_ERROR; 01844 } 01845 01846 01847 /** 01848 * @brief Convert a dot-decimal string into binary data in network byte order 01849 * @param[in] cp NULL-terminated string representing the IPv4 address 01850 * @return Binary data in network byte order 01851 **/ 01852 01853 in_addr_t inet_addr(const char_t *cp) 01854 { 01855 #if (IPV4_SUPPORT == ENABLED) 01856 error_t error; 01857 Ipv4Addr ipv4Addr; 01858 01859 //Convert a dot-decimal string to a binary IPv4 address 01860 error = ipv4StringToAddr(cp, &ipv4Addr); 01861 01862 //Check status code 01863 if(error) 01864 { 01865 //The input is invalid 01866 return INADDR_NONE; 01867 } 01868 else 01869 { 01870 //Return the binary representation 01871 return ipv4Addr; 01872 } 01873 #else 01874 //IPv4 is not implemented 01875 return INADDR_NONE; 01876 #endif 01877 } 01878 01879 01880 /** 01881 * @brief Convert a dot-decimal string into binary form 01882 * @param[in] cp NULL-terminated string representing the IPv4 address 01883 * @param[out] inp Binary data in network byte order 01884 * @return The function returns non-zero if the address is valid, zero if not 01885 **/ 01886 01887 int_t inet_aton(const char_t *cp, in_addr *inp) 01888 { 01889 #if (IPV4_SUPPORT == ENABLED) 01890 error_t error; 01891 Ipv4Addr ipv4Addr; 01892 01893 //Convert a dot-decimal string to a binary IPv4 address 01894 error = ipv4StringToAddr(cp, &ipv4Addr); 01895 01896 //Check status code 01897 if(error) 01898 { 01899 //The input is invalid 01900 return 0; 01901 } 01902 else 01903 { 01904 //Copy the binary representation of the IPv4 address 01905 inp->s_addr = ipv4Addr; 01906 //The conversion succeeded 01907 return 1; 01908 } 01909 #else 01910 //IPv4 is not implemented 01911 return 0; 01912 #endif 01913 } 01914 01915 01916 /** 01917 * @brief Convert a binary IPv4 address to dot-decimal notation 01918 * @param[in] in Binary representation of the IPv4 address 01919 * @param[out] cp Pointer to the buffer where to format the string 01920 * @return Pointer to the formatted string 01921 **/ 01922 01923 const char_t *inet_ntoa(in_addr in, char_t *cp) 01924 { 01925 #if (IPV4_SUPPORT == ENABLED) 01926 //Convert the binary IPv4 address to dot-decimal notation 01927 return ipv4AddrToString(in.s_addr, cp); 01928 #else 01929 //Properly terminate the string 01930 cp[0] = '\0'; 01931 //Return a pointer to the formatted string 01932 return cp; 01933 #endif 01934 } 01935 01936 01937 /** 01938 * @brief Convert an IPv4 or IPv6 address from text to binary form 01939 * @param[in] af Address family 01940 * @param[in] src NULL-terminated string representing the IP address 01941 * @param[out] dst Binary representation of the IP address 01942 * @return The function returns 1 on success. 0 is returned if the address 01943 * is not valid. If the address family is not valid, -1 is returned 01944 **/ 01945 01946 int_t inet_pton(int_t af, const char_t *src, void *dst) 01947 { 01948 error_t error; 01949 01950 #if (IPV4_SUPPORT == ENABLED) 01951 //IPv4 address? 01952 if(af == AF_INET) 01953 { 01954 Ipv4Addr ipv4Addr; 01955 01956 //Convert the IPv4 address from text to binary form 01957 error = ipv4StringToAddr(src, &ipv4Addr); 01958 01959 //Check status code 01960 if(error) 01961 { 01962 //The input is invalid 01963 return 0; 01964 } 01965 else 01966 { 01967 //Copy the binary representation of the IPv4 address 01968 ipv4CopyAddr(dst, &ipv4Addr); 01969 //The conversion succeeded 01970 return 1; 01971 } 01972 } 01973 else 01974 #endif 01975 #if (IPV6_SUPPORT == ENABLED) 01976 //IPv6 address? 01977 if(af == AF_INET6) 01978 { 01979 Ipv6Addr ipv6Addr; 01980 01981 //Convert the IPv6 address from text to binary form 01982 error = ipv6StringToAddr(src, &ipv6Addr); 01983 01984 //Check status code 01985 if(error) 01986 { 01987 //The input is invalid 01988 return 0; 01989 } 01990 else 01991 { 01992 //Copy the binary representation of the IPv6 address 01993 ipv6CopyAddr(dst, &ipv6Addr); 01994 //The conversion succeeded 01995 return 1; 01996 } 01997 } 01998 else 01999 #endif 02000 //Invalid address family? 02001 { 02002 //Report an error 02003 return -1; 02004 } 02005 } 02006 02007 02008 /** 02009 * @brief Convert an IPv4 or IPv6 address from binary to text 02010 * @param[in] af Address family 02011 * @param[in] src Binary representation of the IP address 02012 * @param[out] dst NULL-terminated string representing the IP address 02013 * @param[in] size Number of bytes available in the buffer 02014 * @return On success, the function returns a pointer to the formatted string. 02015 * NULL is returned if there was an error 02016 **/ 02017 02018 const char_t *inet_ntop(int_t af, const void *src, char_t *dst, socklen_t size) 02019 { 02020 #if (IPV4_SUPPORT == ENABLED) 02021 //IPv4 address? 02022 if(af == AF_INET) 02023 { 02024 Ipv4Addr ipv4Addr; 02025 02026 //Copy the binary representation of the IPv4 address 02027 ipv4CopyAddr(&ipv4Addr, src); 02028 02029 //Convert the IPv4 address from text to binary form 02030 return ipv4AddrToString(ipv4Addr, dst); 02031 } 02032 else 02033 #endif 02034 #if (IPV6_SUPPORT == ENABLED) 02035 //IPv6 address? 02036 if(af == AF_INET6) 02037 { 02038 Ipv6Addr ipv6Addr; 02039 02040 //Copy the binary representation of the IPv6 address 02041 ipv6CopyAddr(&ipv6Addr, src); 02042 02043 //Convert the IPv6 address from text to binary form 02044 return ipv6AddrToString(&ipv6Addr, dst); 02045 } 02046 else 02047 #endif 02048 //Invalid address family? 02049 { 02050 //Report an error 02051 return NULL; 02052 } 02053 } 02054 02055 #endif 02056
Generated on Tue Jul 12 2022 17:10:12 by
