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

📄 tcp_input.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * Process segments with URG.	 */	if ((tiflags & TH_URG) && ti->ti_urp &&	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {		/*		 * This is a kludge, but if we receive and accept		 * random urgent pointers, we'll crash in		 * soreceive.  It's hard to imagine someone		 * actually wanting to send this much urgent data.		 */		if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) {			ti->ti_urp = 0;			tiflags &= ~TH_URG;			goto dodata;		}		/*		 * If this segment advances the known urgent pointer,		 * then mark the data stream.  This should not happen		 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since		 * a FIN has been received from the remote side. 		 * In these states we ignore the URG.		 *		 * According to RFC961 (Assigned Protocols),		 * the urgent pointer points to the last octet		 * of urgent data.  We continue, however,		 * to consider it to indicate the first octet		 * of data past the urgent section as the original 		 * spec states (in one of two places).		 */		if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {			tp->rcv_up = ti->ti_seq + ti->ti_urp;			so->so_urgc =  so->so_rcv.sb_cc +				(tp->rcv_up - tp->rcv_nxt); /* -1; */			tp->rcv_up = ti->ti_seq + ti->ti_urp;	 		}	} else		/*		 * If no out of band data is expected,		 * pull receive urgent pointer along		 * with the receive window.		 */		if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))			tp->rcv_up = tp->rcv_nxt;dodata:	/*	 * Process the segment text, merging it into the TCP sequencing queue,	 * and arranging for acknowledgment of receipt if necessary.	 * This process logically involves adjusting tp->rcv_wnd as data	 * is presented to the user (this happens in tcp_usrreq.c,	 * case PRU_RCVD).  If a FIN has already been received on this	 * connection then we just ignore the text.	 */	if ((ti->ti_len || (tiflags&TH_FIN)) &&	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {		TCP_REASS(tp, ti, m, so, tiflags);		/*		 * Note the amount of data that peer has sent into		 * our window, in order to estimate the sender's		 * buffer size.		 */		len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);	} else {		m_free(m);		tiflags &= ~TH_FIN;	}	/*	 * If FIN is received ACK the FIN and let the user know	 * that the connection is closing.	 */	if (tiflags & TH_FIN) {		if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {			/*			 * If we receive a FIN we can't send more data,			 * set it SS_FDRAIN                         * Shutdown the socket if there is no rx data in the			 * buffer.			 * soread() is called on completion of shutdown() and			 * will got to TCPS_LAST_ACK, and use tcp_output()			 * to send the FIN.			 *//*			sofcantrcvmore(so); */			sofwdrain(so);						tp->t_flags |= TF_ACKNOW;			tp->rcv_nxt++;		}		switch (tp->t_state) {	 	/*		 * In SYN_RECEIVED and ESTABLISHED STATES		 * enter the CLOSE_WAIT state.		 */		case TCPS_SYN_RECEIVED:		case TCPS_ESTABLISHED:		  if(so->so_emu == EMU_CTL)        /* no shutdown on socket */		    tp->t_state = TCPS_LAST_ACK;		  else 		    tp->t_state = TCPS_CLOSE_WAIT;		  break;	 	/*		 * If still in FIN_WAIT_1 STATE FIN has not been acked so		 * enter the CLOSING state.		 */		case TCPS_FIN_WAIT_1:			tp->t_state = TCPS_CLOSING;			break;	 	/*		 * In FIN_WAIT_2 state enter the TIME_WAIT state,		 * starting the time-wait timer, turning off the other 		 * standard timers.		 */		case TCPS_FIN_WAIT_2:			tp->t_state = TCPS_TIME_WAIT;			tcp_canceltimers(tp);			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;			soisfdisconnected(so);			break;		/*		 * In TIME_WAIT state restart the 2 MSL time_wait timer.		 */		case TCPS_TIME_WAIT:			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;			break;		}	}	/*	 * If this is a small packet, then ACK now - with Nagel	 *      congestion avoidance sender won't send more until	 *      he gets an ACK.	 * 	 * See above.	 *//*	if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { *//*	if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && *		(so->so_iptos & IPTOS_LOWDELAY) == 0) || *	       ((so->so_iptos & IPTOS_LOWDELAY) && *	       ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { */	if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&	    ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {		tp->t_flags |= TF_ACKNOW;	}	/*	 * Return any desired output.	 */	if (needoutput || (tp->t_flags & TF_ACKNOW)) {		(void) tcp_output(tp);	}	return;dropafterack:	/*	 * Generate an ACK dropping incoming segment if it occupies	 * sequence space, where the ACK reflects our state.	 */	if (tiflags & TH_RST)		goto drop;	m_freem(m);	tp->t_flags |= TF_ACKNOW;	(void) tcp_output(tp);	return;dropwithreset:	/* reuses m if m!=NULL, m_free() unnecessary */	if (tiflags & TH_ACK)		tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);	else {		if (tiflags & TH_SYN) ti->ti_len++;		tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,		    TH_RST|TH_ACK);	}	return;drop:	/*	 * Drop space held by incoming segment and return.	 */	m_free(m);	return;} /* , ts_present, ts_val, ts_ecr) *//*	int *ts_present; *	u_int32_t *ts_val, *ts_ecr; */voidtcp_dooptions(tp, cp, cnt, ti)	struct tcpcb *tp;	u_char *cp;	int cnt;	struct tcpiphdr *ti;{	u_int16_t mss;	int opt, optlen;	DEBUG_CALL("tcp_dooptions");	DEBUG_ARGS((dfd," tp = %lx  cnt=%i \n", (long )tp, cnt));	for (; cnt > 0; cnt -= optlen, cp += optlen) {		opt = cp[0];		if (opt == TCPOPT_EOL)			break;		if (opt == TCPOPT_NOP)			optlen = 1;		else {			optlen = cp[1];			if (optlen <= 0)				break;		}		switch (opt) {		default:			continue;		case TCPOPT_MAXSEG:			if (optlen != TCPOLEN_MAXSEG)				continue;			if (!(ti->ti_flags & TH_SYN))				continue;			memcpy((char *) &mss, (char *) cp + 2, sizeof(mss));			NTOHS(mss);			(void) tcp_mss(tp, mss);	/* sets t_maxseg */			break;/*		case TCPOPT_WINDOW: *			if (optlen != TCPOLEN_WINDOW) *				continue; *			if (!(ti->ti_flags & TH_SYN)) *				continue; *			tp->t_flags |= TF_RCVD_SCALE; *			tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); *			break; *//*		case TCPOPT_TIMESTAMP: *			if (optlen != TCPOLEN_TIMESTAMP) *				continue; *			*ts_present = 1; *			memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); *			NTOHL(*ts_val); *			memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); *			NTOHL(*ts_ecr); * */			/*  *			 * A timestamp received in a SYN makes *			 * it ok to send timestamp requests and replies. *			 *//*			if (ti->ti_flags & TH_SYN) { *				tp->t_flags |= TF_RCVD_TSTMP; *				tp->ts_recent = *ts_val; *				tp->ts_recent_age = tcp_now; *			} */			break;		}	}}/* * Pull out of band byte out of a segment so * it doesn't appear in the user's data queue. * It is still reflected in the segment length for * sequencing purposes. */#ifdef notdefvoidtcp_pulloutofband(so, ti, m)	struct socket *so;	struct tcpiphdr *ti;	register struct mbuf *m;{	int cnt = ti->ti_urp - 1;		while (cnt >= 0) {		if (m->m_len > cnt) {			char *cp = mtod(m, caddr_t) + cnt;			struct tcpcb *tp = sototcpcb(so);			tp->t_iobc = *cp;			tp->t_oobflags |= TCPOOB_HAVEDATA;			memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1));			m->m_len--;			return;		}		cnt -= m->m_len;		m = m->m_next; /* XXX WRONG! Fix it! */		if (m == 0)			break;	}	panic("tcp_pulloutofband");}#endif /* notdef *//* * Collect new round-trip time estimate * and update averages and current timeout. */voidtcp_xmit_timer(tp, rtt)	register struct tcpcb *tp;	int rtt;{	register short delta;	DEBUG_CALL("tcp_xmit_timer");	DEBUG_ARG("tp = %lx", (long)tp);	DEBUG_ARG("rtt = %d", rtt);		tcpstat.tcps_rttupdated++;	if (tp->t_srtt != 0) {		/*		 * srtt is stored as fixed point with 3 bits after the		 * binary point (i.e., scaled by 8).  The following magic		 * is equivalent to the smoothing algorithm in rfc793 with		 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed		 * point).  Adjust rtt to origin 0.		 */		delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT);		if ((tp->t_srtt += delta) <= 0)			tp->t_srtt = 1;		/*		 * We accumulate a smoothed rtt variance (actually, a		 * smoothed mean difference), then set the retransmit		 * timer to smoothed rtt + 4 times the smoothed variance.		 * rttvar is stored as fixed point with 2 bits after the		 * binary point (scaled by 4).  The following is		 * equivalent to rfc793 smoothing with an alpha of .75		 * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces		 * rfc793's wired-in beta.		 */		if (delta < 0)			delta = -delta;		delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT);		if ((tp->t_rttvar += delta) <= 0)			tp->t_rttvar = 1;	} else {		/* 		 * No rtt measurement yet - use the unsmoothed rtt.		 * Set the variance to half the rtt (so our first		 * retransmit happens at 3*rtt).		 */		tp->t_srtt = rtt << TCP_RTT_SHIFT;		tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);	}	tp->t_rtt = 0;	tp->t_rxtshift = 0;	/*	 * the retransmit should happen at rtt + 4 * rttvar.	 * Because of the way we do the smoothing, srtt and rttvar	 * will each average +1/2 tick of bias.  When we compute	 * the retransmit timer, we want 1/2 tick of rounding and	 * 1 extra tick because of +-1/2 tick uncertainty in the	 * firing of the timer.  The bias will give us exactly the	 * 1.5 tick we need.  But, because the bias is	 * statistical, we have to test that we don't drop below	 * the minimum feasible timer (which is 2 ticks).	 */	TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),	    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */		/*	 * We received an ack for a packet that wasn't retransmitted;	 * it is probably safe to discard any error indications we've	 * received recently.  This isn't quite right, but close enough	 * for now (a route might have failed after we sent a segment,	 * and the return path might not be symmetrical).	 */	tp->t_softerror = 0;}/* * Determine a reasonable value for maxseg size. * If the route is known, check route for mtu. * If none, use an mss that can be handled on the outgoing * interface without forcing IP to fragment; if bigger than * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES * to utilize large mbufs.  If no route is found, route has no mtu, * or the destination isn't local, use a default, hopefully conservative * size (usually 512 or the default IP max size, but no more than the mtu * of the interface), as we can't discover anything about intervening * gateways or networks.  We also initialize the congestion/slow start * window to be a single segment if the destination isn't local. * While looking at the routing entry, we also initialize other path-dependent * parameters from pre-set or cached values in the routing entry. */inttcp_mss(tp, offer)        register struct tcpcb *tp;        u_int offer;{	struct socket *so = tp->t_socket;	int mss;		DEBUG_CALL("tcp_mss");	DEBUG_ARG("tp = %lx", (long)tp);	DEBUG_ARG("offer = %d", offer);		mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);	if (offer)		mss = min(mss, offer);	mss = max(mss, 32);	if (mss < tp->t_maxseg || offer != 0)	   tp->t_maxseg = mss;		tp->snd_cwnd = mss;		sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));	sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));		DEBUG_MISC((dfd, " returning mss = %d\n", mss));		return mss;}

⌨️ 快捷键说明

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