TCPConnectionRcvSegment.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004 Andras Varga
00003 // Copyright (C) 2009-2010 Thomas Reschka
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 
00020 #include <string.h>
00021 #include "TCP.h"
00022 #include "TCPConnection.h"
00023 #include "TCPSegment.h"
00024 #include "TCPCommand_m.h"
00025 #include "TCPSendQueue.h"
00026 #include "TCPSACKRexmitQueue.h"
00027 #include "TCPReceiveQueue.h"
00028 #include "TCPAlgorithm.h"
00029 
00030 bool TCPConnection::tryFastRoute(TCPSegment *tcpseg)
00031 {
00032     // fast route processing not yet implemented
00033     return false;
00034 }
00035 
00036 
00037 void TCPConnection::segmentArrivalWhileClosed(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00038 {
00039     tcpEV << "Seg arrived: ";
00040     printSegmentBrief(tcpseg);
00041 
00042     // This segment doesn't belong to any connection, so this object
00043     // must be a temp object created solely for the purpose of calling us
00044     ASSERT(state==NULL);
00045     tcpEV << "Segment doesn't belong to any existing connection\n";
00046 
00047     // RFC 793:
00048     //"
00049     // all data in the incoming segment is discarded.  An incoming
00050     // segment containing a RST is discarded.  An incoming segment not
00051     // containing a RST causes a RST to be sent in response.  The
00052     // acknowledgment and sequence field values are selected to make the
00053     // reset sequence acceptable to the TCP that sent the offending
00054     // segment.
00055     //
00056     // If the ACK bit is off, sequence number zero is used,
00057     //
00058     //    <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
00059     //
00060     // If the ACK bit is on,
00061     //
00062     //    <SEQ=SEG.ACK><CTL=RST>
00063     //"
00064     if (tcpseg->getRstBit())
00065     {
00066         tcpEV << "RST bit set: dropping segment\n";
00067         return;
00068     }
00069 
00070     if (!tcpseg->getAckBit())
00071     {
00072         tcpEV << "ACK bit not set: sending RST+ACK\n";
00073         uint32 ackNo = tcpseg->getSequenceNo() + (uint32)tcpseg->getPayloadLength();
00074         sendRstAck(0,ackNo,destAddr,srcAddr,tcpseg->getDestPort(),tcpseg->getSrcPort());
00075     }
00076     else
00077     {
00078         tcpEV << "ACK bit set: sending RST\n";
00079         sendRst(tcpseg->getAckNo(),destAddr,srcAddr,tcpseg->getDestPort(),tcpseg->getSrcPort());
00080     }
00081 }
00082 
00083 TCPEventCode TCPConnection::process_RCV_SEGMENT(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest)
00084 {
00085     tcpEV << "Seg arrived: ";
00086     printSegmentBrief(tcpseg);
00087     tcpEV << "TCB: " << state->info() << "\n";
00088 
00089     if (rcvSeqVector) rcvSeqVector->record(tcpseg->getSequenceNo());
00090     if (rcvAckVector) rcvAckVector->record(tcpseg->getAckNo());
00091 
00092     //
00093     // Note: this code is organized exactly as RFC 793, section "3.9 Event
00094     // Processing", subsection "SEGMENT ARRIVES".
00095     //
00096     TCPEventCode event;
00097     if (fsm.getState()==TCP_S_LISTEN)
00098     {
00099         event = processSegmentInListen(tcpseg, src, dest);
00100     }
00101     else if (fsm.getState()==TCP_S_SYN_SENT)
00102     {
00103         event = processSegmentInSynSent(tcpseg, src, dest);
00104     }
00105     else
00106     {
00107         // RFC 793 steps "first check sequence number", "second check the RST bit", etc
00108         event = processSegment1stThru8th(tcpseg);
00109     }
00110     delete tcpseg;
00111     return event;
00112 }
00113 
00114 TCPEventCode TCPConnection::processSegment1stThru8th(TCPSegment *tcpseg)
00115 {
00116     //
00117     // RFC 793: first check sequence number
00118     //
00119 
00120     bool acceptable = true;
00121 
00122     if (tcpseg->getHeaderLength() > TCP_HEADER_OCTETS) // Header options present? TCP_HEADER_OCTETS = 20
00123     {
00124         // PAWS
00125         if (state->ts_enabled)
00126         {
00127             uint32 tsval = getTSval(tcpseg);
00128             // FIXME check TS rounding on all other code
00129             if (tsval != 0 && seqLess(tsval, state->ts_recent) &&
00130                     (simTime() - state->time_last_data_sent) > PAWS_IDLE_TIME_THRESH) // PAWS_IDLE_TIME_THRESH = 24 days
00131             {
00132                 tcpEV << "PAWS: Segment is not acceptable, TSval=" << tsval << " in " <<
00133                         stateName(fsm.getState()) << " state received: dropping segment\n";
00134                 acceptable = false;
00135             }
00136         }
00137         readHeaderOptions(tcpseg);
00138     }
00139 
00140     if (acceptable)
00141         acceptable = isSegmentAcceptable(tcpseg);
00142 
00143     if (!acceptable)
00144     {
00145         //"
00146         // If an incoming segment is not acceptable, an acknowledgment
00147         // should be sent in reply (unless the RST bit is set, if so drop
00148         // the segment and return):
00149         //
00150         //  <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
00151         //"
00152         if (tcpseg->getRstBit())
00153         {
00154             tcpEV << "RST with unacceptable seqNum: dropping\n";
00155         }
00156         else
00157         {
00158             if (tcpseg->getSynBit())
00159             {
00160                 tcpEV << "SYN with unacceptable seqNum in " <<  stateName(fsm.getState()) << " state received (SYN duplicat?)\n";
00161             }
00162             else if (state->sack_enabled && seqLess((tcpseg->getSequenceNo()+tcpseg->getPayloadLength()), state->rcv_nxt))
00163             {
00164                 state->start_seqno = tcpseg->getSequenceNo();
00165                 state->end_seqno = tcpseg->getSequenceNo() + tcpseg->getPayloadLength();
00166                 state->snd_dsack = true;
00167                 tcpEV << "SND_D-SACK SET (dupseg rcvd)\n";
00168             }
00169 
00170             tcpEV << "Segment seqNum not acceptable, sending ACK with current receive seq\n";
00171             // RFC 2018, page 4:
00172             // "The receiver SHOULD send an ACK for every valid segment that arrives
00173             // containing new data, and each of these "duplicate" ACKs SHOULD bear a
00174             // SACK option."
00175             //
00176             // The received segment is not "valid" therefore the ACK will not bear a SACK option, if snd_dsack (D-SACK) is not set.
00177             sendAck();
00178         }
00179         return TCP_E_IGNORE;
00180     }
00181 
00182     //
00183     // RFC 793: second check the RST bit,
00184     //
00185     if (tcpseg->getRstBit())
00186     {
00187         // Note: if we come from LISTEN, processSegmentInListen() has already handled RST.
00188         switch (fsm.getState())
00189         {
00190             case TCP_S_SYN_RCVD:
00191                 //"
00192                 // If this connection was initiated with a passive OPEN (i.e.,
00193                 // came from the LISTEN state), then return this connection to
00194                 // LISTEN state and return.  The user need not be informed.  If
00195                 // this connection was initiated with an active OPEN (i.e., came
00196                 // from SYN-SENT state) then the connection was refused, signal
00197                 // the user "connection refused".  In either case, all segments
00198                 // on the retransmission queue should be removed.  And in the
00199                 // active OPEN case, enter the CLOSED state and delete the TCB,
00200                 // and return.
00201                 //"
00202                 return processRstInSynReceived(tcpseg);
00203 
00204             case TCP_S_ESTABLISHED:
00205             case TCP_S_FIN_WAIT_1:
00206             case TCP_S_FIN_WAIT_2:
00207             case TCP_S_CLOSE_WAIT:
00208                 //"
00209                 // If the RST bit is set then, any outstanding RECEIVEs and SEND
00210                 // should receive "reset" responses.  All segment queues should be
00211                 // flushed.  Users should also receive an unsolicited general
00212                 // "connection reset" signal.
00213                 //
00214                 // Enter the CLOSED state, delete the TCB, and return.
00215                 //"
00216                 tcpEV << "RST: performing connection reset, closing connection\n";
00217                 sendIndicationToApp(TCP_I_CONNECTION_RESET);
00218                 return TCP_E_RCV_RST;  // this will trigger state transition
00219 
00220             case TCP_S_CLOSING:
00221             case TCP_S_LAST_ACK:
00222             case TCP_S_TIME_WAIT:
00223                 //"
00224                 // enter the CLOSED state, delete the TCB, and return.
00225                 //"
00226                 tcpEV << "RST: closing connection\n";
00227                 if (fsm.getState()!=TCP_S_TIME_WAIT)
00228                     sendIndicationToApp(TCP_I_CLOSED); // in TIME_WAIT, we've already sent it
00229                 return TCP_E_RCV_RST; // this will trigger state transition
00230 
00231             default: ASSERT(0);
00232         }
00233     }
00234 
00235     // RFC 793: third check security and precedence
00236     // This step is ignored.
00237 
00238     //
00239     // RFC 793: fourth, check the SYN bit,
00240     //
00241     if (tcpseg->getSynBit())
00242     {
00243         //"
00244         // If the SYN is in the window it is an error, send a reset, any
00245         // outstanding RECEIVEs and SEND should receive "reset" responses,
00246         // all segment queues should be flushed, the user should also
00247         // receive an unsolicited general "connection reset" signal, enter
00248         // the CLOSED state, delete the TCB, and return.
00249         //
00250         // If the SYN is not in the window this step would not be reached
00251         // and an ack would have been sent in the first step (sequence
00252         // number check).
00253         //"
00254 
00255         ASSERT(isSegmentAcceptable(tcpseg));  // assert SYN is in the window
00256         tcpEV << "SYN is in the window: performing connection reset, closing connection\n";
00257         sendIndicationToApp(TCP_I_CONNECTION_RESET);
00258         return TCP_E_RCV_UNEXP_SYN;
00259     }
00260 
00261     //
00262     // RFC 793: fifth check the ACK field,
00263     //
00264     if (!tcpseg->getAckBit())
00265     {
00266         // if the ACK bit is off drop the segment and return
00267         tcpEV << "ACK not set, dropping segment\n";
00268         return TCP_E_IGNORE;
00269     }
00270 
00271     uint32 old_snd_una = state->snd_una;
00272 
00273     TCPEventCode event = TCP_E_IGNORE;
00274 
00275     if (fsm.getState()==TCP_S_SYN_RCVD)
00276     {
00277         //"
00278         // If SND.UNA =< SEG.ACK =< SND.NXT then enter ESTABLISHED state
00279         // and continue processing.
00280         //
00281         // If the segment acknowledgment is not acceptable, form a
00282         // reset segment,
00283         //
00284         //  <SEQ=SEG.ACK><CTL=RST>
00285         //
00286         // and send it.
00287         //"
00288         if (!seqLE(state->snd_una,tcpseg->getAckNo()) || !seqLE(tcpseg->getAckNo(),state->snd_nxt))
00289         {
00290             sendRst(tcpseg->getAckNo());
00291             return TCP_E_IGNORE;
00292         }
00293 
00294         // notify tcpAlgorithm and app layer
00295         tcpAlgorithm->established(false);
00296         sendEstabIndicationToApp();
00297 
00298         // This will trigger transition to ESTABLISHED. Timers and notifying
00299         // app will be taken care of in stateEntered().
00300         event = TCP_E_RCV_ACK;
00301     }
00302 
00303     uint32 old_snd_nxt = state->snd_nxt; // later we'll need to see if snd_nxt changed
00304     // Note: If one of the last data segments is lost while already in LAST-ACK state (e.g. if using TCPEchoApps)
00305     // TCP must be able to process acceptable acknowledgments, however please note RFC 793, page 73:
00306         // "LAST-ACK STATE
00307     //    The only thing that can arrive in this state is an
00308     //    acknowledgment of our FIN.  If our FIN is now acknowledged,
00309     //    delete the TCB, enter the CLOSED state, and return."
00310     if (fsm.getState()==TCP_S_SYN_RCVD || fsm.getState()==TCP_S_ESTABLISHED ||
00311         fsm.getState()==TCP_S_FIN_WAIT_1 || fsm.getState()==TCP_S_FIN_WAIT_2 ||
00312         fsm.getState()==TCP_S_CLOSE_WAIT || fsm.getState()==TCP_S_CLOSING || fsm.getState()==TCP_S_LAST_ACK)
00313     {
00314         //
00315         // ESTABLISHED processing:
00316         //"
00317         //  If SND.UNA < SEG.ACK =< SND.NXT then, set SND.UNA <- SEG.ACK.
00318         //  Any segments on the retransmission queue which are thereby
00319         //  entirely acknowledged are removed.  Users should receive
00320         //  positive acknowledgments for buffers which have been SENT and
00321         //  fully acknowledged (i.e., SEND buffer should be returned with
00322         //  "ok" response).  If the ACK is a duplicate
00323         //  (SEG.ACK < SND.UNA), it can be ignored.  If the ACK acks
00324         //  something not yet sent (SEG.ACK > SND.NXT) then send an ACK,
00325         //  drop the segment, and return.
00326         //
00327         //  If SND.UNA < SEG.ACK =< SND.NXT, the send window should be
00328         //  updated.  If (SND.WL1 < SEG.SEQ or (SND.WL1 = SEG.SEQ and
00329         //  SND.WL2 =< SEG.ACK)), set SND.WND <- SEG.WND, set
00330         //  SND.WL1 <- SEG.SEQ, and set SND.WL2 <- SEG.ACK.
00331         //
00332         //  Note that SND.WND is an offset from SND.UNA, that SND.WL1
00333         //  records the sequence number of the last segment used to update
00334         //  SND.WND, and that SND.WL2 records the acknowledgment number of
00335         //  the last segment used to update SND.WND.  The check here
00336         //  prevents using old segments to update the window.
00337         //"
00338         bool ok = processAckInEstabEtc(tcpseg);
00339         if (!ok)
00340             return TCP_E_IGNORE;  // if acks something not yet sent, drop it
00341     }
00342 
00343     if ((fsm.getState()==TCP_S_FIN_WAIT_1 && state->fin_ack_rcvd))
00344     {
00345         //"
00346         // FIN-WAIT-1 STATE
00347         //   In addition to the processing for the ESTABLISHED state, if
00348         //   our FIN is now acknowledged then enter FIN-WAIT-2 and continue
00349         //   processing in that state.
00350         //"
00351         event = TCP_E_RCV_ACK;  // will trigger transition to FIN-WAIT-2
00352     }
00353 
00354     if (fsm.getState()==TCP_S_FIN_WAIT_2)
00355     {
00356         //"
00357         // FIN-WAIT-2 STATE
00358         //  In addition to the processing for the ESTABLISHED state, if
00359         //  the retransmission queue is empty, the user's CLOSE can be
00360         //  acknowledged ("ok") but do not delete the TCB.
00361         //"
00362         // nothing to do here (in our model, used commands don't need to be
00363         // acknowledged)
00364     }
00365 
00366     if (fsm.getState()==TCP_S_CLOSING)
00367     {
00368         //"
00369         // In addition to the processing for the ESTABLISHED state, if
00370         // the ACK acknowledges our FIN then enter the TIME-WAIT state,
00371         // otherwise ignore the segment.
00372         //"
00373         if (state->fin_ack_rcvd)
00374         {
00375             tcpEV << "Our FIN acked -- can go to TIME_WAIT now\n";
00376             event = TCP_E_RCV_ACK;  // will trigger transition to TIME-WAIT
00377             scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);  // start timer
00378 
00379             // we're entering TIME_WAIT, so we can signal CLOSED the user
00380             // (the only thing left to do is wait until the 2MSL timer expires)
00381             sendIndicationToApp(TCP_I_CLOSED);
00382         }
00383     }
00384 
00385     if (fsm.getState()==TCP_S_LAST_ACK)
00386     {
00387         //"
00388         // The only thing that can arrive in this state is an
00389         // acknowledgment of our FIN.  If our FIN is now acknowledged,
00390         // delete the TCB, enter the CLOSED state, and return.
00391         //"
00392         if (state->send_fin && tcpseg->getAckNo()==state->snd_fin_seq+1)
00393         {
00394             tcpEV << "Last ACK arrived\n";
00395             sendIndicationToApp(TCP_I_CLOSED);
00396             return TCP_E_RCV_ACK; // will trigger transition to CLOSED
00397         }
00398     }
00399 
00400     if (fsm.getState()==TCP_S_TIME_WAIT)
00401     {
00402         //"
00403         // The only thing that can arrive in this state is a
00404         // retransmission of the remote FIN.  Acknowledge it, and restart
00405         // the 2 MSL timeout.
00406         //"
00407         // And we are staying in the TIME_WAIT state.
00408         //
00409         sendAck();
00410         cancelEvent(the2MSLTimer);
00411         scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00412     }
00413 
00414     //
00415     // RFC 793: sixth, check the URG bit,
00416     //
00417     if (tcpseg->getUrgBit() && (fsm.getState()==TCP_S_ESTABLISHED ||
00418             fsm.getState()==TCP_S_FIN_WAIT_1 || fsm.getState()==TCP_S_FIN_WAIT_2))
00419     {
00420         //"
00421         // If the URG bit is set, RCV.UP <- max(RCV.UP,SEG.UP), and signal
00422         // the user that the remote side has urgent data if the urgent
00423         // pointer (RCV.UP) is in advance of the data consumed.  If the
00424         // user has already been signaled (or is still in the "urgent
00425         // mode") for this continuous sequence of urgent data, do not
00426         // signal the user again.
00427         //"
00428 
00429         // TBD: URG currently not supported
00430     }
00431 
00432     //
00433     // RFC 793: seventh, process the segment text,
00434     //
00435     uint32 old_rcv_nxt = state->rcv_nxt; // if rcv_nxt changes, we need to send/schedule an ACK
00436     if (fsm.getState()==TCP_S_SYN_RCVD || fsm.getState()==TCP_S_ESTABLISHED ||
00437             fsm.getState()==TCP_S_FIN_WAIT_1 || fsm.getState()==TCP_S_FIN_WAIT_2)
00438     {
00439         //"
00440         // Once in the ESTABLISHED state, it is possible to deliver segment
00441         // text to user RECEIVE buffers.  Text from segments can be moved
00442         // into buffers until either the buffer is full or the segment is
00443         // empty.  If the segment empties and carries an PUSH flag, then
00444         // the user is informed, when the buffer is returned, that a PUSH
00445         // has been received.
00446         //
00447         // When the TCP takes responsibility for delivering the data to the
00448         // user it must also acknowledge the receipt of the data.
00449         //
00450         // Once the TCP takes responsibility for the data it advances
00451         // RCV.NXT over the data accepted, and adjusts RCV.WND as
00452         // apporopriate to the current buffer availability.  The total of
00453         // RCV.NXT and RCV.WND should not be reduced.
00454         //
00455         // Please note the window management suggestions in section 3.7.
00456         //
00457         // Send an acknowledgment of the form:
00458         //
00459         //   <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
00460         //
00461         // This acknowledgment should be piggybacked on a segment being
00462         // transmitted if possible without incurring undue delay.
00463         //"
00464 
00465         tcpseg->truncateSegment(state->rcv_nxt, state->rcv_nxt + state->rcv_wnd);
00466 
00467         if (tcpseg->getPayloadLength()>0)
00468         {
00469             // check for full sized segment
00470             if (tcpseg->getPayloadLength() == state->snd_mss || tcpseg->getPayloadLength() + tcpseg->getHeaderLength() - TCP_HEADER_OCTETS == state->snd_mss)
00471                 state->full_sized_segment_counter++;
00472             // check for persist probe
00473             if (tcpseg->getPayloadLength() == 1)
00474                 state->ack_now = true;    // TODO how to check if it is really a persist probe?
00475 
00476             updateRcvQueueVars();
00477             if (state->freeRcvBuffer >= tcpseg->getPayloadLength()) // enough freeRcvBuffer in rcvQueue for new segment?
00478             {
00479                 tcpEV2 << "Processing segment text in a data transfer state\n";
00480 
00481                 // insert into receive buffers. If this segment is contiguous with
00482                 // previously received ones (seqNo==rcv_nxt), rcv_nxt can be increased;
00483                 // otherwise it stays the same but the data must be cached nevertheless
00484                 // (to avoid "Failure to retain above-sequence data" problem, RFC 2525
00485                 // section 2.5).
00486 
00487                 uint32 old_usedRcvBuffer = state->usedRcvBuffer;
00488                 state->rcv_nxt = receiveQueue->insertBytesFromSegment(tcpseg);
00489 
00490                 if (seqGreater(state->snd_una, old_snd_una))
00491                 {
00492                     // notify
00493                     tcpAlgorithm->receivedDataAck(old_snd_una);
00494 
00495                     // in the receivedDataAck we need the old value
00496                     state->dupacks = 0;
00497                     if (dupAcksVector)
00498                         dupAcksVector->record(state->dupacks);
00499                 }
00500 
00501                 // out-of-order segment?
00502                 if (old_rcv_nxt==state->rcv_nxt)
00503                 {
00504                     state->rcv_oooseg++;
00505                     if (rcvOooSegVector)
00506                         rcvOooSegVector->record(state->rcv_oooseg);
00507 
00508                     // RFC 2018, page 4:
00509                     // "The receiver SHOULD send an ACK for every valid segment that arrives
00510                     // containing new data, and each of these "duplicate" ACKs SHOULD bear a
00511                     // SACK option."
00512                     if (state->sack_enabled)
00513                     {
00514                         // store start and end sequence numbers of current oooseg in state variables
00515                         state->start_seqno = tcpseg->getSequenceNo();
00516                         state->end_seqno = tcpseg->getSequenceNo() + tcpseg->getPayloadLength();
00517 
00518                         if (old_usedRcvBuffer == receiveQueue->getAmountOfBufferedBytes()) // D-SACK
00519                         {
00520                             state->snd_dsack = true;
00521                             tcpEV << "SND_D-SACK SET (old_rcv_nxt==rcv_nxt duplicated oooseg rcvd)\n";
00522                         }
00523                         else // SACK
00524                         {
00525                             state->snd_sack = true;
00526                             tcpEV << "SND_SACK SET (old_rcv_nxt==rcv_nxt oooseg rcvd)\n";
00527                         }
00528                     }
00529                     tcpAlgorithm->receivedOutOfOrderSegment();
00530                 }
00531                 else
00532                 {
00533                     // forward data to app
00534                     //
00535                     // FIXME observe PSH bit
00536                     //
00537                     // FIXME we should implement socket READ command, and pass up only
00538                     // as many bytes as requested. rcv_wnd should be decreased
00539                     // accordingly!
00540                     //
00541                     cPacket *msg;
00542                     while ((msg=receiveQueue->extractBytesUpTo(state->rcv_nxt))!=NULL)
00543                     {
00544                         msg->setKind(TCP_I_DATA);  // TBD currently we never send TCP_I_URGENT_DATA
00545                         TCPCommand *cmd = new TCPCommand();
00546                         cmd->setConnId(connId);
00547                         msg->setControlInfo(cmd);
00548                         sendToApp(msg);
00549                     }
00550 
00551                     // if this segment "filled the gap" until the previously arrived segment
00552                     // that carried a FIN (i.e.rcv_nxt==rcv_fin_seq), we have to advance
00553                     // rcv_nxt over the FIN.
00554                     if (state->fin_rcvd && state->rcv_nxt==state->rcv_fin_seq)
00555                     {
00556                         state->ack_now = true; // although not mentioned in [Stevens, W.R.: TCP/IP Illustrated, Volume 2, page 861] seems like we have to set ack_now
00557                         tcpEV << "All segments arrived up to the FIN segment, advancing rcv_nxt over the FIN\n";
00558                         state->rcv_nxt = state->rcv_fin_seq+1;
00559                         // state transitions will be done in the state machine, here we just set
00560                         // the proper event code (TCP_E_RCV_FIN or TCP_E_RCV_FIN_ACK)
00561                         event = TCP_E_RCV_FIN;
00562                         switch (fsm.getState())
00563                         {
00564                             case TCP_S_FIN_WAIT_1:
00565                                 if (state->fin_ack_rcvd)
00566                                 {
00567                                     event = TCP_E_RCV_FIN_ACK;
00568                                     // start the time-wait timer, turn off the other timers
00569                                     cancelEvent(finWait2Timer);
00570                                     scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00571 
00572                                     // we're entering TIME_WAIT, so we can signal CLOSED the user
00573                                     // (the only thing left to do is wait until the 2MSL timer expires)
00574                                     sendIndicationToApp(TCP_I_CLOSED);
00575                                 }
00576                                 break;
00577                             case TCP_S_FIN_WAIT_2:
00578                                 // Start the time-wait timer, turn off the other timers.
00579                                 cancelEvent(finWait2Timer);
00580                                 scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00581 
00582                                 // we're entering TIME_WAIT, so we can signal CLOSED the user
00583                                 // (the only thing left to do is wait until the 2MSL timer expires)
00584                                 sendIndicationToApp(TCP_I_CLOSED);
00585                                 break;
00586                             case TCP_S_TIME_WAIT:
00587                                 // Restart the 2 MSL time-wait timeout.
00588                                 cancelEvent(the2MSLTimer);
00589                                 scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00590                                 break;
00591                         }
00592                         sendIndicationToApp(TCP_I_PEER_CLOSED);
00593                     }
00594                 }
00595             }
00596             else    // not enough freeRcvBuffer in rcvQueue for new segment
00597             {
00598                 state->tcpRcvQueueDrops++; // update current number of tcp receive queue drops
00599                 if (tcpRcvQueueDropsVector)
00600                     tcpRcvQueueDropsVector->record(state->tcpRcvQueueDrops);
00601 
00602                 // if the ACK bit is off drop the segment and return
00603                 tcpEV << "RcvQueueBuffer has run out, dropping segment\n";
00604                 return TCP_E_IGNORE;
00605             }
00606         }
00607     }
00608 
00609     //
00610     // RFC 793: eighth, check the FIN bit,
00611     //
00612     if (tcpseg->getFinBit())
00613     {
00614         state->ack_now = true;
00615 
00616         //"
00617         // If the FIN bit is set, signal the user "connection closing" and
00618         // return any pending RECEIVEs with same message, advance RCV.NXT
00619         // over the FIN, and send an acknowledgment for the FIN.  Note that
00620         // FIN implies PUSH for any segment text not yet delivered to the
00621         // user.
00622         //"
00623 
00624         // Note: seems like RFC 793 is not entirely correct here: if the
00625         // segment is "above sequence" (ie. RCV.NXT < SEG.SEQ), we cannot
00626         // advance RCV.NXT over the FIN. Instead we remember this sequence
00627         // number and do it later.
00628         uint32 fin_seq = (uint32)tcpseg->getSequenceNo() + (uint32)tcpseg->getPayloadLength();
00629         if (state->rcv_nxt==fin_seq)
00630         {
00631             // advance rcv_nxt over FIN now
00632             tcpEV << "FIN arrived, advancing rcv_nxt over the FIN\n";
00633             state->rcv_nxt++;
00634             // state transitions will be done in the state machine, here we just set
00635             // the proper event code (TCP_E_RCV_FIN or TCP_E_RCV_FIN_ACK)
00636             event = TCP_E_RCV_FIN;
00637             switch (fsm.getState())
00638             {
00639                 case TCP_S_FIN_WAIT_1:
00640                     if (state->fin_ack_rcvd)
00641                     {
00642                         event = TCP_E_RCV_FIN_ACK;
00643                         // start the time-wait timer, turn off the other timers
00644                         cancelEvent(finWait2Timer);
00645                         scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00646 
00647                         // we're entering TIME_WAIT, so we can signal CLOSED the user
00648                         // (the only thing left to do is wait until the 2MSL timer expires)
00649                         sendIndicationToApp(TCP_I_CLOSED);
00650                     }
00651                     break;
00652                 case TCP_S_FIN_WAIT_2:
00653                     // Start the time-wait timer, turn off the other timers.
00654                     cancelEvent(finWait2Timer);
00655                     scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00656 
00657                     // we're entering TIME_WAIT, so we can signal CLOSED the user
00658                     // (the only thing left to do is wait until the 2MSL timer expires)
00659                     sendIndicationToApp(TCP_I_CLOSED);
00660                     break;
00661                 case TCP_S_TIME_WAIT:
00662                     // Restart the 2 MSL time-wait timeout.
00663                     cancelEvent(the2MSLTimer);
00664                     scheduleTimeout(the2MSLTimer, TCP_TIMEOUT_2MSL);
00665                     break;
00666             }
00667             sendIndicationToApp(TCP_I_PEER_CLOSED);
00668         }
00669         else
00670         {
00671             // we'll have to do it later (when an arriving segment "fills the gap")
00672             tcpEV << "FIN segment above sequence, storing sequence number of FIN\n";
00673             state->fin_rcvd = true;
00674             state->rcv_fin_seq = fin_seq;
00675         }
00676 
00677         // TBD do PUSH stuff
00678     }
00679 
00680     if (old_rcv_nxt!=state->rcv_nxt)
00681     {
00682         // if rcv_nxt changed, either because we received segment text or we
00683         // received a FIN that needs to be acked (or both), we need to send or
00684         // schedule an ACK.
00685 
00686         if (state->sack_enabled)
00687         {
00688             if (receiveQueue->getQueueLength()!=0)
00689             {
00690                 // RFC 2018, page 4:
00691                 // "If sent at all, SACK options SHOULD be included in all ACKs which do
00692                 // not ACK the highest sequence number in the data receiver's queue."
00693                 state->start_seqno = tcpseg->getSequenceNo();
00694                 state->end_seqno = tcpseg->getSequenceNo() + tcpseg->getPayloadLength();
00695                 state->snd_sack = true;
00696                 tcpEV << "SND_SACK SET (rcv_nxt changed, but rexmitQ is not empty)\n";
00697                 state->ack_now = true; // although not mentioned in [Stevens, W.R.: TCP/IP Illustrated, Volume 2, page 861] seems like we have to set ack_now
00698             }
00699         }
00700 
00701         // tcpAlgorithm decides when and how to do ACKs
00702         tcpAlgorithm->receiveSeqChanged();
00703     }
00704 
00705     if ((fsm.getState()==TCP_S_ESTABLISHED || fsm.getState()==TCP_S_SYN_RCVD) &&
00706         state->send_fin && state->snd_nxt==state->snd_fin_seq+1)
00707     {
00708         // if the user issued the CLOSE command a long time ago and we've just
00709         // managed to send off FIN, we simulate a CLOSE command now (we had to
00710         // defer it at that time because we still had data in the send queue.)
00711         // This CLOSE will take us into the FIN_WAIT_1 state.
00712         tcpEV << "Now we can do the CLOSE which was deferred a while ago\n";
00713         event = TCP_E_CLOSE;
00714     }
00715 
00716     if (fsm.getState()==TCP_S_CLOSE_WAIT && state->send_fin &&
00717         state->snd_nxt==state->snd_fin_seq+1 && old_snd_nxt!=state->snd_nxt)
00718     {
00719         // if we're in CLOSE_WAIT and we just got to sent our long-pending FIN,
00720         // we simulate a CLOSE command now (we had to defer it at that time because
00721         // we still had data in the send queue.) This CLOSE will take us into the
00722         // LAST_ACK state.
00723         tcpEV << "Now we can do the CLOSE which was deferred a while ago\n";
00724         event = TCP_E_CLOSE;
00725     }
00726 
00727     return event;
00728 }
00729 
00730 //----
00731 
00732 TCPEventCode TCPConnection::processSegmentInListen(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00733 {
00734     tcpEV2 << "Processing segment in LISTEN\n";
00735 
00736     //"
00737     // first check for an RST
00738     //   An incoming RST should be ignored.  Return.
00739     //"
00740     if (tcpseg->getRstBit())
00741     {
00742         tcpEV << "RST bit set: dropping segment\n";
00743         return TCP_E_IGNORE;
00744     }
00745 
00746     //"
00747     // second check for an ACK
00748     //    Any acknowledgment is bad if it arrives on a connection still in
00749     //    the LISTEN state.  An acceptable reset segment should be formed
00750     //    for any arriving ACK-bearing segment.  The RST should be
00751     //    formatted as follows:
00752     //
00753     //      <SEQ=SEG.ACK><CTL=RST>
00754     //
00755     //    Return.
00756     //"
00757     if (tcpseg->getAckBit())
00758     {
00759         tcpEV << "ACK bit set: dropping segment and sending RST\n";
00760         sendRst(tcpseg->getAckNo(),destAddr,srcAddr,tcpseg->getDestPort(),tcpseg->getSrcPort());
00761         return TCP_E_IGNORE;
00762     }
00763 
00764     //"
00765     // third check for a SYN
00766     //"
00767     if (tcpseg->getSynBit())
00768     {
00769         if (tcpseg->getFinBit())
00770         {
00771             // Looks like implementations vary on how to react to SYN+FIN.
00772             // Some treat it as plain SYN (and reply with SYN+ACK), some send RST+ACK.
00773             // Let's just do the former here.
00774             tcpEV << "SYN+FIN received: ignoring FIN\n";
00775         }
00776 
00777         tcpEV << "SYN bit set: filling in foreign socket and sending SYN+ACK\n";
00778 
00779         //"
00780         // If the listen was not fully specified (i.e., the foreign socket was not
00781         // fully specified), then the unspecified fields should be filled in now.
00782         //"
00783         //
00784         // Also, we may need to fork, in order to leave another connection
00785         // LISTENing on the port. Note: forking will change our connId.
00786         //
00787         if (state->fork)
00788         {
00789             TCPConnection *conn = cloneListeningConnection(); // "conn" is the clone which will stay LISTENing, while "this" gets updated with the remote address
00790             tcpMain->addForkedConnection(this, conn, destAddr, srcAddr, tcpseg->getDestPort(), tcpseg->getSrcPort());
00791             tcpEV << "Connection forked: this connection got new connId=" << connId << ", "
00792                 "spinoff keeps LISTENing with connId=" << conn->connId << "\n";
00793         }
00794         else
00795         {
00796             tcpMain->updateSockPair(this, destAddr, srcAddr, tcpseg->getDestPort(), tcpseg->getSrcPort());
00797         }
00798 
00799         //"
00800         //  Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
00801         //  control or text should be queued for processing later.  ISS
00802         //  should be selected and a SYN segment sent of the form:
00803         //
00804         //    <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
00805         //
00806         //  SND.NXT is set to ISS+1 and SND.UNA to ISS.  The connection
00807         //  state should be changed to SYN-RECEIVED.
00808         //"
00809         state->rcv_nxt = tcpseg->getSequenceNo()+1;
00810         state->rcv_adv = state->rcv_nxt + state->rcv_wnd;
00811         if (rcvAdvVector) rcvAdvVector->record(state->rcv_adv);
00812         state->irs = tcpseg->getSequenceNo();
00813         receiveQueue->init(state->rcv_nxt);   // FIXME may init twice...
00814         selectInitialSeqNum();
00815 
00816         // although not mentioned in RFC 793, seems like we have to pick up
00817         // initial snd_wnd from the segment here.
00818         updateWndInfo(tcpseg, true);
00819 
00820         if (tcpseg->getHeaderLength() > TCP_HEADER_OCTETS) // Header options present? TCP_HEADER_OCTETS = 20
00821             readHeaderOptions(tcpseg);
00822 
00823         state->ack_now = true;
00824         sendSynAck();
00825         startSynRexmitTimer();
00826         if (!connEstabTimer->isScheduled())
00827             scheduleTimeout(connEstabTimer, TCP_TIMEOUT_CONN_ESTAB);
00828 
00829         //"
00830         // Note that any other incoming control or data (combined with SYN)
00831         // will be processed in the SYN-RECEIVED state, but processing of SYN
00832         // and ACK should not be repeated.
00833         //"
00834         // We don't send text in SYN or SYN+ACK, but accept it. Otherwise
00835         // there isn't much left to do: RST, SYN, ACK, FIN got processed already,
00836         // so there's only URG and PSH left to handle.
00837         //
00838         if (tcpseg->getPayloadLength()>0)
00839         {
00840             updateRcvQueueVars();
00841             if (state->freeRcvBuffer >= tcpseg->getPayloadLength()) // enough freeRcvBuffer in rcvQueue for new segment?
00842             {
00843                 receiveQueue->insertBytesFromSegment(tcpseg);
00844             }
00845             else    // not enough freeRcvBuffer in rcvQueue for new segment
00846             {
00847                 state->tcpRcvQueueDrops++; // update current number of tcp receive queue drops
00848                 if (tcpRcvQueueDropsVector)
00849                     tcpRcvQueueDropsVector->record(state->tcpRcvQueueDrops);
00850 
00851                 tcpEV << "RcvQueueBuffer has run out, dropping segment\n";
00852                 return TCP_E_IGNORE;
00853             }
00854         }
00855         if (tcpseg->getUrgBit() || tcpseg->getPshBit())
00856             tcpEV << "Ignoring URG and PSH bits in SYN\n"; // TBD
00857 
00858         return TCP_E_RCV_SYN;  // this will take us to SYN_RCVD
00859     }
00860 
00861     //"
00862     //  fourth other text or control
00863     //   So you are unlikely to get here, but if you do, drop the segment, and return.
00864     //"
00865     tcpEV << "Unexpected segment: dropping it\n";
00866     return TCP_E_IGNORE;
00867 }
00868 
00869 TCPEventCode TCPConnection::processSegmentInSynSent(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00870 {
00871     tcpEV2 << "Processing segment in SYN_SENT\n";
00872 
00873     //"
00874     // first check the ACK bit
00875     //
00876     //   If the ACK bit is set
00877     //
00878     //     If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
00879     //     the RST bit is set, if so drop the segment and return)
00880     //
00881     //       <SEQ=SEG.ACK><CTL=RST>
00882     //
00883     //     and discard the segment.  Return.
00884     //
00885     //     If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable.
00886     //"
00887     if (tcpseg->getAckBit())
00888     {
00889         if (seqLE(tcpseg->getAckNo(),state->iss) || seqGreater(tcpseg->getAckNo(),state->snd_nxt))
00890         {
00891             tcpEV << "ACK bit set but wrong AckNo, sending RST\n";
00892             sendRst(tcpseg->getAckNo(),destAddr,srcAddr,tcpseg->getDestPort(),tcpseg->getSrcPort());
00893             return TCP_E_IGNORE;
00894         }
00895         tcpEV << "ACK bit set, AckNo acceptable\n";
00896     }
00897 
00898     //"
00899     // second check the RST bit
00900     //
00901     //   If the RST bit is set
00902     //
00903     //     If the ACK was acceptable then signal the user "error:
00904     //     connection reset", drop the segment, enter CLOSED state,
00905     //     delete TCB, and return.  Otherwise (no ACK) drop the segment
00906     //     and return.
00907     //"
00908     if (tcpseg->getRstBit())
00909     {
00910         if (tcpseg->getAckBit())
00911         {
00912             tcpEV << "RST+ACK: performing connection reset\n";
00913             sendIndicationToApp(TCP_I_CONNECTION_RESET);
00914             return TCP_E_RCV_RST;
00915         }
00916         else
00917         {
00918             tcpEV << "RST without ACK: dropping segment\n";
00919             return TCP_E_IGNORE;
00920         }
00921     }
00922 
00923     //"
00924     // third check the security and precedence -- not done
00925     //
00926     // fourth check the SYN bit
00927     //
00928     //   This step should be reached only if the ACK is ok, or there is
00929     //   no ACK, and it the segment did not contain a RST.
00930     //
00931     //   If the SYN bit is on and the security/compartment and precedence
00932     //   are acceptable then,
00933     //"
00934     if (tcpseg->getSynBit())
00935     {
00936         //
00937         //   RCV.NXT is set to SEG.SEQ+1, IRS is set to
00938         //   SEG.SEQ.  SND.UNA should be advanced to equal SEG.ACK (if there
00939         //   is an ACK), and any segments on the retransmission queue which
00940         //   are thereby acknowledged should be removed.
00941         //
00942         state->rcv_nxt = tcpseg->getSequenceNo()+1;
00943         state->rcv_adv = state->rcv_nxt + state->rcv_wnd;
00944         if (rcvAdvVector) rcvAdvVector->record(state->rcv_adv);
00945         state->irs = tcpseg->getSequenceNo();
00946         receiveQueue->init(state->rcv_nxt);
00947 
00948         if (tcpseg->getAckBit())
00949         {
00950             state->snd_una = tcpseg->getAckNo();
00951             sendQueue->discardUpTo(state->snd_una);
00952             if (state->sack_enabled)
00953                 rexmitQueue->discardUpTo(state->snd_una);
00954 
00955             // although not mentioned in RFC 793, seems like we have to pick up
00956             // initial snd_wnd from the segment here.
00957             updateWndInfo(tcpseg, true);
00958         }
00959 
00960         // this also seems to be a good time to learn our local IP address
00961         // (was probably unspecified at connection open)
00962         tcpMain->updateSockPair(this, destAddr, srcAddr, tcpseg->getDestPort(), tcpseg->getSrcPort());
00963 
00964         //"
00965         //   If SND.UNA > ISS (our SYN has been ACKed), change the connection
00966         //   state to ESTABLISHED, form an ACK segment
00967         //
00968         //     <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
00969         //
00970         //   and send it.  Data or controls which were queued for
00971         //   transmission may be included.  If there are other controls or
00972         //   text in the segment then continue processing at the sixth step
00973         //   below where the URG bit is checked, otherwise return.
00974         //"
00975         if (seqGreater(state->snd_una, state->iss))
00976         {
00977             tcpEV << "SYN+ACK bits set, connection established.\n";
00978 
00979             // RFC says "continue processing at the sixth step below where
00980             // the URG bit is checked". Those steps deal with: URG, segment text
00981             // (and PSH), and FIN.
00982             // Now: URG and PSH we don't support yet; in SYN+FIN we ignore FIN;
00983             // with segment text we just take it easy and put it in the receiveQueue
00984             // -- we'll forward it to the user when more data arrives.
00985             if (tcpseg->getFinBit())
00986                 tcpEV << "SYN+ACK+FIN received: ignoring FIN\n";
00987             if (tcpseg->getPayloadLength()>0)
00988             {
00989                 updateRcvQueueVars();
00990                 if (state->freeRcvBuffer >= tcpseg->getPayloadLength()) // enough freeRcvBuffer in rcvQueue for new segment?
00991                 {
00992                     receiveQueue->insertBytesFromSegment(tcpseg);  // TBD forward to app, etc.
00993                 }
00994                 else    // not enough freeRcvBuffer in rcvQueue for new segment
00995                 {
00996                     state->tcpRcvQueueDrops++; // update current number of tcp receive queue drops
00997                     if (tcpRcvQueueDropsVector)
00998                         tcpRcvQueueDropsVector->record(state->tcpRcvQueueDrops);
00999 
01000                     tcpEV << "RcvQueueBuffer has run out, dropping segment\n";
01001                     return TCP_E_IGNORE;
01002                 }
01003             }
01004             if (tcpseg->getUrgBit() || tcpseg->getPshBit())
01005                 tcpEV << "Ignoring URG and PSH bits in SYN+ACK\n"; // TBD
01006 
01007             if (tcpseg->getHeaderLength() > TCP_HEADER_OCTETS) // Header options present? TCP_HEADER_OCTETS = 20
01008                 readHeaderOptions(tcpseg);
01009 
01010             // notify tcpAlgorithm (it has to send ACK of SYN) and app layer
01011             state->ack_now = true;
01012             tcpAlgorithm->established(true);
01013             sendEstabIndicationToApp();
01014 
01015             // This will trigger transition to ESTABLISHED. Timers and notifying
01016             // app will be taken care of in stateEntered().
01017             return TCP_E_RCV_SYN_ACK;
01018         }
01019 
01020         //"
01021         //   Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
01022         //
01023         //     <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
01024         //
01025         //   and send it.  If there are other controls or text in the
01026         //   segment, queue them for processing after the ESTABLISHED state
01027         //   has been reached, return.
01028         //"
01029         tcpEV << "SYN bit set: sending SYN+ACK\n";
01030         state->snd_max = state->snd_nxt = state->iss;
01031         sendSynAck();
01032         startSynRexmitTimer();
01033 
01034         // Note: code below is similar to processing SYN in LISTEN.
01035 
01036         // For consistency with that code, we ignore SYN+FIN here
01037         if (tcpseg->getFinBit())
01038             tcpEV << "SYN+FIN received: ignoring FIN\n";
01039 
01040         // We don't send text in SYN or SYN+ACK, but accept it. Otherwise
01041         // there isn't much left to do: RST, SYN, ACK, FIN got processed already,
01042         // so there's only URG and PSH left to handle.
01043         if (tcpseg->getPayloadLength()>0)
01044         {
01045             updateRcvQueueVars();
01046             if (state->freeRcvBuffer >= tcpseg->getPayloadLength()) // enough freeRcvBuffer in rcvQueue for new segment?
01047             {
01048                 receiveQueue->insertBytesFromSegment(tcpseg);  // TBD forward to app, etc.
01049             }
01050             else    // not enough freeRcvBuffer in rcvQueue for new segment
01051             {
01052                 state->tcpRcvQueueDrops++; // update current number of tcp receive queue drops
01053                 if (tcpRcvQueueDropsVector)
01054                     tcpRcvQueueDropsVector->record(state->tcpRcvQueueDrops);
01055 
01056                 tcpEV << "RcvQueueBuffer has run out, dropping segment\n";
01057                 return TCP_E_IGNORE;
01058             }
01059         }
01060         if (tcpseg->getUrgBit() || tcpseg->getPshBit())
01061             tcpEV << "Ignoring URG and PSH bits in SYN\n"; // TBD
01062 
01063         return TCP_E_RCV_SYN;
01064     }
01065 
01066     //"
01067     // fifth, if neither of the SYN or RST bits is set then drop the
01068     // segment and return.
01069     //"
01070     return TCP_E_IGNORE;
01071 }
01072 
01073 TCPEventCode TCPConnection::processRstInSynReceived(TCPSegment *tcpseg)
01074 {
01075     tcpEV2 << "Processing RST in SYN_RCVD\n";
01076 
01077     //"
01078     // If this connection was initiated with a passive OPEN (i.e.,
01079     // came from the LISTEN state), then return this connection to
01080     // LISTEN state and return.  The user need not be informed.  If
01081     // this connection was initiated with an active OPEN (i.e., came
01082     // from SYN-SENT state) then the connection was refused, signal
01083     // the user "connection refused".  In either case, all segments
01084     // on the retransmission queue should be removed.  And in the
01085     // active OPEN case, enter the CLOSED state and delete the TCB,
01086     // and return.
01087     //"
01088 
01089     sendQueue->discardUpTo(sendQueue->getBufferEndSeq()); // flush send queue
01090     if (state->sack_enabled)
01091         rexmitQueue->discardUpTo(rexmitQueue->getBufferEndSeq()); // flush rexmit queue
01092 
01093     if (state->active)
01094     {
01095         // signal "connection refused"
01096         sendIndicationToApp(TCP_I_CONNECTION_REFUSED);
01097     }
01098 
01099     // on RCV_RST, FSM will go either to LISTEN or to CLOSED, depending on state->active
01100     // FIXME if this was a forked connection, it should rather close than go back to listening (otherwise we'd now have two listening connections with the original one!)
01101     return TCP_E_RCV_RST;
01102 }
01103 
01104 bool TCPConnection::processAckInEstabEtc(TCPSegment *tcpseg)
01105 {
01106     tcpEV2 << "Processing ACK in a data transfer state\n";
01107 
01108     //
01109     //"
01110     //  If SND.UNA < SEG.ACK =< SND.NXT then, set SND.UNA <- SEG.ACK.
01111     //  Any segments on the retransmission queue which are thereby
01112     //  entirely acknowledged are removed.  Users should receive
01113     //  positive acknowledgments for buffers which have been SENT and
01114     //  fully acknowledged (i.e., SEND buffer should be returned with
01115     //  "ok" response).  If the ACK is a duplicate
01116     //  (SEG.ACK < SND.UNA), it can be ignored.  If the ACK acks
01117     //  something not yet sent (SEG.ACK > SND.NXT) then send an ACK,
01118     //  drop the segment, and return.
01119     //
01120     //  If SND.UNA < SEG.ACK =< SND.NXT, the send window should be
01121     //  updated.  If (SND.WL1 < SEG.SEQ or (SND.WL1 = SEG.SEQ and
01122     //  SND.WL2 =< SEG.ACK)), set SND.WND <- SEG.WND, set
01123     //  SND.WL1 <- SEG.SEQ, and set SND.WL2 <- SEG.ACK.
01124     //
01125     //  Note that SND.WND is an offset from SND.UNA, that SND.WL1
01126     //  records the sequence number of the last segment used to update
01127     //  SND.WND, and that SND.WL2 records the acknowledgment number of
01128     //  the last segment used to update SND.WND.  The check here
01129     //  prevents using old segments to update the window.
01130     //"
01131     // Note: should use SND.MAX instead of SND.NXT in above checks
01132     //
01133     if (seqGE(state->snd_una, tcpseg->getAckNo()))
01134     {
01135         //
01136         // duplicate ACK? A received TCP segment is a duplicate ACK if all of
01137         // the following apply:
01138         //    (1) snd_una==ackNo
01139         //    (2) segment contains no data
01140         //    (3) there's unacked data (snd_una!=snd_max)
01141         //
01142         // Note: ssfnet uses additional constraint "window is the same as last
01143         // received (not an update)" -- we don't do that because window updates
01144         // are ignored anyway if neither seqNo nor ackNo has changed.
01145         //
01146         if (state->snd_una==tcpseg->getAckNo() && tcpseg->getPayloadLength()==0 && state->snd_una!=state->snd_max)
01147         {
01148             state->dupacks++;
01149             if (dupAcksVector)
01150                 dupAcksVector->record(state->dupacks);
01151 
01152             // we need to update send window even if the ACK is a dupACK, because rcv win
01153             // could have been changed if faulty data receiver is not respecting the "do not shrink window" rule
01154             updateWndInfo(tcpseg);
01155 
01156             tcpAlgorithm->receivedDuplicateAck();
01157         }
01158         else
01159         {
01160             // if doesn't qualify as duplicate ACK, just ignore it.
01161             if (tcpseg->getPayloadLength()==0)
01162             {
01163                 if (state->snd_una!=tcpseg->getAckNo())
01164                     tcpEV << "Old ACK: ackNo<snd_una\n";
01165                 else if (state->snd_una==state->snd_max)
01166                     tcpEV << "ACK looks duplicate but we have currently no unacked data (snd_una==snd_max)\n";
01167             }
01168 
01169             // reset counter
01170             state->dupacks = 0;
01171             if (dupAcksVector)
01172                 dupAcksVector->record(state->dupacks);
01173         }
01174     }
01175     else if (seqLE(tcpseg->getAckNo(), state->snd_max))
01176     {
01177         // ack in window.
01178         uint32 old_snd_una = state->snd_una;
01179         state->snd_una = tcpseg->getAckNo();
01180         if (unackedVector) unackedVector->record(state->snd_max - state->snd_una);
01181 
01182         // after retransmitting a lost segment, we may get an ack well ahead of snd_nxt
01183         if (seqLess(state->snd_nxt, state->snd_una))
01184             state->snd_nxt = state->snd_una;
01185 
01186         // RFC 1323, page 36:
01187         // "If SND.UNA < SEG.ACK =< SND.NXT then, set SND.UNA <- SEG.ACK.
01188         // Also compute a new estimate of round-trip time.  If Snd.TS.OK
01189         // bit is on, use my.TSclock - SEG.TSecr; otherwise use the
01190         // elapsed time since the first segment in the retransmission
01191         // queue was sent.  Any segments on the retransmission queue
01192         // which are thereby entirely acknowledged."
01193         if (state->ts_enabled)
01194             tcpAlgorithm->rttMeasurementCompleteUsingTS(getTSecr(tcpseg));
01195         // Note: If TS is disabled the RTT measurement is complete in TCPBaseAlg::receivedDataAck()
01196 
01197         uint32 discardUpToSeq = state->snd_una;
01198 
01199         // our FIN acked?
01200         if (state->send_fin && tcpseg->getAckNo()==state->snd_fin_seq+1)
01201         {
01202             // set flag that our FIN has been acked
01203             tcpEV << "ACK acks our FIN\n";
01204             state->fin_ack_rcvd = true;
01205             discardUpToSeq--; // the FIN sequence number is not real data
01206         }
01207 
01208         // acked data no longer needed in send queue
01209         sendQueue->discardUpTo(discardUpToSeq);
01210         // acked data no longer needed in rexmit queue
01211         if (state->sack_enabled)
01212             rexmitQueue->discardUpTo(discardUpToSeq);
01213 
01214         updateWndInfo(tcpseg);
01215 
01216         // if segment contains data, wait until data has been forwarded to app before sending ACK,
01217         // otherwise we would use an old ACKNo
01218         if (tcpseg->getPayloadLength() == 0 && fsm.getState()!=TCP_S_SYN_RCVD)
01219         {
01220             // notify
01221             tcpAlgorithm->receivedDataAck(old_snd_una);
01222 
01223             // in the receivedDataAck we need the old value
01224             state->dupacks = 0;
01225             if (dupAcksVector)
01226                 dupAcksVector->record(state->dupacks);
01227         }
01228     }
01229     else
01230     {
01231         ASSERT(seqGreater(tcpseg->getAckNo(), state->snd_max)); // from if-ladder
01232 
01233         // send an ACK, drop the segment, and return.
01234         tcpAlgorithm->receivedAckForDataNotYetSent(tcpseg->getAckNo());
01235         state->dupacks = 0;
01236         if (dupAcksVector)
01237             dupAcksVector->record(state->dupacks);
01238         return false;  // means "drop"
01239     }
01240 
01241     return true;
01242 }
01243 
01244 //----
01245 
01246 void TCPConnection::process_TIMEOUT_CONN_ESTAB()
01247 {
01248     switch(fsm.getState())
01249     {
01250         case TCP_S_SYN_RCVD:
01251         case TCP_S_SYN_SENT:
01252             // Nothing to do here. TIMEOUT_CONN_ESTAB event will automatically
01253             // take the connection to LISTEN or CLOSED, and cancel SYN-REXMIT timer.
01254             if (state->active)
01255             {
01256                 // notify user if we're on the active side
01257                 sendIndicationToApp(TCP_I_TIMED_OUT);
01258             }
01259             break;
01260         default:
01261             // We should not receive this timeout in this state.
01262             opp_error("Internal error: received CONN_ESTAB timeout in state %s", stateName(fsm.getState()));
01263     }
01264 }
01265 
01266 void TCPConnection::process_TIMEOUT_2MSL()
01267 {
01268     //"
01269     // If the time-wait timeout expires on a connection delete the TCB,
01270     // enter the CLOSED state and return.
01271     //"
01272     switch(fsm.getState())
01273     {
01274         case TCP_S_TIME_WAIT:
01275             // Nothing to do here. The TIMEOUT_2MSL event will automatically take
01276             // the connection to CLOSED. We already notified the user
01277             // (TCP_I_CLOSED) when we entered the TIME_WAIT state from CLOSING,
01278             // FIN_WAIT_1 or FIN_WAIT_2.
01279             break;
01280         default:
01281             // We should not receive this timeout in this state.
01282             opp_error("Internal error: received time-wait (2MSL) timeout in state %s", stateName(fsm.getState()));
01283     }
01284 }
01285 
01286 void TCPConnection::process_TIMEOUT_FIN_WAIT_2()
01287 {
01288     switch(fsm.getState())
01289     {
01290         case TCP_S_FIN_WAIT_2:
01291             // Nothing to do here. The TIMEOUT_FIN_WAIT_2 event will automatically take
01292             // the connection to CLOSED.
01293             sendIndicationToApp(TCP_I_CLOSED);
01294             break;
01295         default:
01296             // We should not receive this timeout in this state.
01297             opp_error("Internal error: received FIN_WAIT_2 timeout in state %s", stateName(fsm.getState()));
01298     }
01299 }
01300 
01301 void TCPConnection::startSynRexmitTimer()
01302 {
01303     state->syn_rexmit_count = 0;
01304     state->syn_rexmit_timeout = TCP_TIMEOUT_SYN_REXMIT;
01305 
01306     if (synRexmitTimer->isScheduled())
01307         cancelEvent(synRexmitTimer);
01308     scheduleTimeout(synRexmitTimer, state->syn_rexmit_timeout);
01309 }
01310 
01311 void TCPConnection::process_TIMEOUT_SYN_REXMIT(TCPEventCode& event)
01312 {
01313     if (++state->syn_rexmit_count>MAX_SYN_REXMIT_COUNT)
01314     {
01315         tcpEV << "Retransmission count during connection setup exceeds " << MAX_SYN_REXMIT_COUNT << ", giving up\n";
01316         // Note ABORT will take the connection to closed, and cancel CONN-ESTAB timer as well
01317         event = TCP_E_ABORT;
01318         return;
01319     }
01320 
01321     tcpEV << "Performing retransmission #" << state->syn_rexmit_count << "\n";
01322 
01323     // resend what's needed
01324     switch(fsm.getState())
01325     {
01326         case TCP_S_SYN_SENT: sendSyn(); break;
01327         case TCP_S_SYN_RCVD: sendSynAck(); break;
01328         default:  opp_error("Internal error: SYN-REXMIT timer expired while in state %s", stateName(fsm.getState()));
01329     }
01330 
01331     // reschedule timer
01332     state->syn_rexmit_timeout *= 2;
01333 
01334     if (state->syn_rexmit_timeout > TCP_TIMEOUT_SYN_REXMIT_MAX)
01335         state->syn_rexmit_timeout = TCP_TIMEOUT_SYN_REXMIT_MAX;
01336     scheduleTimeout(synRexmitTimer, state->syn_rexmit_timeout);
01337 }
01338 
01339 
01340 //
01341 //TBD:
01342 //"
01343 // USER TIMEOUT
01344 //
01345 //    For any state if the user timeout expires, flush all queues, signal
01346 //    the user "error:  connection aborted due to user timeout" in general
01347 //    and for any outstanding calls, delete the TCB, enter the CLOSED
01348 //    state and return.
01349 //"