|
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 "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 //"