TCPConnectionBase.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 <assert.h>
00022 #include "TCP.h"
00023 #include "TCPConnection.h"
00024 #include "TCPSegment.h"
00025 #include "TCPCommand_m.h"
00026 #include "TCPSendQueue.h"
00027 #include "TCPReceiveQueue.h"
00028 #include "TCPAlgorithm.h"
00029 #include "TCPSACKRexmitQueue.h"
00030 
00031 
00032 TCPStateVariables::TCPStateVariables()
00033 {
00034     // set everything to 0 -- real init values will be set manually
00035     active = false;
00036     fork = false;
00037     snd_mss = 0; // will initially be set from configureStateVariables() and probably reset during connection setup
00038     snd_una = 0;
00039     snd_nxt = 0;
00040     snd_max = 0;
00041     snd_wnd = 0;
00042     snd_up = 0;
00043     snd_wl1 = 0;
00044     snd_wl2 = 0;
00045     iss = 0;
00046 
00047     rcv_nxt = 0;
00048     rcv_wnd = 0; // will be set from configureStateVariables()
00049     rcv_up = 0;
00050     irs = 0;
00051     rcv_adv = 0; // will be set from configureStateVariables()
00052 
00053     syn_rexmit_count = 0;
00054     syn_rexmit_timeout = 0;
00055 
00056     fin_ack_rcvd = false;
00057     send_fin = false;
00058     snd_fin_seq = 0;
00059     fin_rcvd = false;
00060     rcv_fin_seq = 0;
00061     sentBytes = 0;
00062 
00063     nagle_enabled = false;      // will be set from configureStateVariables()
00064     delayed_acks_enabled = false; // will be set from configureStateVariables()
00065     limited_transmit_enabled = false; // will be set from configureStateVariables()
00066     increased_IW_enabled = false; // will be set from configureStateVariables()
00067     full_sized_segment_counter = 0;
00068     ack_now = false;
00069 
00070     afterRto = false;
00071 
00072     time_last_data_sent = 0;
00073 
00074     ws_support = false;       // will be set from configureStateVariables()
00075     ws_enabled = false;
00076     snd_ws = false;
00077     rcv_ws = false;
00078     rcv_wnd_scale = 0;        // will be set from configureStateVariables()
00079     snd_wnd_scale = 0;      
00080 
00081     ts_support = false;       // will be set from configureStateVariables()
00082     ts_enabled = false;
00083     snd_initial_ts = false;
00084     rcv_initial_ts = false;
00085     ts_recent = 0;
00086     last_ack_sent = 0;
00087 
00088     sack_support = false;       // will be set from configureStateVariables()
00089     sack_enabled = false;
00090     snd_sack_perm = false;
00091     rcv_sack_perm = false;
00092 
00093     snd_sack = false;
00094     snd_dsack = false;
00095     start_seqno = 0;
00096     end_seqno = 0;
00097     highRxt = 0;
00098     pipe = 0;
00099     recoveryPoint = 0;
00100     sackedBytes = 0;
00101     sackedBytes_old = 0;
00102     lossRecovery = false;
00103 
00104     dupacks = 0;
00105     snd_sacks = 0;
00106     rcv_sacks = 0;
00107     rcv_oooseg = 0;
00108 
00109     maxRcvBuffer  = 0;  // will be set from configureStateVariables()
00110     usedRcvBuffer = 0;
00111     freeRcvBuffer = 0;
00112     tcpRcvQueueDrops = 0;
00113 }
00114 
00115 std::string TCPStateVariables::info() const
00116 {
00117     std::stringstream out;
00118     out <<  "snd_una=" << snd_una;
00119     out << " snd_nxt=" << snd_nxt;
00120     out << " snd_max=" << snd_max;
00121     out << " snd_wnd=" << snd_wnd;
00122     out << " rcv_nxt=" << rcv_nxt;
00123     out << " rcv_wnd=" << rcv_wnd;
00124     return out.str();
00125 }
00126 
00127 std::string TCPStateVariables::detailedInfo() const
00128 {
00129     std::stringstream out;
00130     out << "active = " << active << "\n";
00131     out << "snd_mss = " << snd_mss << "\n";
00132     out << "snd_una = " << snd_una << "\n";
00133     out << "snd_nxt = " << snd_nxt << "\n";
00134     out << "snd_max = " << snd_max << "\n";
00135     out << "snd_wnd = " << snd_wnd << "\n";
00136     out << "snd_up = " << snd_up << "\n";
00137     out << "snd_wl1 = " << snd_wl1 << "\n";
00138     out << "snd_wl2 = " << snd_wl2 << "\n";
00139     out << "iss = " << iss << "\n";
00140     out << "rcv_nxt = " << rcv_nxt << "\n";
00141     out << "rcv_wnd = " << rcv_wnd << "\n";
00142     out << "rcv_up = " << rcv_up << "\n";
00143     out << "irs = " << irs << "\n";
00144     out << "rcv_adv = " << rcv_adv << "\n";
00145     out << "fin_ack_rcvd = " << fin_ack_rcvd << "\n";
00146     out << "nagle_enabled = " << nagle_enabled << "\n";
00147     out << "limited_transmit_enabled = " << limited_transmit_enabled << "\n";
00148     out << "increased_IW_enabled = " << increased_IW_enabled << "\n";
00149     out << "delayed_acks_enabled = " << delayed_acks_enabled << "\n";
00150     out << "ws_support = " << ws_support << "\n";
00151     out << "ws_enabled = " << ws_enabled << "\n";
00152     out << "ts_support = " << ts_support << "\n";
00153     out << "ts_enabled = " << ts_enabled << "\n";
00154     out << "sack_support = " << sack_support << "\n";
00155     out << "sack_enabled = " << sack_enabled << "\n";
00156     out << "snd_sack_perm = " << snd_sack_perm << "\n";
00157     out << "snd_sacks = " << snd_sacks << "\n";
00158     out << "rcv_sacks = " << rcv_sacks << "\n";
00159     out << "dupacks = " << dupacks << "\n";
00160     out << "rcv_oooseg = " << rcv_oooseg << "\n";
00161     return out.str();
00162 }
00163 
00164 TCPConnection::TCPConnection()
00165 {
00166     // Note: this ctor is NOT used to create live connections, only
00167     // temporary ones to invoke segmentArrivalWhileClosed() on
00168     sendQueue = NULL;
00169     rexmitQueue = NULL;
00170     receiveQueue = NULL;
00171     tcpAlgorithm = NULL;
00172     state = NULL;
00173     the2MSLTimer = connEstabTimer = finWait2Timer = synRexmitTimer = NULL;
00174     sndWndVector = rcvWndVector = rcvAdvVector = sndNxtVector = sndAckVector = rcvSeqVector = rcvAckVector = unackedVector =
00175     dupAcksVector = sndSacksVector = rcvSacksVector = rcvOooSegVector =
00176     tcpRcvQueueBytesVector = tcpRcvQueueDropsVector = pipeVector = sackedBytesVector = NULL;
00177 }
00178 
00179 //
00180 // FSM framework, TCP FSM
00181 //
00182 
00183 TCPConnection::TCPConnection(TCP *_mod, int _appGateIndex, int _connId)
00184 {
00185     tcpMain = _mod;
00186     appGateIndex = _appGateIndex;
00187     connId = _connId;
00188 
00189     localPort = remotePort = -1;
00190 
00191     char fsmname[24];
00192     sprintf(fsmname, "fsm-%d", connId);
00193     fsm.setName(fsmname);
00194     fsm.setState(TCP_S_INIT);
00195 
00196 
00197     // queues and algorithm will be created on active or passive open
00198     sendQueue = NULL;
00199     rexmitQueue = NULL;
00200     receiveQueue = NULL;
00201     tcpAlgorithm = NULL;
00202     state = NULL;
00203 
00204     the2MSLTimer = new cMessage("2MSL");
00205     connEstabTimer = new cMessage("CONN-ESTAB");
00206     finWait2Timer = new cMessage("FIN-WAIT-2");
00207     synRexmitTimer = new cMessage("SYN-REXMIT");
00208 
00209     the2MSLTimer->setContextPointer(this);
00210     connEstabTimer->setContextPointer(this);
00211     finWait2Timer->setContextPointer(this);
00212     synRexmitTimer->setContextPointer(this);
00213 
00214     // statistics
00215     sndWndVector = NULL;
00216     rcvWndVector = NULL;
00217     rcvAdvVector = NULL;
00218     sndNxtVector = NULL;
00219     sndAckVector = NULL;
00220     rcvSeqVector = NULL;
00221     rcvAckVector = NULL;
00222     unackedVector = NULL;
00223 
00224     dupAcksVector = NULL;
00225     sndSacksVector = NULL;
00226     rcvSacksVector = NULL;
00227     rcvOooSegVector = NULL;
00228     tcpRcvQueueBytesVector = NULL;
00229     tcpRcvQueueDropsVector = NULL;
00230     pipeVector = NULL;
00231     sackedBytesVector = NULL;
00232 
00233     if (getTcpMain()->recordStatistics)
00234     {
00235         sndWndVector = new cOutVector("send window");
00236         rcvWndVector = new cOutVector("receive window");
00237         rcvAdvVector = new cOutVector("advertised window");
00238         sndNxtVector = new cOutVector("sent seq");
00239         sndAckVector = new cOutVector("sent ack");
00240         rcvSeqVector = new cOutVector("rcvd seq");
00241         rcvAckVector = new cOutVector("rcvd ack");
00242         unackedVector = new cOutVector("unacked bytes");
00243         dupAcksVector = new cOutVector("rcvd dupAcks");
00244         pipeVector = new cOutVector("pipe");
00245         sndSacksVector = new cOutVector("sent sacks");
00246         rcvSacksVector = new cOutVector("rcvd sacks");
00247         rcvOooSegVector = new cOutVector("rcvd oooseg");
00248         sackedBytesVector = new cOutVector("rcvd sackedBytes");
00249         tcpRcvQueueBytesVector = new cOutVector("tcpRcvQueueBytes");
00250         tcpRcvQueueDropsVector = new cOutVector("tcpRcvQueueDrops");
00251     }
00252 }
00253 
00254 TCPConnection::~TCPConnection()
00255 {
00256     delete sendQueue;
00257     delete rexmitQueue;
00258     delete receiveQueue;
00259     delete tcpAlgorithm;
00260     delete state;
00261 
00262     if (the2MSLTimer)   delete cancelEvent(the2MSLTimer);
00263     if (connEstabTimer) delete cancelEvent(connEstabTimer);
00264     if (finWait2Timer)  delete cancelEvent(finWait2Timer);
00265     if (synRexmitTimer) delete cancelEvent(synRexmitTimer);
00266 
00267     // statistics
00268     delete sndWndVector;
00269     delete rcvWndVector;
00270     delete rcvAdvVector;
00271     delete sndNxtVector;
00272     delete sndAckVector;
00273     delete rcvSeqVector;
00274     delete rcvAckVector;
00275     delete unackedVector;
00276     delete dupAcksVector;
00277     delete sndSacksVector;
00278     delete rcvSacksVector;
00279     delete rcvOooSegVector;
00280     delete tcpRcvQueueBytesVector;
00281     delete tcpRcvQueueDropsVector;
00282     delete pipeVector;
00283     delete sackedBytesVector;
00284 }
00285 
00286 bool TCPConnection::processTimer(cMessage *msg)
00287 {
00288     printConnBrief();
00289     tcpEV << msg->getName() << " timer expired\n";
00290 
00291     // first do actions
00292     TCPEventCode event;
00293     if (msg==the2MSLTimer)
00294     {
00295         event = TCP_E_TIMEOUT_2MSL;
00296         process_TIMEOUT_2MSL();
00297     }
00298     else if (msg==connEstabTimer)
00299     {
00300         event = TCP_E_TIMEOUT_CONN_ESTAB;
00301         process_TIMEOUT_CONN_ESTAB();
00302     }
00303     else if (msg==finWait2Timer)
00304     {
00305         event = TCP_E_TIMEOUT_FIN_WAIT_2;
00306         process_TIMEOUT_FIN_WAIT_2();
00307     }
00308     else if (msg==synRexmitTimer)
00309     {
00310         event = TCP_E_IGNORE;
00311         process_TIMEOUT_SYN_REXMIT(event);
00312     }
00313     else
00314     {
00315         event = TCP_E_IGNORE;
00316         tcpAlgorithm->processTimer(msg, event);
00317     }
00318 
00319     // then state transitions
00320     return performStateTransition(event);
00321 }
00322 
00323 bool TCPConnection::processTCPSegment(TCPSegment *tcpseg, IPvXAddress segSrcAddr, IPvXAddress segDestAddr)
00324 {
00325     printConnBrief();
00326     if (!localAddr.isUnspecified())
00327     {
00328         ASSERT(localAddr==segDestAddr);
00329         ASSERT(localPort==tcpseg->getDestPort());
00330     }
00331     if (!remoteAddr.isUnspecified())
00332     {
00333         ASSERT(remoteAddr==segSrcAddr);
00334         ASSERT(remotePort==tcpseg->getSrcPort());
00335     }
00336 
00337     if (tryFastRoute(tcpseg))
00338         return true;
00339 
00340     // first do actions
00341     TCPEventCode event = process_RCV_SEGMENT(tcpseg, segSrcAddr, segDestAddr);
00342 
00343     // then state transitions
00344     return performStateTransition(event);
00345 }
00346 
00347 bool TCPConnection::processAppCommand(cMessage *msg)
00348 {
00349     printConnBrief();
00350 
00351     // first do actions
00352     TCPCommand *tcpCommand = (TCPCommand *)(msg->removeControlInfo());
00353     TCPEventCode event = preanalyseAppCommandEvent(msg->getKind());
00354     tcpEV << "App command: " << eventName(event) << "\n";
00355     switch (event)
00356     {
00357         case TCP_E_OPEN_ACTIVE: process_OPEN_ACTIVE(event, tcpCommand, msg); break;
00358         case TCP_E_OPEN_PASSIVE: process_OPEN_PASSIVE(event, tcpCommand, msg); break;
00359         case TCP_E_SEND: process_SEND(event, tcpCommand, msg); break;
00360         case TCP_E_CLOSE: process_CLOSE(event, tcpCommand, msg); break;
00361         case TCP_E_ABORT: process_ABORT(event, tcpCommand, msg); break;
00362         case TCP_E_STATUS: process_STATUS(event, tcpCommand, msg); break;
00363         default: opp_error("wrong event code");
00364     }
00365 
00366     // then state transitions
00367     return performStateTransition(event);
00368 }
00369 
00370 
00371 TCPEventCode TCPConnection::preanalyseAppCommandEvent(int commandCode)
00372 {
00373     switch (commandCode)
00374     {
00375         case TCP_C_OPEN_ACTIVE:  return TCP_E_OPEN_ACTIVE;
00376         case TCP_C_OPEN_PASSIVE: return TCP_E_OPEN_PASSIVE;
00377         case TCP_C_SEND:         return TCP_E_SEND;
00378         case TCP_C_CLOSE:        return TCP_E_CLOSE;
00379         case TCP_C_ABORT:        return TCP_E_ABORT;
00380         case TCP_C_STATUS:       return TCP_E_STATUS;
00381         default: opp_error("Unknown message kind in app command");
00382                  return (TCPEventCode)0; // to satisfy compiler
00383     }
00384 }
00385 
00386 bool TCPConnection::performStateTransition(const TCPEventCode& event)
00387 {
00388     ASSERT(fsm.getState()!=TCP_S_CLOSED); // closed connections should be deleted immediately
00389 
00390     if (event==TCP_E_IGNORE)  // e.g. discarded segment
00391     {
00392         tcpEV << "Staying in state: " << stateName(fsm.getState()) << " (no FSM event)\n";
00393         return true;
00394     }
00395 
00396     // state machine
00397     // TBD add handling of connection timeout event (KEEP-ALIVE), with transition to CLOSED
00398     // Note: empty "default:" lines are for gcc's benefit which would otherwise spit warnings
00399     int oldState = fsm.getState();
00400     switch (fsm.getState())
00401     {
00402         case TCP_S_INIT:
00403             switch (event)
00404             {
00405                 case TCP_E_OPEN_PASSIVE:FSM_Goto(fsm, TCP_S_LISTEN); break;
00406                 case TCP_E_OPEN_ACTIVE: FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00407                 default:;
00408             }
00409             break;
00410 
00411         case TCP_S_LISTEN:
00412             switch (event)
00413             {
00414                 case TCP_E_OPEN_ACTIVE: FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00415                 case TCP_E_SEND:        FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00416                 case TCP_E_CLOSE:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00417                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00418                 case TCP_E_RCV_SYN:     FSM_Goto(fsm, TCP_S_SYN_RCVD);break;
00419                 default:;
00420             }
00421             break;
00422 
00423         case TCP_S_SYN_RCVD:
00424             switch (event)
00425             {
00426                 case TCP_E_CLOSE:       FSM_Goto(fsm, TCP_S_FIN_WAIT_1); break;
00427                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00428                 case TCP_E_TIMEOUT_CONN_ESTAB: FSM_Goto(fsm, state->active ? TCP_S_CLOSED : TCP_S_LISTEN); break;
00429                 case TCP_E_RCV_RST:     FSM_Goto(fsm, state->active ? TCP_S_CLOSED : TCP_S_LISTEN); break;
00430                 case TCP_E_RCV_ACK:     FSM_Goto(fsm, TCP_S_ESTABLISHED); break;
00431                 case TCP_E_RCV_FIN:     FSM_Goto(fsm, TCP_S_CLOSE_WAIT); break;
00432                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00433                 default:;
00434             }
00435             break;
00436 
00437         case TCP_S_SYN_SENT:
00438             switch (event)
00439             {
00440                 case TCP_E_CLOSE:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00441                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00442                 case TCP_E_TIMEOUT_CONN_ESTAB: FSM_Goto(fsm, TCP_S_CLOSED); break;
00443                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00444                 case TCP_E_RCV_SYN_ACK: FSM_Goto(fsm, TCP_S_ESTABLISHED); break;
00445                 case TCP_E_RCV_SYN:     FSM_Goto(fsm, TCP_S_SYN_RCVD); break;
00446                 default:;
00447             }
00448             break;
00449 
00450         case TCP_S_ESTABLISHED:
00451             switch (event)
00452             {
00453                 case TCP_E_CLOSE:       FSM_Goto(fsm, TCP_S_FIN_WAIT_1); break;
00454                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00455                 case TCP_E_RCV_FIN:     FSM_Goto(fsm, TCP_S_CLOSE_WAIT); break;
00456                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00457                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00458                 default:;
00459             }
00460             break;
00461 
00462         case TCP_S_CLOSE_WAIT:
00463             switch (event)
00464             {
00465                 case TCP_E_CLOSE:       FSM_Goto(fsm, TCP_S_LAST_ACK); break;
00466                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00467                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00468                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00469                 default:;
00470             }
00471             break;
00472 
00473         case TCP_S_LAST_ACK:
00474             switch (event)
00475             {
00476                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00477                 case TCP_E_RCV_ACK:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00478                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00479                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00480                 default:;
00481             }
00482             break;
00483 
00484         case TCP_S_FIN_WAIT_1:
00485             switch (event)
00486             {
00487                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00488                 case TCP_E_RCV_FIN:     FSM_Goto(fsm, TCP_S_CLOSING); break;
00489                 case TCP_E_RCV_ACK:     FSM_Goto(fsm, TCP_S_FIN_WAIT_2); break;
00490                 case TCP_E_RCV_FIN_ACK: FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00491                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00492                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00493                 default:;
00494             }
00495             break;
00496 
00497         case TCP_S_FIN_WAIT_2:
00498             switch (event)
00499             {
00500                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00501                 case TCP_E_RCV_FIN:     FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00502                 case TCP_E_TIMEOUT_FIN_WAIT_2: FSM_Goto(fsm, TCP_S_CLOSED); break;
00503                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00504                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00505                 default:;
00506             }
00507             break;
00508 
00509         case TCP_S_CLOSING:
00510             switch (event)
00511             {
00512                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00513                 case TCP_E_RCV_ACK:     FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00514                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00515                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00516                 default:;
00517             }
00518             break;
00519 
00520         case TCP_S_TIME_WAIT:
00521             switch (event)
00522             {
00523                 case TCP_E_ABORT:       FSM_Goto(fsm, TCP_S_CLOSED); break;
00524                 case TCP_E_TIMEOUT_2MSL: FSM_Goto(fsm, TCP_S_CLOSED); break;
00525                 case TCP_E_RCV_RST:     FSM_Goto(fsm, TCP_S_CLOSED); break;
00526                 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00527                 default:;
00528             }
00529             break;
00530 
00531         case TCP_S_CLOSED:
00532             break;
00533     }
00534 
00535     if (oldState!=fsm.getState())
00536     {
00537         tcpEV << "Transition: " << stateName(oldState) << " --> " << stateName(fsm.getState()) << "  (event was: " << eventName(event) << ")\n";
00538         testingEV << tcpMain->getName() << ": " << stateName(oldState) << " --> " << stateName(fsm.getState()) << "  (on " << eventName(event) << ")\n";
00539 
00540         // cancel timers, etc.
00541         stateEntered(fsm.getState());
00542     }
00543     else
00544     {
00545         tcpEV << "Staying in state: " << stateName(fsm.getState()) << " (event was: " << eventName(event) << ")\n";
00546     }
00547 
00548     return fsm.getState()!=TCP_S_CLOSED;
00549 }
00550 
00551 void TCPConnection::stateEntered(int state)
00552 {
00553     // cancel timers
00554     switch (state)
00555     {
00556         case TCP_S_INIT:
00557             // we'll never get back to INIT
00558             break;
00559         case TCP_S_LISTEN:
00560             // we may get back to LISTEN from SYN_RCVD
00561             ASSERT(connEstabTimer && synRexmitTimer);
00562             cancelEvent(connEstabTimer);
00563             cancelEvent(synRexmitTimer);
00564             break;
00565         case TCP_S_SYN_RCVD:
00566         case TCP_S_SYN_SENT:
00567             break;
00568         case TCP_S_ESTABLISHED:
00569             // we're in ESTABLISHED, these timers are no longer needed
00570             delete cancelEvent(connEstabTimer);
00571             delete cancelEvent(synRexmitTimer);
00572             connEstabTimer = synRexmitTimer = NULL;
00573             // TCP_I_ESTAB notification moved inside event processing
00574             break;
00575         case TCP_S_CLOSE_WAIT:
00576         case TCP_S_LAST_ACK:
00577         case TCP_S_FIN_WAIT_1:
00578         case TCP_S_FIN_WAIT_2:
00579         case TCP_S_CLOSING:
00580         case TCP_S_TIME_WAIT:
00581             // whether connection setup succeeded (ESTABLISHED) or not (others),
00582             // cancel these timers
00583             if (connEstabTimer) cancelEvent(connEstabTimer);
00584             if (synRexmitTimer) cancelEvent(synRexmitTimer);
00585             break;
00586         case TCP_S_CLOSED:
00587             // all timers need to be cancelled
00588             if (the2MSLTimer)   cancelEvent(the2MSLTimer);
00589             if (connEstabTimer) cancelEvent(connEstabTimer);
00590             if (finWait2Timer)  cancelEvent(finWait2Timer);
00591             if (synRexmitTimer) cancelEvent(synRexmitTimer);
00592             tcpAlgorithm->connectionClosed();
00593             break;
00594     }
00595 }
00596 
00597