Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp.c Source File

tcp.c

Go to the documentation of this file.
00001 /**
00002  * @file tcp.c
00003  * @brief TCP (Transmission Control Protocol)
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 TCP_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <string.h>
00034 #include "core/net.h"
00035 #include "core/socket.h"
00036 #include "core/tcp.h"
00037 #include "core/tcp_misc.h"
00038 #include "core/tcp_timer.h"
00039 #include "mibs/mib2_module.h"
00040 #include "debug.h"
00041 
00042 //Check TCP/IP stack configuration
00043 #if (TCP_SUPPORT == ENABLED)
00044 
00045 //Tick counter to handle periodic operations
00046 systime_t tcpTickCounter;
00047 
00048 //Ephemeral ports are used for dynamic port assignment
00049 static uint16_t tcpDynamicPort;
00050 
00051 
00052 /**
00053  * @brief TCP related initialization
00054  * @return Error code
00055  **/
00056 
00057 error_t tcpInit(void)
00058 {
00059    //Reset ephemeral port number
00060    tcpDynamicPort = 0;
00061 
00062    //Successful initialization
00063    return NO_ERROR;
00064 }
00065 
00066 
00067 /**
00068  * @brief Get an ephemeral port number
00069  * @return Ephemeral port
00070  **/
00071 
00072 uint16_t tcpGetDynamicPort(void)
00073 {
00074    uint_t port;
00075 
00076    //Retrieve current port number
00077    port = tcpDynamicPort;
00078 
00079    //Invalid port number?
00080    if(port < SOCKET_EPHEMERAL_PORT_MIN || port > SOCKET_EPHEMERAL_PORT_MAX)
00081    {
00082       //Generate a random port number
00083       port = SOCKET_EPHEMERAL_PORT_MIN + netGetRand() %
00084          (SOCKET_EPHEMERAL_PORT_MAX - SOCKET_EPHEMERAL_PORT_MIN + 1);
00085    }
00086 
00087    //Next dynamic port to use
00088    if(port < SOCKET_EPHEMERAL_PORT_MAX)
00089    {
00090       //Increment port number
00091       tcpDynamicPort = port + 1;
00092    }
00093    else
00094    {
00095       //Wrap around if necessary
00096       tcpDynamicPort = SOCKET_EPHEMERAL_PORT_MIN;
00097    }
00098 
00099    //Return an ephemeral port number
00100    return port;
00101 }
00102 
00103 
00104 /**
00105  * @brief Establish a TCP connection
00106  * @param[in] socket Handle to an unconnected socket
00107  * @param[in] remoteIpAddr IP address of the remote host
00108  * @param[in] remotePort Remote port number that will be used to establish the connection
00109  * @return Error code
00110  **/
00111 
00112 error_t tcpConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
00113 {
00114    error_t error;
00115    uint_t event;
00116 
00117    //Check current TCP state
00118    if(socket->state == TCP_STATE_CLOSED)
00119    {
00120       //Save port number and IP address of the remote host
00121       socket->remoteIpAddr = *remoteIpAddr;
00122       socket->remotePort = remotePort;
00123 
00124       //Select the source address and the relevant network interface
00125       //to use when establishing the connection
00126       error = ipSelectSourceAddr(&socket->interface,
00127          &socket->remoteIpAddr, &socket->localIpAddr);
00128       //Any error to report?
00129       if(error)
00130          return error;
00131 
00132       //Make sure the source address is valid
00133       if(ipIsUnspecifiedAddr(&socket->localIpAddr))
00134          return ERROR_NOT_CONFIGURED;
00135 
00136       //The user owns the socket
00137       socket->ownedFlag = TRUE;
00138 
00139       //Number of chunks that comprise the TX and the RX buffers
00140       socket->txBuffer.maxChunkCount = arraysize(socket->txBuffer.chunk);
00141       socket->rxBuffer.maxChunkCount = arraysize(socket->rxBuffer.chunk);
00142 
00143       //Allocate transmit buffer
00144       error = netBufferSetLength((NetBuffer *) &socket->txBuffer,
00145          socket->txBufferSize);
00146 
00147       //Allocate receive buffer
00148       if(!error)
00149       {
00150          error = netBufferSetLength((NetBuffer *) &socket->rxBuffer,
00151             socket->rxBufferSize);
00152       }
00153 
00154       //Failed to allocate memory?
00155       if(error)
00156       {
00157          //Free any previously allocated memory
00158          tcpDeleteControlBlock(socket);
00159          //Report an error to the caller
00160          return error;
00161       }
00162 
00163       //The SMSS is the size of the largest segment that the sender can transmit
00164       socket->smss = MIN(TCP_DEFAULT_MSS, TCP_MAX_MSS);
00165       //The RMSS is the size of the largest segment the receiver is willing to accept
00166       socket->rmss = MIN(socket->rxBufferSize, TCP_MAX_MSS);
00167 
00168       //An initial send sequence number is selected
00169       socket->iss = netGetRand();
00170 
00171       //Initialize TCP control block
00172       socket->sndUna = socket->iss;
00173       socket->sndNxt = socket->iss + 1;
00174       socket->rcvUser = 0;
00175       socket->rcvWnd = socket->rxBufferSize;
00176 
00177       //Default retransmission timeout
00178       socket->rto = TCP_INITIAL_RTO;
00179 
00180 #if (TCP_CONGEST_CONTROL_SUPPORT == ENABLED)
00181       //Default congestion state
00182       socket->congestState = TCP_CONGEST_STATE_IDLE;
00183       //Initial congestion window
00184       socket->cwnd = MIN(TCP_INITIAL_WINDOW * socket->smss, socket->txBufferSize);
00185       //Slow start threshold should be set arbitrarily high
00186       socket->ssthresh = UINT16_MAX;
00187       //Recover is set to the initial send sequence number
00188       socket->recover = socket->iss;
00189 #endif
00190 
00191       //Send a SYN segment
00192       error = tcpSendSegment(socket, TCP_FLAG_SYN, socket->iss, 0, 0, TRUE);
00193       //Failed to send TCP segment?
00194       if(error)
00195          return error;
00196 
00197       //Switch to the SYN-SENT state
00198       tcpChangeState(socket, TCP_STATE_SYN_SENT);
00199 
00200       //Number of times TCP connections have made a direct transition to
00201       //the SYN-SENT state from the CLOSED state
00202       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpActiveOpens, 1);
00203    }
00204 
00205    //Wait for the connection to be established
00206    event = tcpWaitForEvents(socket, SOCKET_EVENT_CONNECTED |
00207       SOCKET_EVENT_CLOSED, socket->timeout);
00208 
00209    //Connection successfully established?
00210    if(event == SOCKET_EVENT_CONNECTED)
00211       return NO_ERROR;
00212    //Failed to establish connection?
00213    else if(event == SOCKET_EVENT_CLOSED)
00214       return ERROR_CONNECTION_FAILED;
00215    //Timeout exception?
00216    else
00217       return ERROR_TIMEOUT;
00218 }
00219 
00220 
00221 /**
00222  * @brief Place a socket in the listening state
00223  *
00224  * Place a socket in a state in which it is listening for an incoming connection
00225  *
00226  * @param[in] socket Socket to place in the listening state
00227  * @param[in] backlog backlog The maximum length of the pending connection queue.
00228  *   If this parameter is zero, then the default backlog value is used instead
00229  * @return Error code
00230  **/
00231 
00232 error_t tcpListen(Socket *socket, uint_t backlog)
00233 {
00234    //Socket already connected?
00235    if(socket->state != TCP_STATE_CLOSED)
00236       return ERROR_ALREADY_CONNECTED;
00237 
00238    //Set the size of the SYN queue
00239    socket->synQueueSize = (backlog > 0) ? backlog : TCP_DEFAULT_SYN_QUEUE_SIZE;
00240    //Limit the number of pending connections
00241    socket->synQueueSize = MIN(socket->synQueueSize, TCP_MAX_SYN_QUEUE_SIZE);
00242 
00243    //Place the socket in the listening state
00244    tcpChangeState(socket, TCP_STATE_LISTEN);
00245 
00246    //Successful processing
00247    return NO_ERROR;
00248 }
00249 
00250 
00251 /**
00252  * @brief Permit an incoming connection attempt on a TCP socket
00253  * @param[in] socket Handle to a socket previously placed in a listening state
00254  * @param[out] clientIpAddr IP address of the client
00255  * @param[out] clientPort Port number used by the client
00256  * @return Handle to the socket in which the actual connection is made
00257  **/
00258 
00259 Socket *tcpAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
00260 {
00261    error_t error;
00262    Socket *newSocket;
00263    TcpSynQueueItem *queueItem;
00264 
00265    //Ensure the socket was previously placed in the listening state
00266    if(tcpGetState(socket) != TCP_STATE_LISTEN)
00267       return NULL;
00268 
00269    //Get exclusive access
00270    osAcquireMutex(&netMutex);
00271 
00272    //Wait for an connection attempt
00273    while(1)
00274    {
00275       //The SYN queue is empty?
00276       if(!socket->synQueue)
00277       {
00278          //Set the events the application is interested in
00279          socket->eventMask = SOCKET_EVENT_RX_READY;
00280          //Reset the event object
00281          osResetEvent(&socket->event);
00282 
00283          //Release exclusive access
00284          osReleaseMutex(&netMutex);
00285          //Wait until a SYN message is received from a client
00286          osWaitForEvent(&socket->event, socket->timeout);
00287          //Get exclusive access
00288          osAcquireMutex(&netMutex);
00289       }
00290 
00291       //Check whether the queue is still empty
00292       if(!socket->synQueue)
00293       {
00294          //Timeout error
00295          newSocket = NULL;
00296          //Exit immediately
00297          break;
00298       }
00299 
00300       //Point to the first item in the receive queue
00301       queueItem = socket->synQueue;
00302 
00303       //Return the client IP address and port number
00304       if(clientIpAddr)
00305          *clientIpAddr = queueItem->srcAddr;
00306       if(clientPort)
00307          *clientPort = queueItem->srcPort;
00308 
00309       //Release exclusive access
00310       osReleaseMutex(&netMutex);
00311       //Create a new socket to handle the incoming connection request
00312       newSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
00313       //Get exclusive access
00314       osAcquireMutex(&netMutex);
00315 
00316       //Socket successfully created?
00317       if(newSocket != NULL)
00318       {
00319          //The user owns the socket
00320          newSocket->ownedFlag = TRUE;
00321 
00322          //Inherit settings from the listening socket
00323          newSocket->txBufferSize = socket->txBufferSize;
00324          newSocket->rxBufferSize = socket->rxBufferSize;
00325 
00326          //Number of chunks that comprise the TX and the RX buffers
00327          newSocket->txBuffer.maxChunkCount = arraysize(newSocket->txBuffer.chunk);
00328          newSocket->rxBuffer.maxChunkCount = arraysize(newSocket->rxBuffer.chunk);
00329 
00330          //Allocate transmit buffer
00331          error = netBufferSetLength((NetBuffer *) &newSocket->txBuffer, newSocket->txBufferSize);
00332 
00333          //Check status code
00334          if(!error)
00335          {
00336             //Allocate receive buffer
00337             error = netBufferSetLength((NetBuffer *) &newSocket->rxBuffer, newSocket->rxBufferSize);
00338          }
00339 
00340          //Transmit and receive buffers successfully allocated?
00341          if(!error)
00342          {
00343             //Bind the newly created socket to the appropriate interface
00344             newSocket->interface = queueItem->interface;
00345 
00346             //Bind the socket to the specified address
00347             newSocket->localIpAddr = queueItem->destAddr;
00348             newSocket->localPort = socket->localPort;
00349             //Save the port number and the IP address of the remote host
00350             newSocket->remoteIpAddr = queueItem->srcAddr;
00351             newSocket->remotePort = queueItem->srcPort;
00352 
00353             //The SMSS is the size of the largest segment that the sender
00354             //can transmit
00355             newSocket->smss = queueItem->mss;
00356 
00357             //The RMSS is the size of the largest segment the receiver is
00358             //willing to accept
00359             newSocket->rmss = MIN(newSocket->rxBufferSize, TCP_MAX_MSS);
00360 
00361             //Initialize TCP control block
00362             newSocket->iss = netGetRand();
00363             newSocket->irs = queueItem->isn;
00364             newSocket->sndUna = newSocket->iss;
00365             newSocket->sndNxt = newSocket->iss + 1;
00366             newSocket->rcvNxt = newSocket->irs + 1;
00367             newSocket->rcvUser = 0;
00368             newSocket->rcvWnd = newSocket->rxBufferSize;
00369 
00370             //Default retransmission timeout
00371             newSocket->rto = TCP_INITIAL_RTO;
00372 
00373 #if (TCP_CONGEST_CONTROL_SUPPORT == ENABLED)
00374             //Default congestion state
00375             socket->congestState = TCP_CONGEST_STATE_IDLE;
00376             //Initial congestion window
00377             newSocket->cwnd = MIN(TCP_INITIAL_WINDOW * newSocket->smss, newSocket->txBufferSize);
00378             //Slow start threshold should be set arbitrarily high
00379             newSocket->ssthresh = UINT16_MAX;
00380             //Recover is set to the initial send sequence number
00381             newSocket->recover = newSocket->iss;
00382 #endif
00383             //Send a SYN ACK control segment
00384             error = tcpSendSegment(newSocket, TCP_FLAG_SYN | TCP_FLAG_ACK,
00385                newSocket->iss, newSocket->rcvNxt, 0, TRUE);
00386 
00387             //TCP segment successfully sent?
00388             if(!error)
00389             {
00390                //Remove the item from the SYN queue
00391                socket->synQueue = queueItem->next;
00392                //Deallocate memory buffer
00393                memPoolFree(queueItem);
00394                //Update the state of events
00395                tcpUpdateEvents(socket);
00396 
00397                //The connection state should be changed to SYN-RECEIVED
00398                tcpChangeState(newSocket, TCP_STATE_SYN_RECEIVED);
00399 
00400                //Number of times TCP connections have made a direct transition to
00401                //the SYN-RECEIVED state from the LISTEN state
00402                MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpPassiveOpens, 1);
00403 
00404                //We are done...
00405                break;
00406             }
00407          }
00408 
00409          //Dispose the socket
00410          tcpAbort(newSocket);
00411       }
00412 
00413       //Debug message
00414       TRACE_WARNING("Cannot accept TCP connection!\r\n");
00415 
00416       //Remove the item from the SYN queue
00417       socket->synQueue = queueItem->next;
00418       //Deallocate memory buffer
00419       memPoolFree(queueItem);
00420 
00421       //Wait for the next connection attempt
00422    }
00423 
00424    //Release exclusive access
00425    osReleaseMutex(&netMutex);
00426 
00427    //Return a handle to the newly created socket
00428    return newSocket;
00429 }
00430 
00431 
00432 /**
00433  * @brief Send data to a connected socket
00434  * @param[in] socket Handle that identifies a connected socket
00435  * @param[in] data Pointer to a buffer containing the data to be transmitted
00436  * @param[in] length Number of bytes to be transmitted
00437  * @param[out] written Actual number of bytes written (optional parameter)
00438  * @param[in] flags Set of flags that influences the behavior of this function
00439  * @return Error code
00440  **/
00441 
00442 error_t tcpSend(Socket *socket, const uint8_t *data,
00443    size_t length, size_t *written, uint_t flags)
00444 {
00445    uint_t n;
00446    uint_t totalLength;
00447    uint_t event;
00448 
00449    //Check whether the socket is in the listening state
00450    if(socket->state == TCP_STATE_LISTEN)
00451       return ERROR_NOT_CONNECTED;
00452 
00453    //Actual number of bytes written
00454    totalLength = 0;
00455 
00456    //Send as much data as possible
00457    do
00458    {
00459       //Wait until there is more room in the send buffer
00460       event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_READY, socket->timeout);
00461 
00462       //A timeout exception occurred?
00463       if(event != SOCKET_EVENT_TX_READY)
00464          return ERROR_TIMEOUT;
00465 
00466       //Check current TCP state
00467       switch(socket->state)
00468       {
00469       //ESTABLISHED or CLOSE-WAIT state?
00470       case TCP_STATE_ESTABLISHED:
00471       case TCP_STATE_CLOSE_WAIT:
00472          //The send buffer is now available for writing
00473          break;
00474 
00475       //LAST-ACK, FIN-WAIT-1, FIN-WAIT-2, CLOSING or TIME-WAIT state?
00476       case TCP_STATE_LAST_ACK:
00477       case TCP_STATE_FIN_WAIT_1:
00478       case TCP_STATE_FIN_WAIT_2:
00479       case TCP_STATE_CLOSING:
00480       case TCP_STATE_TIME_WAIT:
00481          //The connection is being closed
00482          return ERROR_CONNECTION_CLOSING;
00483 
00484       //CLOSED state?
00485       default:
00486          //The connection was reset by remote side?
00487          return (socket->resetFlag) ? ERROR_CONNECTION_RESET : ERROR_NOT_CONNECTED;
00488       }
00489 
00490       //Determine the actual number of bytes in the send buffer
00491       n = socket->sndUser + socket->sndNxt - socket->sndUna;
00492       //Exit immediately if the transmission buffer is full (sanity check)
00493       if(n >= socket->txBufferSize)
00494          return ERROR_FAILURE;
00495 
00496       //Number of bytes available for writing
00497       n = socket->txBufferSize - n;
00498       //Calculate the number of bytes to copy at a time
00499       n = MIN(n, length - totalLength);
00500 
00501       //Any data to copy?
00502       if(n > 0)
00503       {
00504          //Copy user data to send buffer
00505          tcpWriteTxBuffer(socket, socket->sndNxt + socket->sndUser, data, n);
00506 
00507          //Update the number of data buffered but not yet sent
00508          socket->sndUser += n;
00509          //Advance data pointer
00510          data += n;
00511          //Update byte counter
00512          totalLength += n;
00513 
00514          //Total number of data that have been written
00515          if(written != NULL)
00516             *written = totalLength;
00517 
00518          //Update TX events
00519          tcpUpdateEvents(socket);
00520 
00521          //To avoid a deadlock, it is necessary to have a timeout to force
00522          //transmission of data, overriding the SWS avoidance algorithm. In
00523          //practice, this timeout should seldom occur (see RFC 1122 4.2.3.4)
00524          if(socket->sndUser == n)
00525             tcpTimerStart(&socket->overrideTimer, TCP_OVERRIDE_TIMEOUT);
00526       }
00527 
00528       //The Nagle algorithm should be implemented to coalesce
00529       //short segments (refer to RFC 1122 4.2.3.4)
00530       tcpNagleAlgo(socket, flags);
00531 
00532       //Send as much data as possible
00533    } while(totalLength < length);
00534 
00535    //The SOCKET_FLAG_WAIT_ACK flag causes the function to
00536    //wait for acknowledgment from the remote side
00537    if(flags & SOCKET_FLAG_WAIT_ACK)
00538    {
00539       //Wait for the data to be acknowledged
00540       event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_ACKED, socket->timeout);
00541 
00542       //A timeout exception occurred?
00543       if(event != SOCKET_EVENT_TX_ACKED)
00544          return ERROR_TIMEOUT;
00545 
00546       //The connection was closed before an acknowledgment was received?
00547       if(socket->state != TCP_STATE_ESTABLISHED && socket->state != TCP_STATE_CLOSE_WAIT)
00548          return ERROR_NOT_CONNECTED;
00549    }
00550 
00551    //Successful write operation
00552    return NO_ERROR;
00553 }
00554 
00555 
00556 /**
00557  * @brief Receive data from a connected socket
00558  * @param[in] socket Handle that identifies a connected socket
00559  * @param[out] data Buffer where to store the incoming data
00560  * @param[in] size Maximum number of bytes that can be received
00561  * @param[out] received Number of bytes that have been received
00562  * @param[in] flags Set of flags that influences the behavior of this function
00563  * @return Error code
00564  **/
00565 
00566 error_t tcpReceive(Socket *socket, uint8_t *data,
00567    size_t size, size_t *received, uint_t flags)
00568 {
00569    uint_t i;
00570    uint_t n;
00571    uint_t event;
00572    uint32_t seqNum;
00573    systime_t timeout;
00574 
00575    //Retrieve the break character code
00576    char_t c = LSB(flags);
00577    //No data has been read yet
00578    *received = 0;
00579 
00580    //Check whether the socket is in the listening state
00581    if(socket->state == TCP_STATE_LISTEN)
00582       return ERROR_NOT_CONNECTED;
00583 
00584    //Read as much data as possible
00585    while(*received < size)
00586    {
00587       //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
00588       timeout = (flags & SOCKET_FLAG_DONT_WAIT) ? 0 : socket->timeout;
00589       //Wait for data to be available for reading
00590       event = tcpWaitForEvents(socket, SOCKET_EVENT_RX_READY, timeout);
00591 
00592       //A timeout exception occurred?
00593       if(event != SOCKET_EVENT_RX_READY)
00594          return ERROR_TIMEOUT;
00595 
00596       //Check current TCP state
00597       switch(socket->state)
00598       {
00599       //ESTABLISHED, FIN-WAIT-1 or FIN-WAIT-2 state?
00600       case TCP_STATE_ESTABLISHED:
00601       case TCP_STATE_FIN_WAIT_1:
00602       case TCP_STATE_FIN_WAIT_2:
00603          //Sequence number of the first byte to read
00604          seqNum = socket->rcvNxt - socket->rcvUser;
00605          //Data is available in the receive buffer
00606          break;
00607 
00608       //CLOSE-WAIT, LAST-ACK, CLOSING or TIME-WAIT state?
00609       case TCP_STATE_CLOSE_WAIT:
00610       case TCP_STATE_LAST_ACK:
00611       case TCP_STATE_CLOSING:
00612       case TCP_STATE_TIME_WAIT:
00613          //The user must be satisfied with data already on hand
00614          if(!socket->rcvUser)
00615          {
00616             if(*received > 0)
00617                return NO_ERROR;
00618             else
00619                return ERROR_END_OF_STREAM;
00620          }
00621 
00622          //Sequence number of the first byte to read
00623          seqNum = (socket->rcvNxt - 1) - socket->rcvUser;
00624          //Data is available in the receive buffer
00625          break;
00626 
00627       //CLOSED state?
00628       default:
00629          //The connection was reset by remote side?
00630          if(socket->resetFlag)
00631             return ERROR_CONNECTION_RESET;
00632          //The connection has not yet been established?
00633          if(!socket->closedFlag)
00634             return ERROR_NOT_CONNECTED;
00635 
00636          //The user must be satisfied with data already on hand
00637          if(!socket->rcvUser)
00638          {
00639             if(*received > 0)
00640                return NO_ERROR;
00641             else
00642                return ERROR_END_OF_STREAM;
00643          }
00644 
00645          //Sequence number of the first byte to read
00646          seqNum = (socket->rcvNxt - 1) - socket->rcvUser;
00647          //Data is available in the receive buffer
00648          break;
00649       }
00650 
00651       //Sanity check
00652       if(!socket->rcvUser)
00653          return ERROR_FAILURE;
00654 
00655       //Calculate the number of bytes to read at a time
00656       n = MIN(socket->rcvUser, size - *received);
00657       //Copy data from circular buffer
00658       tcpReadRxBuffer(socket, seqNum, data, n);
00659 
00660       //Read data until a break character is encountered?
00661       if(flags & SOCKET_FLAG_BREAK_CHAR)
00662       {
00663          //Search for the specified break character
00664          for(i = 0; i < n && data[i] != c; i++);
00665          //Adjust the number of data to read
00666          n = MIN(n, i + 1);
00667       }
00668 
00669       //Total number of data that have been read
00670       *received += n;
00671       //Remaining data still available in the receive buffer
00672       socket->rcvUser -= n;
00673 
00674       //Update the receive window
00675       tcpUpdateReceiveWindow(socket);
00676       //Update RX event state
00677       tcpUpdateEvents(socket);
00678 
00679       //The SOCKET_FLAG_BREAK_CHAR flag causes the function to stop reading
00680       //data as soon as the specified break character is encountered
00681       if(flags & SOCKET_FLAG_BREAK_CHAR)
00682       {
00683          //Check whether a break character has been found
00684          if(data[n - 1] == c)
00685             break;
00686       }
00687       //The SOCKET_FLAG_WAIT_ALL flag causes the function to return
00688       //only when the requested number of bytes have been read
00689       else if(!(flags & SOCKET_FLAG_WAIT_ALL))
00690       {
00691          break;
00692       }
00693 
00694       //Advance data pointer
00695       data += n;
00696    }
00697 
00698    //Successful read operation
00699    return NO_ERROR;
00700 }
00701 
00702 
00703 /**
00704  * @brief Shutdown gracefully reception, transmission, or both
00705  *
00706  * Note that socketShutdown() does not close the socket, and resources attached
00707  * to the socket will not be freed until socketClose() is invoked
00708  *
00709  * @param[in] socket Handle to a socket
00710  * @param[in] how Flag that describes what types of operation will no longer be allowed
00711  * @return Error code
00712  **/
00713 
00714 error_t tcpShutdown(Socket *socket, uint_t how)
00715 {
00716    error_t error;
00717    uint_t event;
00718 
00719    //Disable transmission?
00720    if(how == SOCKET_SD_SEND || how == SOCKET_SD_BOTH)
00721    {
00722       //Check current state
00723       switch(socket->state)
00724       {
00725       //CLOSED or LISTEN state?
00726       case TCP_STATE_CLOSED:
00727       case TCP_STATE_LISTEN:
00728          //Connection does not exist
00729          return ERROR_NOT_CONNECTED;
00730 
00731       //SYN-RECEIVED or ESTABLISHED state?
00732       case TCP_STATE_SYN_RECEIVED:
00733       case TCP_STATE_ESTABLISHED:
00734          //Flush the send buffer
00735          error = tcpSend(socket, NULL, 0, NULL, SOCKET_FLAG_NO_DELAY);
00736          //Any error to report?
00737          if(error)
00738             return error;
00739 
00740          //Make sure all the data has been sent out
00741          event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_DONE, socket->timeout);
00742          //Timeout error?
00743          if(event != SOCKET_EVENT_TX_DONE)
00744             return ERROR_TIMEOUT;
00745 
00746          //Send a FIN segment
00747          error = tcpSendSegment(socket, TCP_FLAG_FIN | TCP_FLAG_ACK,
00748             socket->sndNxt, socket->rcvNxt, 0, TRUE);
00749          //Failed to send FIN segment?
00750          if(error)
00751             return error;
00752 
00753          //Sequence number expected to be received
00754          socket->sndNxt++;
00755          //Switch to the FIN-WAIT1 state
00756          tcpChangeState(socket, TCP_STATE_FIN_WAIT_1);
00757 
00758          //Wait for the FIN to be acknowledged
00759          event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_SHUTDOWN, socket->timeout);
00760          //Timeout interval elapsed?
00761          if(event != SOCKET_EVENT_TX_SHUTDOWN)
00762             return ERROR_TIMEOUT;
00763 
00764          //Continue processing...
00765          break;
00766 
00767       //CLOSE-WAIT state?
00768       case TCP_STATE_CLOSE_WAIT:
00769          //Flush the send buffer
00770          error = tcpSend(socket, NULL, 0, NULL, SOCKET_FLAG_NO_DELAY);
00771          //Any error to report?
00772          if(error)
00773             return error;
00774 
00775          //Make sure all the data has been sent out
00776          event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_DONE, socket->timeout);
00777          //Timeout error?
00778          if(event != SOCKET_EVENT_TX_DONE)
00779             return ERROR_TIMEOUT;
00780 
00781          //Send a FIN segment
00782          error = tcpSendSegment(socket, TCP_FLAG_FIN | TCP_FLAG_ACK,
00783             socket->sndNxt, socket->rcvNxt, 0, TRUE);
00784          //Failed to send FIN segment?
00785          if(error)
00786             return error;
00787 
00788          //Sequence number expected to be received
00789          socket->sndNxt++;
00790          //Switch to the LAST-ACK state
00791          tcpChangeState(socket, TCP_STATE_LAST_ACK);
00792 
00793          //Wait for the FIN to be acknowledged
00794          event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_SHUTDOWN, socket->timeout);
00795          //Timeout interval elapsed?
00796          if(event != SOCKET_EVENT_TX_SHUTDOWN)
00797             return ERROR_TIMEOUT;
00798 
00799          //Continue processing...
00800          break;
00801 
00802       //FIN-WAIT-1, CLOSING or LAST-ACK state?
00803       case TCP_STATE_FIN_WAIT_1:
00804       case TCP_STATE_CLOSING:
00805       case TCP_STATE_LAST_ACK:
00806          //Wait for the FIN to be acknowledged
00807          event = tcpWaitForEvents(socket, SOCKET_EVENT_TX_SHUTDOWN, socket->timeout);
00808          //Timeout interval elapsed?
00809          if(event != SOCKET_EVENT_TX_SHUTDOWN)
00810             return ERROR_TIMEOUT;
00811 
00812          //Continue processing...
00813          break;
00814 
00815       //SYN-SENT, FIN-WAIT-2 or TIME-WAIT state?
00816       default:
00817          //Continue processing...
00818          break;
00819       }
00820    }
00821 
00822    //Disable reception?
00823    if(how == SOCKET_SD_RECEIVE || how == SOCKET_SD_BOTH)
00824    {
00825       //Check current state
00826       switch(socket->state)
00827       {
00828       //CLOSED or LISTEN state?
00829       case TCP_STATE_CLOSED:
00830       case TCP_STATE_LISTEN:
00831          //Connection does not exist
00832          return ERROR_NOT_CONNECTED;
00833 
00834       //SYN-SENT, SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1 or FIN-WAIT-2 state?
00835       case TCP_STATE_SYN_SENT:
00836       case TCP_STATE_SYN_RECEIVED:
00837       case TCP_STATE_ESTABLISHED:
00838       case TCP_STATE_FIN_WAIT_1:
00839       case TCP_STATE_FIN_WAIT_2:
00840          //Wait for a FIN to be received
00841          event = tcpWaitForEvents(socket, SOCKET_EVENT_RX_SHUTDOWN, socket->timeout);
00842          //Timeout interval elapsed?
00843          if(event != SOCKET_EVENT_RX_SHUTDOWN)
00844             return ERROR_TIMEOUT;
00845          //A FIN segment has been received
00846          break;
00847 
00848       //CLOSING, TIME-WAIT, CLOSE-WAIT or LAST-ACK state?
00849       default:
00850          //A FIN segment has already been received
00851          break;
00852       }
00853    }
00854 
00855    //Successful operation
00856    return NO_ERROR;
00857 }
00858 
00859 
00860 /**
00861  * @brief Abort an existing TCP connection
00862  * @param[in] socket Handle identifying the socket to close
00863  * @return Error code
00864  **/
00865 
00866 error_t tcpAbort(Socket *socket)
00867 {
00868    error_t error;
00869 
00870    //Check current state
00871    switch(socket->state)
00872    {
00873    //SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1
00874    //FIN-WAIT-2 or CLOSE-WAIT state?
00875    case TCP_STATE_SYN_RECEIVED:
00876    case TCP_STATE_ESTABLISHED:
00877    case TCP_STATE_FIN_WAIT_1:
00878    case TCP_STATE_FIN_WAIT_2:
00879    case TCP_STATE_CLOSE_WAIT:
00880       //Send a reset segment
00881       error = tcpSendSegment(socket, TCP_FLAG_RST, socket->sndNxt, 0, 0, FALSE);
00882       //Enter CLOSED state
00883       tcpChangeState(socket, TCP_STATE_CLOSED);
00884       //Delete TCB
00885       tcpDeleteControlBlock(socket);
00886       //Mark the socket as closed
00887       socket->type = SOCKET_TYPE_UNUSED;
00888       //Return status code
00889       return error;
00890 
00891    //TIME-WAIT state?
00892    case TCP_STATE_TIME_WAIT:
00893 #if (TCP_2MSL_TIMER > 0)
00894       //The user doe not own the socket anymore...
00895       socket->ownedFlag = FALSE;
00896       //TCB will be deleted and socket will be closed
00897       //when the 2MSL timer will elapse
00898       return NO_ERROR;
00899 #else
00900       //Enter CLOSED state
00901       tcpChangeState(socket, TCP_STATE_CLOSED);
00902       //Delete TCB
00903       tcpDeleteControlBlock(socket);
00904       //Mark the socket as closed
00905       socket->type = SOCKET_TYPE_UNUSED;
00906       //No error to report
00907       return NO_ERROR;
00908 #endif
00909 
00910    //Any other state?
00911    default:
00912       //Enter CLOSED state
00913       tcpChangeState(socket, TCP_STATE_CLOSED);
00914       //Delete TCB
00915       tcpDeleteControlBlock(socket);
00916       //Mark the socket as closed
00917       socket->type = SOCKET_TYPE_UNUSED;
00918       //No error to report
00919       return NO_ERROR;
00920    }
00921 }
00922 
00923 
00924 /**
00925  * @brief Get the current state of the TCP FSM
00926  * @param[in] socket Handle identifying the socket
00927  * @return TCP FSM state
00928  **/
00929 
00930 TcpState tcpGetState(Socket *socket)
00931 {
00932    TcpState state;
00933 
00934    //Get exclusive access
00935    osAcquireMutex(&netMutex);
00936 
00937    //Get TCP FSM current state
00938    state = socket->state;
00939 
00940    //Release exclusive access
00941    osReleaseMutex(&netMutex);
00942 
00943    //Return current state
00944    return state;
00945 }
00946 
00947 
00948 /**
00949  * @brief Kill the oldest socket in the TIME-WAIT state
00950  * @return Handle identifying the oldest TCP connection in the TIME-WAIT state.
00951  *   NULL is returned if no socket is currently in the TIME-WAIT state
00952  **/
00953 
00954 Socket *tcpKillOldestConnection(void)
00955 {
00956    uint_t i;
00957    Socket *socket;
00958    Socket *oldestSocket;
00959 
00960    //Keep track of the oldest socket in the TIME-WAIT state
00961    oldestSocket = NULL;
00962 
00963    //Loop through socket descriptors
00964    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00965    {
00966       //Point to the current socket descriptor
00967       socket = &socketTable[i];
00968 
00969       //TCP connection found?
00970       if(socket->type == SOCKET_TYPE_STREAM)
00971       {
00972          //Check current state
00973          if(socket->state == TCP_STATE_TIME_WAIT)
00974          {
00975             //Keep track of the oldest socket in the TIME-WAIT state
00976             if(oldestSocket == NULL)
00977             {
00978                //Save socket handle
00979                oldestSocket = socket;
00980             }
00981             else if(timeCompare(socket->timeWaitTimer.startTime,
00982                oldestSocket->timeWaitTimer.startTime) < 0)
00983             {
00984                //Save socket handle
00985                oldestSocket = socket;
00986             }
00987          }
00988       }
00989    }
00990 
00991    //Any connection in the TIME-WAIT state?
00992    if(oldestSocket != NULL)
00993    {
00994       //Enter CLOSED state
00995       tcpChangeState(oldestSocket, TCP_STATE_CLOSED);
00996       //Delete TCB
00997       tcpDeleteControlBlock(oldestSocket);
00998       //Mark the socket as closed
00999       oldestSocket->type = SOCKET_TYPE_UNUSED;
01000    }
01001 
01002    //The oldest connection in the TIME-WAIT state can be reused
01003    //when the socket table runs out of space
01004    return oldestSocket;
01005 }
01006 
01007 #endif
01008