|
INET Framework for OMNeT++/OMNEST
|
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