Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bsd_socket.c Source File

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