Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers raw_socket.c Source File

raw_socket.c

Go to the documentation of this file.
00001 /**
00002  * @file raw_socket.c
00003  * @brief TCP/IP raw sockets
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  * @section Description
00026  *
00027  * A raw socket is a type of socket that allows access to the
00028  * underlying transport provider
00029  *
00030  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00031  * @version 1.7.6
00032  **/
00033 
00034 //Switch to the appropriate trace level
00035 #define TRACE_LEVEL RAW_SOCKET_TRACE_LEVEL
00036 
00037 //Dependencies
00038 #include <string.h>
00039 #include "core/net.h"
00040 #include "ipv4/ipv4.h"
00041 #include "ipv6/ipv6.h"
00042 #include "ipv6/ipv6_misc.h"
00043 #include "core/raw_socket.h"
00044 #include "core/socket.h"
00045 #include "core/ethernet.h"
00046 #include "debug.h"
00047 
00048 //Check TCP/IP stack configuration
00049 #if (RAW_SOCKET_SUPPORT == ENABLED)
00050 
00051 
00052 /**
00053  * @brief Process incoming IP packet
00054  * @param[in] interface Underlying network interface
00055  * @param[in] pseudoHeader IPv4 or IPv6 pseudo header
00056  * @param[in] buffer Multi-part buffer containing the IP packet
00057  * @param[in] offset Offset to the first byte of the IP packet
00058  * @return Error code
00059  **/
00060 
00061 error_t rawSocketProcessIpPacket(NetInterface *interface,
00062    IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
00063 {
00064    uint_t i;
00065    size_t length;
00066    Socket *socket;
00067    SocketQueueItem *queueItem;
00068    NetBuffer *p;
00069 
00070    //Retrieve the length of the raw IP packet
00071    length = netBufferGetLength(buffer) - offset;
00072 
00073    //Loop through opened sockets
00074    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00075    {
00076       //Point to the current socket
00077       socket = socketTable + i;
00078 
00079       //Raw socket found?
00080       if(socket->type != SOCKET_TYPE_RAW_IP)
00081          continue;
00082       //Check whether the socket is bound to a particular interface
00083       if(socket->interface && socket->interface != interface)
00084          continue;
00085 
00086 #if (IPV4_SUPPORT == ENABLED)
00087       //An IPv4 packet was received?
00088       if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
00089       {
00090          //Check protocol field
00091          if(socket->protocol != pseudoHeader->ipv4Data.protocol)
00092             continue;
00093          //Destination IP address filtering
00094          if(socket->localIpAddr.length)
00095          {
00096             //An IPv4 address is expected
00097             if(socket->localIpAddr.length != sizeof(Ipv4Addr))
00098                continue;
00099             //Filter out non-matching addresses
00100             if(socket->localIpAddr.ipv4Addr != pseudoHeader->ipv4Data.destAddr)
00101                continue;
00102          }
00103          //Source IP address filtering
00104          if(socket->remoteIpAddr.length)
00105          {
00106             //An IPv4 address is expected
00107             if(socket->remoteIpAddr.length != sizeof(Ipv4Addr))
00108                continue;
00109             //Filter out non-matching addresses
00110             if(socket->remoteIpAddr.ipv4Addr != pseudoHeader->ipv4Data.srcAddr)
00111                continue;
00112          }
00113       }
00114       else
00115 #endif
00116 #if (IPV6_SUPPORT == ENABLED)
00117       //An IPv6 packet was received?
00118       if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
00119       {
00120          //Check protocol field
00121          if(socket->protocol != pseudoHeader->ipv6Data.nextHeader)
00122             continue;
00123 
00124          //Destination IP address filtering
00125          if(socket->localIpAddr.length)
00126          {
00127             //An IPv6 address is expected
00128             if(socket->localIpAddr.length != sizeof(Ipv6Addr))
00129                continue;
00130             //Filter out non-matching addresses
00131             if(!ipv6CompAddr(&socket->localIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.destAddr))
00132                continue;
00133          }
00134 
00135          //Source IP address filtering
00136          if(socket->remoteIpAddr.length)
00137          {
00138             //An IPv6 address is expected
00139             if(socket->remoteIpAddr.length != sizeof(Ipv6Addr))
00140                continue;
00141             //Filter out non-matching addresses
00142             if(!ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.srcAddr))
00143                continue;
00144          }
00145       }
00146       else
00147 #endif
00148       //An invalid packet was received?
00149       {
00150          //This should never occur...
00151          continue;
00152       }
00153 
00154       //The current socket meets all the criteria
00155       break;
00156    }
00157 
00158    //Drop incoming packet if no matching socket was found
00159    if(i >= SOCKET_MAX_COUNT)
00160       return ERROR_PROTOCOL_UNREACHABLE;
00161 
00162    //Empty receive queue?
00163    if(!socket->receiveQueue)
00164    {
00165       //Allocate a memory buffer to hold the data and the associated descriptor
00166       p = netBufferAlloc(sizeof(SocketQueueItem) + length);
00167 
00168       //Successful memory allocation?
00169       if(p != NULL)
00170       {
00171          //Point to the newly created item
00172          queueItem = netBufferAt(p, 0);
00173          queueItem->buffer = p;
00174          //Add the newly created item to the queue
00175          socket->receiveQueue = queueItem;
00176       }
00177       else
00178       {
00179          //Memory allocation failed
00180          queueItem = NULL;
00181       }
00182    }
00183    else
00184    {
00185       //Point to the very first item
00186       queueItem = socket->receiveQueue;
00187       //Reach the last item in the receive queue
00188       for(i = 1; queueItem->next; i++)
00189          queueItem = queueItem->next;
00190 
00191       //Make sure the receive queue is not full
00192       if(i >= RAW_SOCKET_RX_QUEUE_SIZE)
00193          return ERROR_RECEIVE_QUEUE_FULL;
00194 
00195       //Allocate a memory buffer to hold the data and the associated descriptor
00196       p = netBufferAlloc(sizeof(SocketQueueItem) + length);
00197 
00198       //Successful memory allocation?
00199       if(p != NULL)
00200       {
00201          //Add the newly created item to the queue
00202          queueItem->next = netBufferAt(p, 0);
00203          //Point to the newly created item
00204          queueItem = queueItem->next;
00205          queueItem->buffer = p;
00206       }
00207       else
00208       {
00209          //Memory allocation failed
00210          queueItem = NULL;
00211       }
00212    }
00213 
00214    //Failed to allocate memory?
00215    if(queueItem == NULL)
00216       return ERROR_OUT_OF_MEMORY;
00217 
00218    //Initialize next field
00219    queueItem->next = NULL;
00220    //Port number is unused
00221    queueItem->srcPort = 0;
00222 
00223 #if (IPV4_SUPPORT == ENABLED)
00224    //IPv4 remote address?
00225    if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
00226    {
00227       //Save the source IPv4 address
00228       queueItem->srcIpAddr.length = sizeof(Ipv4Addr);
00229       queueItem->srcIpAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
00230       //Save the destination IPv4 address
00231       queueItem->destIpAddr.length = sizeof(Ipv4Addr);
00232       queueItem->destIpAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
00233    }
00234 #endif
00235 #if (IPV6_SUPPORT == ENABLED)
00236    //IPv6 remote address?
00237    if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
00238    {
00239       //Save the source IPv6 address
00240       queueItem->srcIpAddr.length = sizeof(Ipv6Addr);
00241       queueItem->srcIpAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
00242       //Save the destination IPv6 address
00243       queueItem->destIpAddr.length = sizeof(Ipv6Addr);
00244       queueItem->destIpAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
00245    }
00246 #endif
00247 
00248    //Offset to the raw IP packet
00249    queueItem->offset = sizeof(SocketQueueItem);
00250    //Copy the raw data
00251    netBufferCopy(queueItem->buffer, queueItem->offset, buffer, offset, length);
00252 
00253    //Notify user that data is available
00254    rawSocketUpdateEvents(socket);
00255 
00256    //Successful processing
00257    return NO_ERROR;
00258 }
00259 
00260 
00261 /**
00262  * @brief Process incoming Ethernet packet
00263  * @param[in] interface Underlying network interface
00264  * @param[in] ethFrame Incoming Ethernet frame to process
00265  * @param[in] length Total frame length
00266  **/
00267 
00268 void rawSocketProcessEthPacket(NetInterface *interface,
00269    EthHeader *ethFrame, size_t length)
00270 {
00271    uint_t i;
00272    Socket *socket;
00273    SocketQueueItem *queueItem;
00274    NetBuffer *p;
00275 
00276    //Loop through opened sockets
00277    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00278    {
00279       //Point to the current socket
00280       socket = socketTable + i;
00281 
00282       //Raw socket found?
00283       if(socket->type != SOCKET_TYPE_RAW_ETH)
00284          continue;
00285       //Check whether the socket is bound to a particular interface
00286       if(socket->interface && socket->interface != interface)
00287          continue;
00288       //Check protocol field
00289       if(socket->protocol != SOCKET_ETH_PROTO_ALL && socket->protocol != ntohs(ethFrame->type))
00290          continue;
00291 
00292       //The current socket meets all the criteria
00293       break;
00294    }
00295 
00296    //Drop incoming packet if no matching socket was found
00297    if(i >= SOCKET_MAX_COUNT)
00298       return;
00299 
00300    //Empty receive queue?
00301    if(!socket->receiveQueue)
00302    {
00303       //Allocate a memory buffer to hold the data and the associated descriptor
00304       p = netBufferAlloc(sizeof(SocketQueueItem) + length);
00305 
00306       //Successful memory allocation?
00307       if(p != NULL)
00308       {
00309          //Point to the newly created item
00310          queueItem = netBufferAt(p, 0);
00311          queueItem->buffer = p;
00312          //Add the newly created item to the queue
00313          socket->receiveQueue = queueItem;
00314       }
00315       else
00316       {
00317          //Memory allocation failed
00318          queueItem = NULL;
00319       }
00320    }
00321    else
00322    {
00323       //Point to the very first item
00324       queueItem = socket->receiveQueue;
00325       //Reach the last item in the receive queue
00326       for(i = 1; queueItem->next; i++)
00327          queueItem = queueItem->next;
00328 
00329       //Make sure the receive queue is not full
00330       if(i >= RAW_SOCKET_RX_QUEUE_SIZE)
00331          return;
00332 
00333       //Allocate a memory buffer to hold the data and the associated descriptor
00334       p = netBufferAlloc(sizeof(SocketQueueItem) + length);
00335 
00336       //Successful memory allocation?
00337       if(p != NULL)
00338       {
00339          //Add the newly created item to the queue
00340          queueItem->next = netBufferAt(p, 0);
00341          //Point to the newly created item
00342          queueItem = queueItem->next;
00343          queueItem->buffer = p;
00344       }
00345       else
00346       {
00347          //Memory allocation failed
00348          queueItem = NULL;
00349       }
00350    }
00351 
00352    //Failed to allocate memory?
00353    if(queueItem == NULL)
00354       return;
00355 
00356    //Initialize next field
00357    queueItem->next = NULL;
00358    //Other fields are meaningless
00359    queueItem->srcPort = 0;
00360    queueItem->srcIpAddr = IP_ADDR_ANY;
00361    queueItem->destIpAddr = IP_ADDR_ANY;
00362 
00363    //Offset to the raw datagram
00364    queueItem->offset = sizeof(SocketQueueItem);
00365    //Copy the raw data
00366    netBufferWrite(queueItem->buffer, queueItem->offset, ethFrame, length);
00367 
00368    //Notify user that data is available
00369    rawSocketUpdateEvents(socket);
00370 }
00371 
00372 
00373 /**
00374  * @brief Send an raw IP packet
00375  * @param[in] socket Handle referencing the socket
00376  * @param[in] destIpAddr IP address of the target host
00377  * @param[in] data Pointer to raw data
00378  * @param[in] length Length of the raw data
00379  * @param[out] written Actual number of bytes written (optional parameter)
00380  * @return Error code
00381  **/
00382 
00383 error_t rawSocketSendIpPacket(Socket *socket, const IpAddr *destIpAddr,
00384    const void *data, size_t length, size_t *written)
00385 {
00386    error_t error;
00387    size_t offset;
00388    NetBuffer *buffer;
00389    NetInterface *interface;
00390    IpPseudoHeader pseudoHeader;
00391 
00392    //The socket may be bound to a particular network interface
00393    interface = socket->interface;
00394 
00395    //Allocate a buffer memory to hold the raw IP datagram
00396    buffer = ipAllocBuffer(0, &offset);
00397    //Failed to allocate memory?
00398    if(buffer == NULL)
00399       return ERROR_OUT_OF_MEMORY;
00400 
00401    //Start of exception handling block
00402    do
00403    {
00404       //Copy the raw data
00405       error = netBufferAppend(buffer, data, length);
00406       //Any error to report?
00407       if(error)
00408          break;
00409 
00410 #if (IPV4_SUPPORT == ENABLED)
00411       //Destination address is an IPv4 address?
00412       if(destIpAddr->length == sizeof(Ipv4Addr))
00413       {
00414          Ipv4Addr srcIpAddr;
00415 
00416          //Select the source IPv4 address and the relevant network interface
00417          //to use when sending data to the specified destination host
00418          error = ipv4SelectSourceAddr(&interface, destIpAddr->ipv4Addr, &srcIpAddr);
00419          //Any error to report?
00420          if(error)
00421             break;
00422 
00423          //Format IPv4 pseudo header
00424          pseudoHeader.length = sizeof(Ipv4PseudoHeader);
00425          pseudoHeader.ipv4Data.srcAddr = srcIpAddr;
00426          pseudoHeader.ipv4Data.destAddr = destIpAddr->ipv4Addr;
00427          pseudoHeader.ipv4Data.reserved = 0;
00428          pseudoHeader.ipv4Data.protocol = socket->protocol;
00429          pseudoHeader.ipv4Data.length = htons(length);
00430       }
00431       else
00432 #endif
00433 #if (IPV6_SUPPORT == ENABLED)
00434       //Destination address is an IPv6 address?
00435       if(destIpAddr->length == sizeof(Ipv6Addr))
00436       {
00437          //Select the source IPv6 address and the relevant network interface
00438          //to use when sending data to the specified destination host
00439          error = ipv6SelectSourceAddr(&interface,
00440             &destIpAddr->ipv6Addr, &pseudoHeader.ipv6Data.srcAddr);
00441          //Any error to report?
00442          if(error)
00443             break;
00444 
00445          //Format IPv6 pseudo header
00446          pseudoHeader.length = sizeof(Ipv6PseudoHeader);
00447          pseudoHeader.ipv6Data.destAddr = destIpAddr->ipv6Addr;
00448          pseudoHeader.ipv6Data.length = htonl(length);
00449          pseudoHeader.ipv6Data.reserved = 0;
00450          pseudoHeader.ipv6Data.nextHeader = socket->protocol;
00451       }
00452       else
00453 #endif
00454       //Invalid destination address?
00455       {
00456          //An internal error has occurred
00457          error = ERROR_FAILURE;
00458          //Exit immediately
00459          break;
00460       }
00461 
00462       //Send raw IP datagram
00463       error = ipSendDatagram(interface, &pseudoHeader, buffer, offset, socket->ttl);
00464       //Failed to send data?
00465       if(error)
00466          break;
00467 
00468       //Total number of bytes successfully transmitted
00469       if(written != NULL)
00470          *written = length;
00471 
00472       //End of exception handling block
00473    } while(0);
00474 
00475    //Free previously allocated memory block
00476    netBufferFree(buffer);
00477    //Return status code
00478    return error;
00479 }
00480 
00481 
00482 /**
00483  * @brief Send an raw Ethernet packet
00484  * @param[in] socket Handle referencing the socket
00485  * @param[in] data Pointer to raw data
00486  * @param[in] length Length of the raw data
00487  * @param[out] written Actual number of bytes written (optional parameter)
00488  * @return Error code
00489  **/
00490 
00491 error_t rawSocketSendEthPacket(Socket *socket,
00492    const void *data, size_t length, size_t *written)
00493 {
00494    error_t error;
00495 
00496 #if (ETH_SUPPORT == ENABLED)
00497    NetBuffer *buffer;
00498    NetInterface *interface;
00499 
00500    //Select the relevant network interface
00501    if(!socket->interface)
00502       interface = netGetDefaultInterface();
00503    else
00504       interface = socket->interface;
00505 
00506    //Ethernet interface?
00507    if(interface->nicDriver->type == NIC_TYPE_ETHERNET)
00508    {
00509       //Allocate a buffer memory to hold the raw Ethernet packet
00510       buffer = netBufferAlloc(0);
00511       //Failed to allocate buffer?
00512       if(buffer == NULL)
00513          return ERROR_OUT_OF_MEMORY;
00514 
00515       //Copy the raw data
00516       error = netBufferAppend(buffer, data, length);
00517 
00518       //Successful processing?
00519       if(!error)
00520       {
00521          //Automatic padding not supported by hardware?
00522          if(!interface->nicDriver->autoPadding)
00523          {
00524             //The host controller should manually add padding
00525             //to the packet before transmitting it
00526             if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE))
00527             {
00528                size_t n;
00529 
00530                //Add padding as necessary
00531                n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length;
00532 
00533                //Append padding bytes
00534                error = netBufferAppend(buffer, ethPadding, n);
00535                //Any error to report?
00536                if(error)
00537                   return error;
00538 
00539                //Adjust frame length
00540                length += n;
00541             }
00542          }
00543 
00544          //CRC calculation not supported by hardware?
00545          if(!interface->nicDriver->autoCrcCalc)
00546          {
00547             uint32_t crc;
00548 
00549             //Compute CRC over the header and payload
00550             crc = ethCalcCrcEx(buffer, 0, length);
00551             //Convert from host byte order to little-endian byte order
00552             crc = htole32(crc);
00553 
00554             //Append the calculated CRC value
00555             error = netBufferAppend(buffer, &crc, sizeof(crc));
00556             //Any error to report?
00557             if(error)
00558                return error;
00559 
00560             //Adjust frame length
00561             length += sizeof(crc);
00562          }
00563 
00564          //Debug message
00565          TRACE_DEBUG("Sending raw Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);
00566 
00567          //Send the resulting packet over the specified link
00568          error = nicSendPacket(interface, buffer, 0);
00569       }
00570 
00571       //Free previously allocated memory block
00572       netBufferFree(buffer);
00573    }
00574    else
00575 #endif
00576    //Unknown interface type?
00577    {
00578       //Report an error
00579       error = ERROR_INVALID_INTERFACE;
00580    }
00581 
00582    //Successful processing?
00583    if(!error)
00584    {
00585       //Total number of bytes successfully transmitted
00586       if(written != NULL)
00587          *written = length;
00588    }
00589 
00590    //Return status code
00591    return error;
00592 }
00593 
00594 
00595 /**
00596  * @brief Receive an IP packet from a raw socket
00597  * @param[in] socket Handle referencing the socket
00598  * @param[out] srcIpAddr Source IP address (optional)
00599  * @param[out] destIpAddr Destination IP address (optional)
00600  * @param[out] data Buffer where to store the incoming data
00601  * @param[in] size Maximum number of bytes that can be received
00602  * @param[out] received Number of bytes that have been received
00603  * @param[in] flags Set of flags that influences the behavior of this function
00604  * @return Error code
00605  **/
00606 
00607 error_t rawSocketReceiveIpPacket(Socket *socket, IpAddr *srcIpAddr,
00608    IpAddr *destIpAddr, void *data, size_t size, size_t *received, uint_t flags)
00609 {
00610    SocketQueueItem *queueItem;
00611 
00612    //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
00613    if(!(flags & SOCKET_FLAG_DONT_WAIT))
00614    {
00615       //The receive queue is empty?
00616       if(!socket->receiveQueue)
00617       {
00618          //Set the events the application is interested in
00619          socket->eventMask = SOCKET_EVENT_RX_READY;
00620          //Reset the event object
00621          osResetEvent(&socket->event);
00622 
00623          //Release exclusive access
00624          osReleaseMutex(&netMutex);
00625          //Wait until an event is triggered
00626          osWaitForEvent(&socket->event, socket->timeout);
00627          //Get exclusive access
00628          osAcquireMutex(&netMutex);
00629       }
00630    }
00631 
00632    //Check whether the read operation timed out
00633    if(!socket->receiveQueue)
00634    {
00635       //No data can be read
00636       *received = 0;
00637       //Report a timeout error
00638       return ERROR_TIMEOUT;
00639    }
00640 
00641    //Point to the first item in the receive queue
00642    queueItem = socket->receiveQueue;
00643    //Copy data to user buffer
00644    *received = netBufferRead(data, queueItem->buffer, queueItem->offset, size);
00645 
00646    //Save the source IP address
00647    if(srcIpAddr)
00648       *srcIpAddr = queueItem->srcIpAddr;
00649    //Save the destination IP address
00650    if(destIpAddr)
00651       *destIpAddr = queueItem->destIpAddr;
00652 
00653    //If the SOCKET_FLAG_PEEK flag is set, the data is copied
00654    //into the buffer but is not removed from the input queue
00655    if(!(flags & SOCKET_FLAG_PEEK))
00656    {
00657       //Remove the item from the receive queue
00658       socket->receiveQueue = queueItem->next;
00659       //Deallocate memory buffer
00660       netBufferFree(queueItem->buffer);
00661    }
00662 
00663    //Update the state of events
00664    rawSocketUpdateEvents(socket);
00665 
00666    //Successful read operation
00667    return NO_ERROR;
00668 }
00669 
00670 
00671 /**
00672  * @brief Receive an Ethernet packet from a raw socket
00673  * @param[in] socket Handle referencing the socket
00674  * @param[out] data Buffer where to store the incoming data
00675  * @param[in] size Maximum number of bytes that can be received
00676  * @param[out] received Number of bytes that have been received
00677  * @param[in] flags Set of flags that influences the behavior of this function
00678  * @return Error code
00679  **/
00680 
00681 error_t rawSocketReceiveEthPacket(Socket *socket,
00682    void *data, size_t size, size_t *received, uint_t flags)
00683 {
00684    SocketQueueItem *queueItem;
00685 
00686    //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
00687    if(!(flags & SOCKET_FLAG_DONT_WAIT))
00688    {
00689       //The receive queue is empty?
00690       if(!socket->receiveQueue)
00691       {
00692          //Set the events the application is interested in
00693          socket->eventMask = SOCKET_EVENT_RX_READY;
00694          //Reset the event object
00695          osResetEvent(&socket->event);
00696 
00697          //Release exclusive access
00698          osReleaseMutex(&netMutex);
00699          //Wait until an event is triggered
00700          osWaitForEvent(&socket->event, socket->timeout);
00701          //Get exclusive access
00702          osAcquireMutex(&netMutex);
00703       }
00704    }
00705 
00706    //Check whether the read operation timed out
00707    if(!socket->receiveQueue)
00708    {
00709       //No data can be read
00710       *received = 0;
00711       //Report a timeout error
00712       return ERROR_TIMEOUT;
00713    }
00714 
00715    //Point to the first item in the receive queue
00716    queueItem = socket->receiveQueue;
00717    //Copy data to user buffer
00718    *received = netBufferRead(data, queueItem->buffer, queueItem->offset, size);
00719 
00720    //If the SOCKET_FLAG_PEEK flag is set, the data is copied
00721    //into the buffer but is not removed from the input queue
00722    if(!(flags & SOCKET_FLAG_PEEK))
00723    {
00724       //Remove the item from the receive queue
00725       socket->receiveQueue = queueItem->next;
00726       //Deallocate memory buffer
00727       netBufferFree(queueItem->buffer);
00728    }
00729 
00730    //Update the state of events
00731    rawSocketUpdateEvents(socket);
00732 
00733    //Successful read operation
00734    return NO_ERROR;
00735 }
00736 
00737 
00738 /**
00739  * @brief Update event state for raw sockets
00740  * @param[in] socket Handle referencing the socket
00741  **/
00742 
00743 void rawSocketUpdateEvents(Socket *socket)
00744 {
00745    //Clear event flags
00746    socket->eventFlags = 0;
00747 
00748    //The socket is marked as readable if a datagram is pending in the queue
00749    if(socket->receiveQueue)
00750       socket->eventFlags |= SOCKET_EVENT_RX_READY;
00751 
00752    //Check whether the socket is bound to a particular network interface
00753    if(socket->interface != NULL)
00754    {
00755       //Handle link up and link down events
00756       if(socket->interface->linkState)
00757          socket->eventFlags |= SOCKET_EVENT_LINK_UP;
00758       else
00759          socket->eventFlags |= SOCKET_EVENT_LINK_DOWN;
00760    }
00761 
00762    //Mask unused events
00763    socket->eventFlags &= socket->eventMask;
00764 
00765    //Any event to signal?
00766    if(socket->eventFlags)
00767    {
00768       //Unblock I/O operations currently in waiting state
00769       osSetEvent(&socket->event);
00770 
00771       //Set user event to signaled state if necessary
00772       if(socket->userEvent != NULL)
00773          osSetEvent(socket->userEvent);
00774    }
00775 }
00776 
00777 #endif
00778