Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp_fsm.c Source File

tcp_fsm.c

Go to the documentation of this file.
00001 /**
00002  * @file tcp_fsm.c
00003  * @brief TCP finite state machine
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  * The TCP state machine progresses from one state to another in response to
00028  * events (user calls, incoming segments and timeouts). This file describes
00029  * the state transitions caused by incoming segments. Refer to the
00030  * following RFCs for complete details:
00031  * - RFC 793: Transmission Control Protocol
00032  * - RFC 1122: Requirements for Internet Hosts - Communication Layers
00033  *
00034  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00035  * @version 1.7.6
00036  **/
00037 
00038 //Switch to the appropriate trace level
00039 #define TRACE_LEVEL TCP_TRACE_LEVEL
00040 
00041 //Dependencies
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include "core/net.h"
00045 #include "core/ip.h"
00046 #include "core/socket.h"
00047 #include "core/tcp.h"
00048 #include "core/tcp_fsm.h"
00049 #include "core/tcp_misc.h"
00050 #include "core/tcp_timer.h"
00051 #include "ipv4/ipv4.h"
00052 #include "ipv6/ipv6.h"
00053 #include "mibs/mib2_module.h"
00054 #include "date_time.h"
00055 #include "debug.h"
00056 
00057 //Check TCP/IP stack configuration
00058 #if (TCP_SUPPORT == ENABLED)
00059 
00060 
00061 /**
00062  * @brief Incoming TCP segment processing
00063  * @param[in] interface Underlying network interface
00064  * @param[in] pseudoHeader TCP pseudo header
00065  * @param[in] buffer Multi-part buffer that holds the incoming TCP segment
00066  * @param[in] offset Offset to the first byte of the TCP header
00067  **/
00068 
00069 void tcpProcessSegment(NetInterface *interface,
00070    IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset)
00071 {
00072    uint_t i;
00073    size_t length;
00074    Socket *socket;
00075    Socket *passiveSocket;
00076    TcpHeader *segment;
00077 
00078    //Total number of segments received, including those received in error
00079    MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpInSegs, 1);
00080    MIB2_INC_COUNTER64(mib2Base.tcpGroup.tcpHCInSegs, 1);
00081 
00082    //A TCP implementation must silently discard an incoming
00083    //segment that is addressed to a broadcast or multicast
00084    //address (see RFC 1122 4.2.3.10)
00085 #if (IPV4_SUPPORT == ENABLED)
00086    if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
00087    {
00088       //Ensure the destination address is not a broadcast address
00089       if(ipv4IsBroadcastAddr(interface, pseudoHeader->ipv4Data.destAddr))
00090          return;
00091       //Ensure the destination address is not a multicast address
00092       if(ipv4IsMulticastAddr(pseudoHeader->ipv4Data.destAddr))
00093          return;
00094    }
00095    else
00096 #endif
00097 #if (IPV6_SUPPORT == ENABLED)
00098    if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
00099    {
00100       //Ensure the destination address is not a multicast address
00101       if(ipv6IsMulticastAddr(&pseudoHeader->ipv6Data.destAddr))
00102          return;
00103    }
00104    else
00105 #endif
00106    {
00107       //This should never occur...
00108       return;
00109    }
00110 
00111    //Retrieve the length of the TCP segment
00112    length = netBufferGetLength(buffer) - offset;
00113 
00114    //Point to the TCP header
00115    segment = netBufferAt(buffer, offset);
00116    //Sanity check
00117    if(segment == NULL)
00118       return;
00119 
00120    //Ensure the TCP header is valid
00121    if(length < sizeof(TcpHeader))
00122    {
00123       //Debug message
00124       TRACE_WARNING("TCP segment length is invalid!\r\n");
00125       //Total number of segments received in error
00126       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpInErrs, 1);
00127       //Exit immediately
00128       return;
00129    }
00130 
00131    //Check header length
00132    if(segment->dataOffset < 5 || ((size_t) segment->dataOffset * 4) > length)
00133    {
00134       //Debug message
00135       TRACE_WARNING("TCP header length is invalid!\r\n");
00136       //Total number of segments received in error
00137       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpInErrs, 1);
00138       //Exit immediately
00139       return;
00140    }
00141 
00142    //Verify TCP checksum
00143    if(ipCalcUpperLayerChecksumEx(pseudoHeader->data,
00144       pseudoHeader->length, buffer, offset, length) != 0x0000)
00145    {
00146       //Debug message
00147       TRACE_WARNING("Wrong TCP header checksum!\r\n");
00148       //Total number of segments received in error
00149       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpInErrs, 1);
00150       //Exit immediately
00151       return;
00152    }
00153 
00154    //No matching socket in the LISTEN state for the moment
00155    passiveSocket = NULL;
00156 
00157    //Look through opened sockets
00158    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00159    {
00160       //Point to the current socket
00161       socket = socketTable + i;
00162 
00163       //TCP socket found?
00164       if(socket->type != SOCKET_TYPE_STREAM)
00165          continue;
00166       //Check whether the socket is bound to a particular interface
00167       if(socket->interface && socket->interface != interface)
00168          continue;
00169       //Check destination port number
00170       if(socket->localPort != ntohs(segment->destPort))
00171          continue;
00172 
00173 #if (IPV4_SUPPORT == ENABLED)
00174       //An IPv4 packet was received?
00175       if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
00176       {
00177          //Destination IP address filtering
00178          if(socket->localIpAddr.length)
00179          {
00180             //An IPv4 address is expected
00181             if(socket->localIpAddr.length != sizeof(Ipv4Addr))
00182                continue;
00183             //Filter out non-matching addresses
00184             if(socket->localIpAddr.ipv4Addr != pseudoHeader->ipv4Data.destAddr)
00185                continue;
00186          }
00187          //Source IP address filtering
00188          if(socket->remoteIpAddr.length)
00189          {
00190             //An IPv4 address is expected
00191             if(socket->remoteIpAddr.length != sizeof(Ipv4Addr))
00192                continue;
00193             //Filter out non-matching addresses
00194             if(socket->remoteIpAddr.ipv4Addr != pseudoHeader->ipv4Data.srcAddr)
00195                continue;
00196          }
00197       }
00198       else
00199 #endif
00200 #if (IPV6_SUPPORT == ENABLED)
00201       //An IPv6 packet was received?
00202       if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
00203       {
00204          //Destination IP address filtering
00205          if(socket->localIpAddr.length)
00206          {
00207             //An IPv6 address is expected
00208             if(socket->localIpAddr.length != sizeof(Ipv6Addr))
00209                continue;
00210             //Filter out non-matching addresses
00211             if(!ipv6CompAddr(&socket->localIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.destAddr))
00212                continue;
00213          }
00214          //Source IP address filtering
00215          if(socket->remoteIpAddr.length)
00216          {
00217             //An IPv6 address is expected
00218             if(socket->remoteIpAddr.length != sizeof(Ipv6Addr))
00219                continue;
00220             //Filter out non-matching addresses
00221             if(!ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.srcAddr))
00222                continue;
00223          }
00224       }
00225       else
00226 #endif
00227       //An invalid packet was received?
00228       {
00229          //This should never occur...
00230          continue;
00231       }
00232 
00233       //Keep track of the first matching socket in the LISTEN state
00234       if(socket->state == TCP_STATE_LISTEN && !passiveSocket)
00235          passiveSocket = socket;
00236       //Source port filtering
00237       if(socket->remotePort != ntohs(segment->srcPort))
00238          continue;
00239 
00240       //A matching socket has been found
00241       break;
00242    }
00243 
00244    //If no matching socket has been found then try to
00245    //use the first matching socket in the LISTEN state
00246    if(i >= SOCKET_MAX_COUNT) socket = passiveSocket;
00247 
00248    //Offset to the first data byte
00249    offset += segment->dataOffset * 4;
00250    //Calculate the length of the data
00251    length -= segment->dataOffset * 4;
00252 
00253    //Debug message
00254    TRACE_DEBUG("%s: TCP segment received (%" PRIuSIZE " data bytes)...\r\n",
00255       formatSystemTime(osGetSystemTime(), NULL), length);
00256 
00257    //Dump TCP header contents for debugging purpose
00258    if(socket == NULL)
00259       tcpDumpHeader(segment, length, 0, 0);
00260    else
00261       tcpDumpHeader(segment, length, socket->irs, socket->iss);
00262 
00263    //Convert from network byte order to host byte order
00264    segment->srcPort = ntohs(segment->srcPort);
00265    segment->destPort = ntohs(segment->destPort);
00266    segment->seqNum = ntohl(segment->seqNum);
00267    segment->ackNum = ntohl(segment->ackNum);
00268    segment->window = ntohs(segment->window);
00269    segment->urgentPointer = ntohs(segment->urgentPointer);
00270 
00271    //Specified port is unreachable?
00272    if(socket == NULL)
00273    {
00274       //An incoming segment not containing a RST causes
00275       //a reset to be sent in response
00276       if(!(segment->flags & TCP_FLAG_RST))
00277          tcpSendResetSegment(interface, pseudoHeader, segment, length);
00278 
00279       //Return immediately
00280       return;
00281    }
00282 
00283    //Check current state
00284    switch(socket->state)
00285    {
00286    //Process CLOSED state
00287    case TCP_STATE_CLOSED:
00288       //This is the default state that each connection starts in before
00289       //the process of establishing it begins
00290       tcpStateClosed(interface, pseudoHeader, segment, length);
00291       break;
00292    //Process LISTEN state
00293    case TCP_STATE_LISTEN:
00294       //A device (normally a server) is waiting to receive a synchronize (SYN)
00295       //message from a client. It has not yet sent its own SYN message
00296       tcpStateListen(socket, interface, pseudoHeader, segment, length);
00297       break;
00298    //Process SYN_SENT state
00299    case TCP_STATE_SYN_SENT:
00300       //The device (normally a client) has sent a synchronize (SYN) message and
00301       //is waiting for a matching SYN from the other device (usually a server)
00302       tcpStateSynSent(socket, segment, length);
00303       break;
00304    //Process SYN_RECEIVED state
00305    case TCP_STATE_SYN_RECEIVED:
00306       //The device has both received a SYN from its partner and sent its own SYN.
00307       //It is now waiting for an ACK to its SYN to finish connection setup
00308       tcpStateSynReceived(socket, segment, buffer, offset, length);
00309       break;
00310    //Process ESTABLISHED state
00311    case TCP_STATE_ESTABLISHED:
00312       //Data can be exchanged freely once both devices in the connection enter
00313       //this state. This will continue until the connection is closed
00314       tcpStateEstablished(socket, segment, buffer, offset, length);
00315       break;
00316    //Process CLOSE_WAIT state
00317    case TCP_STATE_CLOSE_WAIT:
00318       //The device has received a close request (FIN) from the other device. It
00319       //must now wait for the application to acknowledge this request and
00320       //generate a matching request
00321       tcpStateCloseWait(socket, segment, length);
00322       break;
00323    //Process LAST_ACK state
00324    case TCP_STATE_LAST_ACK:
00325       //A device that has already received a close request and acknowledged it,
00326       //has sent its own FIN and is waiting for an ACK to this request
00327       tcpStateLastAck(socket, segment, length);
00328       break;
00329    //Process FIN_WAIT_1 state
00330    case TCP_STATE_FIN_WAIT_1:
00331       //A device in this state is waiting for an ACK for a FIN it has sent, or
00332       //is waiting for a connection termination request from the other device
00333       tcpStateFinWait1(socket, segment, buffer, offset, length);
00334       break;
00335    //Process FIN_WAIT_2 state
00336    case TCP_STATE_FIN_WAIT_2:
00337       //A device in this state has received an ACK for its request to terminate the
00338       //connection and is now waiting for a matching FIN from the other device
00339       tcpStateFinWait2(socket, segment, buffer, offset, length);
00340       break;
00341    //Process CLOSING state
00342    case TCP_STATE_CLOSING:
00343       //The device has received a FIN from the other device and sent an ACK for
00344       //it, but not yet received an ACK for its own FIN message
00345       tcpStateClosing(socket, segment, length);
00346       break;
00347    //Process TIME_WAIT state
00348    case TCP_STATE_TIME_WAIT:
00349       //The device has now received a FIN from the other device and acknowledged
00350       //it, and sent its own FIN and received an ACK for it. We are done, except
00351       //for waiting to ensure the ACK is received and prevent potential overlap
00352       //with new connections
00353       tcpStateTimeWait(socket, segment, length);
00354       break;
00355    //Invalid state...
00356    default:
00357       //Back to the CLOSED state
00358       tcpChangeState(socket, TCP_STATE_CLOSED);
00359       //Silently discard incoming packet
00360       break;
00361    }
00362 }
00363 
00364 
00365 /**
00366  * @brief CLOSED state
00367  *
00368  * This is the default state that each connection starts in before
00369  * the process of establishing it begins
00370  *
00371  * @param[in] interface Underlying network interface
00372  * @param[in] pseudoHeader TCP pseudo header
00373  * @param[in] segment Incoming TCP segment
00374  * @param[in] length Length of the segment data
00375  **/
00376 
00377 void tcpStateClosed(NetInterface *interface,
00378    IpPseudoHeader *pseudoHeader, TcpHeader *segment, size_t length)
00379 {
00380    //Debug message
00381    TRACE_DEBUG("TCP FSM: CLOSED state\r\n");
00382 
00383    //An incoming segment not containing a RST causes
00384    //a reset to be sent in response
00385    if(!(segment->flags & TCP_FLAG_RST))
00386       tcpSendResetSegment(interface, pseudoHeader, segment, length);
00387 }
00388 
00389 
00390 /**
00391  * @brief LISTEN state
00392  *
00393  * A device (normally a server) is waiting to receive a synchronize (SYN)
00394  * message from a client. It has not yet sent its own SYN message
00395  *
00396  * @param[in] socket Handle referencing the current socket
00397  * @param[in] interface Underlying network interface
00398  * @param[in] pseudoHeader TCP pseudo header
00399  * @param[in] segment Incoming TCP segment
00400  * @param[in] length Length of the segment data
00401  **/
00402 
00403 void tcpStateListen(Socket *socket, NetInterface *interface,
00404    IpPseudoHeader *pseudoHeader, TcpHeader *segment, size_t length)
00405 {
00406    uint_t i;
00407    TcpOption *option;
00408    TcpSynQueueItem *queueItem;
00409 
00410    //Debug message
00411    TRACE_DEBUG("TCP FSM: LISTEN state\r\n");
00412 
00413    //An incoming RST should be ignored
00414    if(segment->flags & TCP_FLAG_RST)
00415       return;
00416 
00417    //Any acknowledgment is bad if it arrives on a connection
00418    //still in the LISTEN state
00419    if(segment->flags & TCP_FLAG_ACK)
00420    {
00421       //A reset segment should be formed for any arriving ACK-bearing segment
00422       tcpSendResetSegment(interface, pseudoHeader, segment, length);
00423       //Return immediately
00424       return;
00425    }
00426 
00427    //Check the SYN bit
00428    if(segment->flags & TCP_FLAG_SYN)
00429    {
00430       //The SYN queue is empty?
00431       if(!socket->synQueue)
00432       {
00433          //Allocate memory to save incoming data
00434          queueItem = memPoolAlloc(sizeof(TcpSynQueueItem));
00435          //Add the newly created item to the queue
00436          socket->synQueue = queueItem;
00437       }
00438       else
00439       {
00440          //Point to the very first item
00441          queueItem = socket->synQueue;
00442 
00443          //Reach the last item in the receive queue
00444          for(i = 1; queueItem->next; i++)
00445             queueItem = queueItem->next;
00446 
00447          //Make sure the receive queue is not full
00448          if(i >= socket->synQueueSize)
00449             return;
00450 
00451          //Allocate memory to save incoming data
00452          queueItem->next = memPoolAlloc(sizeof(TcpSynQueueItem));
00453          //Point to the newly created item
00454          queueItem = queueItem->next;
00455       }
00456 
00457       //Failed to allocate memory?
00458       if(queueItem == NULL)
00459          return;
00460 
00461 #if (IPV4_SUPPORT == ENABLED)
00462       //IPv4 is currently used?
00463       if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
00464       {
00465          //Save the source IPv4 address
00466          queueItem->srcAddr.length = sizeof(Ipv4Addr);
00467          queueItem->srcAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
00468          //Save the destination IPv4 address
00469          queueItem->destAddr.length = sizeof(Ipv4Addr);
00470          queueItem->destAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
00471       }
00472       else
00473 #endif
00474 #if (IPV6_SUPPORT == ENABLED)
00475       //IPv6 is currently used?
00476       if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
00477       {
00478          //Save the source IPv6 address
00479          queueItem->srcAddr.length = sizeof(Ipv6Addr);
00480          queueItem->srcAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
00481          //Save the destination IPv6 address
00482          queueItem->destAddr.length = sizeof(Ipv6Addr);
00483          queueItem->destAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
00484       }
00485       else
00486 #endif
00487       //Invalid pseudo header?
00488       {
00489          //This should never occur...
00490          return;
00491       }
00492 
00493       //Initialize next field
00494       queueItem->next = NULL;
00495       //Underlying network interface
00496       queueItem->interface = interface;
00497       //Save the port number of the client
00498       queueItem->srcPort = segment->srcPort;
00499       //Save the initial sequence number
00500       queueItem->isn = segment->seqNum;
00501       //Default MSS value
00502       queueItem->mss = MIN(TCP_DEFAULT_MSS, TCP_MAX_MSS);
00503 
00504       //Get the maximum segment size
00505       option = tcpGetOption(segment, TCP_OPTION_MAX_SEGMENT_SIZE);
00506       //Specified option found?
00507       if(option != NULL && option->length == 4)
00508       {
00509          //Retrieve MSS value
00510          memcpy(&queueItem->mss, option->value, 2);
00511          //Convert from network byte order to host byte order
00512          queueItem->mss = ntohs(queueItem->mss);
00513 
00514          //Debug message
00515          TRACE_DEBUG("Remote host MSS = %" PRIu16 "\r\n", queueItem->mss);
00516 
00517          //Make sure that the MSS advertised by the peer is acceptable
00518          queueItem->mss = MIN(queueItem->mss, TCP_MAX_MSS);
00519          queueItem->mss = MAX(queueItem->mss, TCP_MIN_MSS);
00520       }
00521 
00522       //Notify user that a connection request is pending
00523       tcpUpdateEvents(socket);
00524 
00525       //The rest of the processing described in RFC 793 will be done
00526       //asynchronously when socketAccept() function is called
00527    }
00528 }
00529 
00530 
00531 /**
00532  * @brief SYN-SENT state
00533  *
00534  * The device (normally a client) has sent a synchronize (SYN) message and
00535  * is waiting for a matching SYN from the other device (usually a server)
00536  *
00537  * @param[in] socket Handle referencing the current socket
00538  * @param[in] segment Incoming TCP segment
00539  * @param[in] length Length of the segment data
00540  **/
00541 
00542 void tcpStateSynSent(Socket *socket, TcpHeader *segment, size_t length)
00543 {
00544    TcpOption *option;
00545 
00546    //Debug message
00547    TRACE_DEBUG("TCP FSM: SYN-SENT state\r\n");
00548 
00549    //Check the ACK bit
00550    if(segment->flags & TCP_FLAG_ACK)
00551    {
00552       //Make sure the acknowledgment number is valid
00553       if(segment->ackNum != socket->sndNxt)
00554       {
00555          //Send a reset segment unless the RST bit is set
00556          if(!(segment->flags & TCP_FLAG_RST))
00557             tcpSendSegment(socket, TCP_FLAG_RST, segment->ackNum, 0, 0, FALSE);
00558 
00559          //Drop the segment and return
00560          return;
00561       }
00562    }
00563 
00564    //Check the RST bit
00565    if(segment->flags & TCP_FLAG_RST)
00566    {
00567       //Make sure the ACK is acceptable
00568       if(segment->flags & TCP_FLAG_ACK)
00569       {
00570          //Enter CLOSED state
00571          tcpChangeState(socket, TCP_STATE_CLOSED);
00572 
00573          //Number of times TCP connections have made a direct transition to the
00574          //CLOSED state from either the SYN-SENT state or the SYN-RECEIVED state
00575          MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpAttemptFails, 1);
00576       }
00577 
00578       //Drop the segment and return
00579       return;
00580    }
00581 
00582    //Check the SYN bit
00583    if(segment->flags & TCP_FLAG_SYN)
00584    {
00585       //Save initial receive sequence number
00586       socket->irs = segment->seqNum;
00587       //Initialize RCV.NXT pointer
00588       socket->rcvNxt = segment->seqNum + 1;
00589 
00590       //If there is an ACK, SND.UNA should be advanced to equal SEG.ACK
00591       if(segment->flags & TCP_FLAG_ACK)
00592          socket->sndUna = segment->ackNum;
00593 
00594       //Compute retransmission timeout
00595       tcpComputeRto(socket);
00596 
00597       //Any segments on the retransmission queue which are thereby
00598       //acknowledged should be removed
00599       tcpUpdateRetransmitQueue(socket);
00600 
00601       //Get the maximum segment size
00602       option = tcpGetOption(segment, TCP_OPTION_MAX_SEGMENT_SIZE);
00603 
00604       //Specified option found?
00605       if(option != NULL && option->length == 4)
00606       {
00607          //Retrieve MSS value
00608          memcpy(&socket->smss, option->value, 2);
00609          //Convert from network byte order to host byte order
00610          socket->smss = ntohs(socket->smss);
00611 
00612          //Debug message
00613          TRACE_DEBUG("Remote host MSS = %" PRIu16 "\r\n", socket->smss);
00614 
00615          //Make sure that the MSS advertised by the peer is acceptable
00616          socket->smss = MIN(socket->smss, TCP_MAX_MSS);
00617          socket->smss = MAX(socket->smss, TCP_MIN_MSS);
00618       }
00619 
00620 #if (TCP_CONGEST_CONTROL_SUPPORT == ENABLED)
00621       //Initial congestion window
00622       socket->cwnd = MIN(TCP_INITIAL_WINDOW * socket->smss, socket->txBufferSize);
00623 #endif
00624 
00625       //Check whether our SYN has been acknowledged (SND.UNA > ISS)
00626       if(TCP_CMP_SEQ(socket->sndUna, socket->iss) > 0)
00627       {
00628          //Update the send window before entering ESTABLISHED state (see RFC 1122 4.2.2.20)
00629          socket->sndWnd = segment->window;
00630          socket->sndWl1 = segment->seqNum;
00631          socket->sndWl2 = segment->ackNum;
00632 
00633          //Maximum send window it has seen so far on the connection
00634          socket->maxSndWnd = segment->window;
00635 
00636          //Form an ACK segment and send it
00637          tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
00638          //Switch to the ESTABLISHED state
00639          tcpChangeState(socket, TCP_STATE_ESTABLISHED);
00640       }
00641       else
00642       {
00643          //Form an SYN ACK segment and send it
00644          tcpSendSegment(socket, TCP_FLAG_SYN | TCP_FLAG_ACK, socket->iss, socket->rcvNxt, 0, TRUE);
00645          //Enter SYN-RECEIVED state
00646          tcpChangeState(socket, TCP_STATE_SYN_RECEIVED);
00647       }
00648    }
00649 }
00650 
00651 
00652 /**
00653  * @brief SYN-RECEIVED state
00654  *
00655  * The device has both received a SYN from its partner and sent its own SYN.
00656  * It is now waiting for an ACK to its SYN to finish connection setup
00657  *
00658  * @param[in] socket Handle referencing the current socket
00659  * @param[in] segment Incoming TCP segment
00660  * @param[in] buffer Multi-part buffer containing the incoming TCP segment
00661  * @param[in] offset Offset to the first data byte
00662  * @param[in] length Length of the segment data
00663  **/
00664 
00665 void tcpStateSynReceived(Socket *socket, TcpHeader *segment,
00666    const NetBuffer *buffer, size_t offset, size_t length)
00667 {
00668    //Debug message
00669    TRACE_DEBUG("TCP FSM: SYN-RECEIVED state\r\n");
00670 
00671    //First check sequence number
00672    if(tcpCheckSequenceNumber(socket, segment, length))
00673       return;
00674 
00675    //Check the RST bit
00676    if(segment->flags & TCP_FLAG_RST)
00677    {
00678       //Return to CLOSED state
00679       tcpChangeState(socket, TCP_STATE_CLOSED);
00680 
00681       //Number of times TCP connections have made a direct transition to the
00682       //CLOSED state from either the SYN-SENT state or the SYN-RECEIVED state
00683       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpAttemptFails, 1);
00684 
00685       //Return immediately
00686       return;
00687    }
00688 
00689    //Check the SYN bit
00690    if(tcpCheckSyn(socket, segment, length))
00691       return;
00692 
00693    //If the ACK bit is off drop the segment and return
00694    if(!(segment->flags & TCP_FLAG_ACK))
00695       return;
00696 
00697    //Make sure the acknowledgment number is valid
00698    if(segment->ackNum != socket->sndNxt)
00699    {
00700       //If the segment acknowledgment is not acceptable, form a reset
00701       //segment and send it
00702       tcpSendSegment(socket, TCP_FLAG_RST, segment->ackNum, 0, 0, FALSE);
00703 
00704       //Drop the segment and return
00705       return;
00706    }
00707 
00708    //Update the send window before entering ESTABLISHED state (see RFC 1122 4.2.2.20)
00709    socket->sndWnd = segment->window;
00710    socket->sndWl1 = segment->seqNum;
00711    socket->sndWl2 = segment->ackNum;
00712 
00713    //Maximum send window it has seen so far on the connection
00714    socket->maxSndWnd = segment->window;
00715 
00716    //Enter ESTABLISHED state
00717    tcpChangeState(socket, TCP_STATE_ESTABLISHED);
00718    //And continue processing...
00719    tcpStateEstablished(socket, segment, buffer, offset, length);
00720 }
00721 
00722 
00723 /**
00724  * @brief ESTABLISHED state
00725  *
00726  * Data can be exchanged freely once both devices in the connection enter
00727  * this state. This will continue until the connection is closed
00728  *
00729  * @param[in] socket Handle referencing the current socket
00730  * @param[in] segment Incoming TCP segment
00731  * @param[in] buffer Multi-part buffer containing the incoming TCP segment
00732  * @param[in] offset Offset to the first data byte
00733  * @param[in] length Length of the segment data
00734  **/
00735 
00736 void tcpStateEstablished(Socket *socket, TcpHeader *segment,
00737    const NetBuffer *buffer, size_t offset, size_t length)
00738 {
00739    uint_t flags = 0;
00740 
00741    //Debug message
00742    TRACE_DEBUG("TCP FSM: ESTABLISHED state\r\n");
00743 
00744    //First check sequence number
00745    if(tcpCheckSequenceNumber(socket, segment, length))
00746       return;
00747 
00748    //Check the RST bit
00749    if(segment->flags & TCP_FLAG_RST)
00750    {
00751       //Switch to the CLOSED state
00752       tcpChangeState(socket, TCP_STATE_CLOSED);
00753 
00754       //Number of times TCP connections have made a direct transition to the
00755       //CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state
00756       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpEstabResets, 1);
00757 
00758       //Return immediately
00759       return;
00760    }
00761 
00762    //Check the SYN bit
00763    if(tcpCheckSyn(socket, segment, length))
00764       return;
00765    //Check the ACK field
00766    if(tcpCheckAck(socket, segment, length))
00767       return;
00768    //Process the segment text
00769    if(length > 0)
00770       tcpProcessSegmentData(socket, segment, buffer, offset, length);
00771 
00772    //Check the FIN bit
00773    if(segment->flags & TCP_FLAG_FIN)
00774    {
00775       //The FIN can only be acknowledged if all the segment data
00776       //has been successfully transferred to the receive buffer
00777       if(socket->rcvNxt == (segment->seqNum + length))
00778       {
00779          //Advance RCV.NXT over the FIN
00780          socket->rcvNxt++;
00781          //Send an acknowledgment for the FIN
00782          tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
00783          //Switch to the CLOSE-WAIT state
00784          tcpChangeState(socket, TCP_STATE_CLOSE_WAIT);
00785       }
00786    }
00787 
00788 #if (TCP_CONGEST_CONTROL_SUPPORT == ENABLED)
00789    //Duplicate AK received?
00790    if(socket->dupAckCount > 0)
00791       flags = SOCKET_FLAG_NO_DELAY;
00792 #endif
00793 
00794    //The Nagle algorithm should be implemented to coalesce
00795    //short segments (refer to RFC 1122 4.2.3.4)
00796    tcpNagleAlgo(socket, flags);
00797 }
00798 
00799 
00800 /**
00801  * @brief CLOSE-WAIT state
00802  *
00803  * The device has received a close request (FIN) from the other device. It
00804  * must now wait for the application to acknowledge this request and
00805  * generate a matching request
00806  *
00807  * @param[in] socket Handle referencing the current socket
00808  * @param[in] segment Incoming TCP segment
00809  * @param[in] length Length of the segment data
00810  **/
00811 
00812 void tcpStateCloseWait(Socket *socket, TcpHeader *segment, size_t length)
00813 {
00814    uint_t flags = 0;
00815 
00816    //Debug message
00817    TRACE_DEBUG("TCP FSM: CLOSE-WAIT state\r\n");
00818 
00819    //First check sequence number
00820    if(tcpCheckSequenceNumber(socket, segment, length))
00821       return;
00822 
00823    //Check the RST bit
00824    if(segment->flags & TCP_FLAG_RST)
00825    {
00826       //Switch to the CLOSED state
00827       tcpChangeState(socket, TCP_STATE_CLOSED);
00828 
00829       //Number of times TCP connections have made a direct transition to the
00830       //CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state
00831       MIB2_INC_COUNTER32(mib2Base.tcpGroup.tcpEstabResets, 1);
00832 
00833       //Return immediately
00834       return;
00835    }
00836 
00837    //Check the SYN bit
00838    if(tcpCheckSyn(socket, segment, length))
00839       return;
00840    //Check the ACK field
00841    if(tcpCheckAck(socket, segment, length))
00842       return;
00843 
00844 #if (TCP_CONGEST_CONTROL_SUPPORT == ENABLED)
00845    //Duplicate AK received?
00846    if(socket->dupAckCount > 0)
00847       flags = SOCKET_FLAG_NO_DELAY;
00848 #endif
00849 
00850    //The Nagle algorithm should be implemented to coalesce
00851    //short segments (refer to RFC 1122 4.2.3.4)
00852    tcpNagleAlgo(socket, flags);
00853 }
00854 
00855 
00856 /**
00857  * @brief LAST-ACK state
00858  *
00859  * A device that has already received a close request and acknowledged it,
00860  * has sent its own FIN and is waiting for an ACK to this request
00861  *
00862  * @param[in] socket Handle referencing the current socket
00863  * @param[in] segment Incoming TCP segment
00864  * @param[in] length Length of the segment data
00865  **/
00866 
00867 void tcpStateLastAck(Socket *socket, TcpHeader *segment, size_t length)
00868 {
00869    //Debug message
00870    TRACE_DEBUG("TCP FSM: LAST-ACK state\r\n");
00871 
00872    //First check sequence number
00873    if(tcpCheckSequenceNumber(socket, segment, length))
00874       return;
00875 
00876    //Check the RST bit
00877    if(segment->flags & TCP_FLAG_RST)
00878    {
00879       //Enter CLOSED state
00880       tcpChangeState(socket, TCP_STATE_CLOSED);
00881       //Return immediately
00882       return;
00883    }
00884 
00885    //Check the SYN bit
00886    if(tcpCheckSyn(socket, segment, length))
00887       return;
00888    //If the ACK bit is off drop the segment and return
00889    if(!(segment->flags & TCP_FLAG_ACK))
00890       return;
00891 
00892    //The only thing that can arrive in this state is an
00893    //acknowledgment of our FIN
00894    if(segment->ackNum == socket->sndNxt)
00895    {
00896       //Enter CLOSED state
00897       tcpChangeState(socket, TCP_STATE_CLOSED);
00898    }
00899 }
00900 
00901 
00902 /**
00903  * @brief FIN-WAIT-1 state
00904  *
00905  * A device in this state is waiting for an ACK for a FIN it has sent, or
00906  * is waiting for a connection termination request from the other device
00907  *
00908  * @param[in] socket Handle referencing the current socket
00909  * @param[in] segment Incoming TCP segment
00910  * @param[in] buffer Multi-part buffer containing the incoming TCP segment
00911  * @param[in] offset Offset to the first data byte
00912  * @param[in] length Length of the segment data
00913  **/
00914 
00915 void tcpStateFinWait1(Socket *socket, TcpHeader *segment,
00916    const NetBuffer *buffer, size_t offset, size_t length)
00917 {
00918    //Debug message
00919    TRACE_DEBUG("TCP FSM: FIN-WAIT-1 state\r\n");
00920 
00921    //First check sequence number
00922    if(tcpCheckSequenceNumber(socket, segment, length))
00923       return;
00924 
00925    //Check the RST bit
00926    if(segment->flags & TCP_FLAG_RST)
00927    {
00928       //Switch to the CLOSED state
00929       tcpChangeState(socket, TCP_STATE_CLOSED);
00930       //Return immediately
00931       return;
00932    }
00933 
00934    //Check the SYN bit
00935    if(tcpCheckSyn(socket, segment, length))
00936       return;
00937    //Check the ACK field
00938    if(tcpCheckAck(socket, segment, length))
00939       return;
00940 
00941    //Check whether our FIN is now acknowledged
00942    if(segment->ackNum == socket->sndNxt)
00943    {
00944       //Start the FIN-WAIT-2 timer to prevent the connection
00945       //from staying in the FIN-WAIT-2 state forever
00946       tcpTimerStart(&socket->finWait2Timer, TCP_FIN_WAIT_2_TIMER);
00947       //enter FIN-WAIT-2 and continue processing in that state
00948       tcpChangeState(socket, TCP_STATE_FIN_WAIT_2);
00949    }
00950 
00951    //Process the segment text
00952    if(length > 0)
00953       tcpProcessSegmentData(socket, segment, buffer, offset, length);
00954 
00955    //Check the FIN bit
00956    if(segment->flags & TCP_FLAG_FIN)
00957    {
00958       //The FIN can only be acknowledged if all the segment data
00959       //has been successfully transferred to the receive buffer
00960       if(socket->rcvNxt == (segment->seqNum + length))
00961       {
00962          //Advance RCV.NXT over the FIN
00963          socket->rcvNxt++;
00964          //Send an acknowledgment for the FIN
00965          tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
00966 
00967          //Check if our FIN has been acknowledged
00968          if(segment->ackNum == socket->sndNxt)
00969          {
00970             //Release previously allocated resources
00971             tcpDeleteControlBlock(socket);
00972             //Start the 2MSL timer
00973             tcpTimerStart(&socket->timeWaitTimer, TCP_2MSL_TIMER);
00974             //Switch to the TIME-WAIT state
00975             tcpChangeState(socket, TCP_STATE_TIME_WAIT);
00976          }
00977          else
00978          {
00979             //If our FIN has not been acknowledged, then enter CLOSING state
00980             tcpChangeState(socket, TCP_STATE_CLOSING);
00981          }
00982       }
00983    }
00984 }
00985 
00986 
00987 /**
00988  * @brief FIN-WAIT-2 state
00989  *
00990  * A device in this state has received an ACK for its request to terminate the
00991  * connection and is now waiting for a matching FIN from the other device
00992  *
00993  * @param[in] socket Handle referencing the current socket
00994  * @param[in] segment Incoming TCP segment
00995  * @param[in] buffer Multi-part buffer containing the incoming TCP segment
00996  * @param[in] offset Offset to the first data byte
00997  * @param[in] length Length of the segment data
00998  **/
00999 
01000 void tcpStateFinWait2(Socket *socket, TcpHeader *segment,
01001    const NetBuffer *buffer, size_t offset, size_t length)
01002 {
01003    //Debug message
01004    TRACE_DEBUG("TCP FSM: FIN-WAIT-2 state\r\n");
01005 
01006    //First check sequence number
01007    if(tcpCheckSequenceNumber(socket, segment, length))
01008       return;
01009 
01010    //Check the RST bit
01011    if(segment->flags & TCP_FLAG_RST)
01012    {
01013       //Switch to the CLOSED state
01014       tcpChangeState(socket, TCP_STATE_CLOSED);
01015       //Return immediately
01016       return;
01017    }
01018 
01019    //Check the SYN bit
01020    if(tcpCheckSyn(socket, segment, length))
01021       return;
01022    //Check the ACK field
01023    if(tcpCheckAck(socket, segment, length))
01024       return;
01025    //Process the segment text
01026    if(length > 0)
01027       tcpProcessSegmentData(socket, segment, buffer, offset, length);
01028 
01029    //Check the FIN bit
01030    if(segment->flags & TCP_FLAG_FIN)
01031    {
01032       //The FIN can only be acknowledged if all the segment data
01033       //has been successfully transferred to the receive buffer
01034       if(socket->rcvNxt == (segment->seqNum + length))
01035       {
01036          //Advance RCV.NXT over the FIN
01037          socket->rcvNxt++;
01038          //Send an acknowledgment for the FIN
01039          tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
01040 
01041          //Release previously allocated resources
01042          tcpDeleteControlBlock(socket);
01043          //Start the 2MSL timer
01044          tcpTimerStart(&socket->timeWaitTimer, TCP_2MSL_TIMER);
01045          //Switch to the TIME_WAIT state
01046          tcpChangeState(socket, TCP_STATE_TIME_WAIT);
01047       }
01048    }
01049 }
01050 
01051 
01052 /**
01053  * @brief CLOSING state
01054  *
01055  * The device has received a FIN from the other device and sent an ACK for
01056  * it, but not yet received an ACK for its own FIN message
01057  *
01058  * @param[in] socket Handle referencing the current socket
01059  * @param[in] segment Incoming TCP segment
01060  * @param[in] length Length of the segment data
01061  **/
01062 
01063 void tcpStateClosing(Socket *socket, TcpHeader *segment, size_t length)
01064 {
01065    //Debug message
01066    TRACE_DEBUG("TCP FSM: CLOSING state\r\n");
01067 
01068    //First check sequence number
01069    if(tcpCheckSequenceNumber(socket, segment, length))
01070       return;
01071 
01072    //Check the RST bit
01073    if(segment->flags & TCP_FLAG_RST)
01074    {
01075       //Enter CLOSED state
01076       tcpChangeState(socket, TCP_STATE_CLOSED);
01077       //Return immediately
01078       return;
01079    }
01080 
01081    //Check the SYN bit
01082    if(tcpCheckSyn(socket, segment, length))
01083       return;
01084    //Check the ACK field
01085    if(tcpCheckAck(socket, segment, length))
01086       return;
01087 
01088    //If the ACK acknowledges our FIN then enter the TIME-WAIT
01089    //state, otherwise ignore the segment
01090    if(segment->ackNum == socket->sndNxt)
01091    {
01092       //Release previously allocated resources
01093       tcpDeleteControlBlock(socket);
01094       //Start the 2MSL timer
01095       tcpTimerStart(&socket->timeWaitTimer, TCP_2MSL_TIMER);
01096       //Switch to the TIME-WAIT state
01097       tcpChangeState(socket, TCP_STATE_TIME_WAIT);
01098    }
01099 }
01100 
01101 
01102 /**
01103  * @brief TIME-WAIT state
01104  *
01105  * The device has now received a FIN from the other device and acknowledged
01106  * it, and sent its own FIN and received an ACK for it. We are done, except
01107  * for waiting to ensure the ACK is received and prevent potential overlap
01108  * with new connections
01109  *
01110  * @param[in] socket Handle referencing the current socket
01111  * @param[in] segment Incoming TCP segment
01112  * @param[in] length Length of the segment data
01113  **/
01114 
01115 void tcpStateTimeWait(Socket *socket, TcpHeader *segment, size_t length)
01116 {
01117    //Debug message
01118    TRACE_DEBUG("TCP FSM: TIME-WAIT state\r\n");
01119 
01120    //First check sequence number
01121    if(tcpCheckSequenceNumber(socket, segment, length))
01122       return;
01123 
01124    //Check the RST bit
01125    if(segment->flags & TCP_FLAG_RST)
01126    {
01127       //Enter CLOSED state
01128       tcpChangeState(socket, TCP_STATE_CLOSED);
01129 
01130       //Dispose the socket if the user does not have the ownership anymore
01131       if(!socket->ownedFlag)
01132       {
01133          //Delete the TCB
01134          tcpDeleteControlBlock(socket);
01135          //Mark the socket as closed
01136          socket->type = SOCKET_TYPE_UNUSED;
01137       }
01138 
01139       //Return immediately
01140       return;
01141    }
01142 
01143    //Check the SYN bit
01144    if(tcpCheckSyn(socket, segment, length))
01145       return;
01146    //If the ACK bit is off drop the segment and return
01147    if(!(segment->flags & TCP_FLAG_ACK))
01148       return;
01149 
01150    //The only thing that can arrive in this state is a retransmission
01151    //of the remote FIN. Acknowledge it and restart the 2 MSL timeout
01152    if(segment->flags & TCP_FLAG_FIN)
01153    {
01154       //Send an acknowledgment for the FIN
01155       tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
01156       //Restart the 2MSL timer
01157       tcpTimerStart(&socket->timeWaitTimer, TCP_2MSL_TIMER);
01158    }
01159 }
01160 
01161 #endif
01162