⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp-sock.cc

📁 升级版的p2p文件共享linux环境ns2仿真软件
💻 CC
📖 第 1 页 / 共 3 页
字号:
	case TCPS_LISTEN:	/* awaiting peer's SYN */		if (tiflags & TH_ACK) {			goto dropwithreset;		}		if ((tiflags & TH_SYN) == 0) {			goto drop;		}	  if(listen_only_) {	    if(app_)	      ((NSSocket *)app_)->upcall_accept(pkt);	    return;	  }		/*		 * must by a SYN (no ACK) at this point...		 * in real tcp we would bump the iss counter here also		 */		dooptions(pkt);		irs_ = tcph->seqno();		t_seqno_ = iss_; /* tcp_sendseqinit() macro in real tcp */		rcv_nxt_ = rcvseqinit(irs_, datalen);		flags_ |= TF_ACKNOW;		if (ecn_ && fh->ecnecho()) {			ect_ = TRUE;		}		newstate(TCPS_SYN_RECEIVED);		goto trimthenstep6;        /*         * If the state is SYN_SENT:         *      if seg contains an ACK, but not for our SYN, drop the input.         *      if seg does not contain SYN, then drop it.         * Otherwise this is an acceptable SYN segment         *      initialize tp->rcv_nxt and tp->irs         *      if seg contains ack then advance tp->snd_una         *      if SYN has been acked change to ESTABLISHED else SYN_RCVD state         *      arrange for segment to be acked (eventually)         *      continue processing rest of data/controls, beginning with URG         */	case TCPS_SYN_SENT:	/* we sent SYN, expecting SYN+ACK (or SYN) */		/* drop if it's a SYN+ACK and the ack field is bad */		if ((tiflags & TH_ACK) &&			((ackno <= iss_) || (ackno > maxseq_))) {			// not an ACK for our SYN, discard			fprintf(stderr,			    "%f: FullTcpAgent::recv(%s): bad ACK (%d) for our SYN(%d)\n",			        now(), name(), int(ackno), int(maxseq_));			goto dropwithreset;		}		if ((tiflags & TH_SYN) == 0) {			fprintf(stderr,			    "%f: FullTcpAgent::recv(%s): no SYN for our SYN(%d)\n",			        now(), name(), int(maxseq_));			goto drop;		}		/* looks like an ok SYN or SYN+ACK */#ifdef notdef		cancel_rtx_timer();	// cancel timer on our 1st SYN [does this belong!?]#endif		irs_ = tcph->seqno();	// get initial recv'd seq #		rcv_nxt_ = rcvseqinit(irs_, datalen);		/*		 * we are seeing either a SYN or SYN+ACK.  For pure SYN,		 * ecnecho tells us our peer is ecn-capable.  For SYN+ACK,		 * it's acking our SYN, so it already knows we're ecn capable,		 * so it can just turn on ect		 */		if (ecn_ && (fh->ecnecho() || fh->ect()))			ect_ = TRUE;		if (tiflags & TH_ACK) {			// SYN+ACK (our SYN was acked)			// CHECKME			highest_ack_ = ackno;			cwnd_ = initial_window();#ifdef notdef			/*			 * if we didn't have to retransmit the SYN,			 * use its rtt as our initial srtt & rtt var.			 */			if (t_rtt_) {			  double tao = now() - tcph->ts();			  rtt_update(tao);			}#endif			/*			 * if there's data, delay ACK; if there's also a FIN			 * ACKNOW will be turned on later.			 */			if (datalen > 0) {				flags_ |= TF_DELACK;	// data there: wait			} else {				flags_ |= TF_ACKNOW;	// ACK peer's SYN			}                        /*                         * Received <SYN,ACK> in SYN_SENT[*] state.                         * Transitions:                         *      SYN_SENT  --> ESTABLISHED                         *      SYN_SENT* --> FIN_WAIT_1                         */			int newst = FALSE;			if (flags_ & TF_NEEDFIN) {				newstate(TCPS_FIN_WAIT_1);				flags_ &= ~TF_NEEDFIN;				tiflags &= ~TH_SYN;			} else {				newstate(TCPS_ESTABLISHED);#ifdef PDNS				hdr_rti *rtih = hdr_rti::access(pkt);				dst_ipaddr_ = rtih->ipsrc();				dst_ipport_ = rtih->ipsrcport();				if(GetLocalIP(dst_ipaddr_))				  dst_= iph->src();#else				dst_ = iph->src();#endif				newst = TRUE;			}			// special to ns:			//  generate pure ACK here.			//  this simulates the ordinary connection establishment			//  where the ACK of the peer's SYN+ACK contains			//  no data.  This is typically caused by the way			//  the connect() socket call works in which the			//  entire 3-way handshake occurs prior to the app			//  being able to issue a write() [which actually			//  causes the segment to be sent].			//sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, 0);			sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, NULL, 0);			if(app_ && newst) 			  ((NSSocket *)app_)->upcall_connected(pkt);		} else {			// SYN (no ACK) (simultaneous active opens)			flags_ |= TF_ACKNOW;			cancel_rtx_timer();			newstate(TCPS_SYN_RECEIVED);			/*			 * decrement t_seqno_: we are sending a			 * 2nd SYN (this time in the form of a			 * SYN+ACK, so t_seqno_ will have been			 * advanced to 2... reduce this			 */			t_seqno_--;	// CHECKME		}trimthenstep6:		/*		 * advance the seq# to correspond to first data byte		 */		tcph->seqno()++;		if (tiflags & TH_ACK)			goto process_ACK;		goto step6;	case TCPS_LAST_ACK:	case TCPS_CLOSING:		break;	} /* end switch(state_) */        /*         * States other than LISTEN or SYN_SENT.         * First check timestamp, if present.         * Then check that at least some bytes of segment are within         * receive window.  If segment begins before rcv_nxt,         * drop leading data (and SYN); if nothing left, just ack.         *         * RFC 1323 PAWS: If we have a timestamp reply on this segment         * and it's less than ts_recent, drop it.         */	if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {		if ((now() - recent_age_) > TCP_PAWS_IDLE) {			/*			 * this is basically impossible in the simulator,			 * but here it is...			 */                        /*                         * Invalidate ts_recent.  If this segment updates                         * ts_recent, the age will be reset later and ts_recent                         * will get a valid value.  If it does not, setting                         * ts_recent to zero will at least satisfy the                         * requirement that zero be placed in the timestamp                         * echo reply when ts_recent isn't valid.  The                         * age isn't reset until we get a valid ts_recent                         * because we don't want out-of-order segments to be                         * dropped when ts_recent is old.                         */			recent_ = 0.0;		} else {			goto dropafterack;		}	}	// check for redundant data at head/tail of segment	//	note that the 4.4bsd [Net/3] code has	//	a bug here which can cause us to ignore the	//	perfectly good ACKs on duplicate segments.  The	//	fix is described in (Stevens, Vol2, p. 959-960).	//	This code is based on that correction.	//	// In addition, it has a modification so that duplicate segments	// with dup acks don't trigger a fast retransmit when dupseg_fix_	// is enabled.	//	// Yet one more modification: make sure that if the received	//	segment had datalen=0 and wasn't a SYN or FIN that	//	we don't turn on the ACKNOW status bit.  If we were to	//	allow ACKNO to be turned on, normal pure ACKs that happen	//	to have seq #s below rcv_nxt can trigger an ACK war by	//	forcing us to ACK the pure ACKs	//	todrop = rcv_nxt_ - tcph->seqno();  // how much overlap?	if (todrop > 0 && ((tiflags & (TH_SYN|TH_FIN)) || datalen > 0)) {		if (tiflags & TH_SYN) {			tiflags &= ~TH_SYN;			tcph->seqno()++;			th->size()--;	// XXX Must decrease packet size too!!			todrop--;		}		//		// see Stevens, vol 2, p. 960 for this check;		// this check is to see if we are dropping		// more than this segment (i.e. the whole pkt + a FIN),		// or just the whole packet (no FIN)		//		if (todrop > datalen ||		    (todrop == datalen && (tiflags & TH_FIN) == 0)) {                        /*                         * Any valid FIN must be to the left of the window.                         * At this point the FIN must be a duplicate or out                         * of sequence; drop it.                         */			tiflags &= ~TH_FIN;			/*			 * Send an ACK to resynchronize and drop any data.			 * But keep on processing for RST or ACK.			 */			flags_ |= TF_ACKNOW;			todrop = datalen;			dupseg = TRUE;		}		tcph->seqno() += todrop;		th->size() -= todrop;	// XXX Must decrease size too!!		datalen -= todrop;	}	/*	 * If last ACK falls within this segment's sequence numbers,	 * record the timestamp.	 * See RFC1323 (now RFC1323 bis)	 */	if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {		/*		 * this is the case where the ts value is newer than		 * the last one we've seen, and the seq # is the one we expect		 * [seqno == last_ack_sent_] or older		 */		recent_age_ = now();		recent_ = tcph->ts();	}	if (tiflags & TH_SYN) {		fprintf(stderr,		    "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d)\n",		        now(), name(), state_);		goto dropwithreset;	}	// K: added TH_SYN, but it is already known here!	if ((tiflags & TH_ACK) == 0) {		fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (seq %d)\n",			now(), name(), tcph->seqno());		goto drop;	}	/*	 * Ack processing.	 */	switch (state_) {	case TCPS_SYN_RECEIVED:	/* want ACK for our SYN+ACK */		if (ackno < highest_ack_ || ackno > maxseq_) {			// not in useful range			goto dropwithreset;		}                /*                 * Make transitions:                 *      SYN-RECEIVED  -> ESTABLISHED                 *      SYN-RECEIVED* -> FIN-WAIT-1                 */                if (flags_ & TF_NEEDFIN) {			newstate(TCPS_FIN_WAIT_1);                        flags_ &= ~TF_NEEDFIN;                } else {                        newstate(TCPS_ESTABLISHED);			if(app_)			  ((NSSocket *)app_)->upcall_passconn();                }		cwnd_ = initial_window();		/* fall into ... */        /*         * In ESTABLISHED state: drop duplicate ACKs; ACK out of range         * ACKs.  If the ack is in the range         *      tp->snd_una < ti->ti_ack <= tp->snd_max         * then advance tp->snd_una to ti->ti_ack and drop         * data from the retransmission queue.	 *	 * note that state TIME_WAIT isn't used	 * in the simulator         */        case TCPS_ESTABLISHED:        case TCPS_FIN_WAIT_1:        case TCPS_FIN_WAIT_2:	case TCPS_CLOSE_WAIT:        case TCPS_CLOSING:        case TCPS_LAST_ACK:		//		// look for ECNs in ACKs, react as necessary		//		if (fh->ecnecho() && (!ecn_ || !ect_)) {			fprintf(stderr,			    "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",				now(), name());		}                //                // generate a stream of ecnecho bits until we see a true                // cong_action bit                //                 if (ecn_) {                        if (fh->ce() && fh->ect())                                recent_ce_ = TRUE;                        else if (fh->cong_action())                                recent_ce_ = FALSE;                }		// look for dup ACKs (dup ack numbers, no data)		//		// do fast retransmit/recovery if at/past thresh		if (ackno <= highest_ack_) {			// an ACK which doesn't advance highest_ack_			if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {				--pipe_; // ACK indicates pkt cached @ receiver                                /*                                 * If we have outstanding data                                 * this is a completely                                 * duplicate ack,                                 * the ack is the biggest we've                                 * seen and we've seen exactly our rexmt                                 * threshhold of them, assume a packet                                 * has been dropped and retransmit it.                                 *                                 * We know we're losing at the current                                 * window size so do congestion avoidance.                                 *                                 * Dup acks mean that packets have left the                                 * network (they're now cached at the receiver)                                 * so bump cwnd by the amount in the receiver                                 * to keep a constant cwnd packets in the                                 * network.                                 */				if ((rtx_timer_.status() != TIMER_PENDING) ||				    ackno != highest_ack_) {					// not timed, or re-ordered ACK					dupacks_ = 0;				} else if (++dupacks_ == tcprexmtthresh_) {					fastrecov_ = TRUE;					/* re-sync the pipe_ estimate */					pipe_ = maxseq_ - highest_ack_;					pipe_ /= maxseg_;					pipe_ -= (dupacks_ + 1);					pipe_ = int(cwnd_) - dupacks_ - 1;					dupack_action(); // maybe fast rexmt					goto drop;				} else if (dupacks_ > tcprexmtthresh_) {					if (reno_fastrecov_) {						// we just measure cwnd in						// packets, so don't scale by						// maxseg_ as real						// tcp does						cwnd_++;					}					send_much(0, REASON_NORMAL, maxburst_);					goto drop;				}			} else {				// non zero-length [dataful] segment				// with a dup ack (normal for dataful segs)				// (or window changed in real TCP).				if (dupack_reset_) {					dupacks_ = 0;					fastrecov_ = FALSE;				}			}			break;	/* take us to "step6" */		} /* end of dup acks */		/*		 * we've finished the fast retransmit/recovery period		 * (i.e. received an ACK which advances highest_ack_)		 * The ACK may be "good" or "partial"		 */process_ACK:		if (ackno > maxseq_) {			// ack more than we sent(!?)			fprintf(stderr,			    "%f: FullTcpAgent::recv(%s) too-big ACK (ack: %d, maxseq:%d)\n",				now(), name(), int(ackno), int(maxseq_));			goto dropafterack;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -