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

📄 tcp_input.pc

📁 无线自组织网络的一个协议仿真软件
💻 PC
📖 第 1 页 / 共 4 页
字号:
        tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;    /*     * Process options if not in LISTEN state,     * else do it below (after getting remote address).     */    if (tp->t_state != TCPS_LISTEN){        tcp_dooptions(tp, optp, optlen, ti, &topt, tcp_now, tcp_stat);        datap = optp;    }               /*     * Header prediction: check for the two common cases     * of a uni-directional data xfer.  If the packet has     * no control flags, is in-sequence, the window didn't     * change and we're not retransmitting, it's a     * candidate.  If the length is zero and the ack moved     * forward, we're the sender side of the xfer.  Just     * free the data acked & wake any higher level process     * that was blocked waiting for space.  If the length     * is non-zero and the ack didn't move, we're the     * receiver side.  If we're getting packets in-order     * (the reassembly queue is empty), add the data to     * the socket buffer and note that we need a delayed ack.     * Make sure that the hidden state-flags are also off.     * Since we check for TCPS_ESTABLISHED above, it can only     * be TH_NEEDSYN.     */    if (tp->t_state == TCPS_ESTABLISHED &&        (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) == TH_ACK &&        ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&        ((topt.to_flag & TOF_TS) == 0 ||         TSTMP_GEQ(topt.to_tsval, tp->ts_recent)) &&        ti->ti_seq == tp->rcv_nxt &&        tiwin && tiwin == tp->snd_wnd &&        tp->snd_nxt == tp->snd_max) {        /*         * If last ACK falls within this segment's sequence numbers,         * record the timestamp.         * NOTE that the test is modified according to the latest         * proposal of the tcplw@cray.com list (Braden 1993/04/26).         */        if ((topt.to_flag & TOF_TS) != 0 &&           SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {            tp->ts_recent_age = tcp_now;            tp->ts_recent = topt.to_tsval;        }        if (ti->ti_len == 0) {            if (SEQ_GT(ti->ti_ack, tp->snd_una) &&                SEQ_LEQ(ti->ti_ack, tp->snd_max) &&                tp->snd_cwnd >= tp->snd_wnd &&                tp->t_dupacks < tcprexmtthresh) {                /*                 * this is a pure ack for outstanding data.                 */                if (tcp_stat)                    ++tcp_stat->tcps_predack;                if ((topt.to_flag & TOF_TS) != 0)                    tcp_xmit_timer(tp, tcp_now - topt.to_tsecr + 1, tcp_stat);                else if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))                    tcp_xmit_timer(tp, tp->t_rtt, tcp_stat);                            acked = ti->ti_ack - tp->snd_una;                if (tcp_stat) {                    tcp_stat->tcps_rcvackpack++;                    tcp_stat->tcps_rcvackbyte += acked;                }                del_buf(node, inp, acked);                tp->snd_una = ti->ti_ack;                /*                 * If all outstanding data are acked, stop                 * retransmit timer, otherwise restart timer                 * using current (possibly backed-off) value.                 * If process is waiting for space,                 * wakeup/selwakeup/signal.  If data                 * are ready to send, let tcp_output                 * decide between more output or persist.                 */                if (tp->snd_una == tp->snd_max)                    tp->t_timer[TCPT_REXMT] = 0;                else if (tp->t_timer[TCPT_PERSIST] == 0)                    tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;                if (inp->inp_snd.cc)                    tcp_output(node, tp, tcp_now, tcp_stat);                pc_free(tcp_seg);                return;            }        } else if (ti->ti_ack == tp->snd_una &&            tp->seg_next == (struct tcpiphdr *)tp &&            ti->ti_len <= sbspace(inp)) {            /*             * this is a pure, in-sequence data packet             * with nothing on the reassembly queue and             * we have enough buffer space to take it.             */            tp->rcv_nxt += ti->ti_len;            if (tcp_stat)                ++tcp_stat->tcps_preddat;            /*             * submit data to application.             */            submit_data(node, inp->app_proto_type, inp->con_id,                         datap, ti->ti_len, tp);            if (TCP_ACK_HACK) {                /*                 * If this is a short packet, then ACK now - with Nagel                 *  congestion avoidance sender won't send more until                 *  he gets an ACK.                 */                if (tiflags & TH_PUSH) {                    tp->t_flags |= TF_ACKNOW;                    tcp_output(node, tp, tcp_now, tcp_stat);                } else {                    tp->t_flags |= TF_DELACK;                }            } else {                tp->t_flags |= TF_DELACK;            }            pc_free(tcp_seg);            return;        }    }    /*     * Calculate amount of space in receive window,     * and then do TCP input processing.     * Receive window is amount of space in rcv queue,     * but not less than advertised window.     */    {        int win;        win = sbspace(inp);        if (win < 0)            win = 0;        tp->rcv_wnd = MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt));    }    switch (tp->t_state) {    /*     * If the state is LISTEN then ignore segment if it contains an RST.     * If the segment contains an ACK then it is bad and send a RST.     * If it does not contain a SYN then it is not interesting; drop it.     * Don't bother responding if the destination was a broadcast.     * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial     * tp->iss, and send a segment:     *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>     * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.     * Fill in remote peer address fields if not previously specified.     * Enter SYN_RECEIVED state, and process any other fields of this     * segment in this state.     */    case TCPS_LISTEN:         if (tiflags & TH_RST)            goto drop;        if (tiflags & TH_ACK)            goto dropwithreset;        if ((tiflags & TH_SYN) == 0)            goto drop;        tp->t_template = (struct tcpiphdr *) tcp_template(tp);        if (tp->t_template == 0) {            tp = (struct tcpcb *)tcp_drop(node, tp, tcp_now, tcp_stat);            goto drop;        }        tcp_dooptions(tp, optp, optlen, ti, &topt, tcp_now, tcp_stat);        datap = optp;        if (iss)            tp->iss = iss;        else            tp->iss = *tcp_iss;        *tcp_iss += TCP_ISSINCR/4;        tp->irs = ti->ti_seq;        tcp_sendseqinit(tp);        tcp_rcvseqinit(tp);        /*         * Initialization of the tcpcb for transaction;         *   set SND.WND = SEG.WND,         */        tp->snd_wnd = tiwin;    /* initial send-window */        /*         *    do a standard 3-way handshake.         */        tp->t_flags |= TF_ACKNOW;        tp->t_state = TCPS_SYN_RECEIVED;        tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;        if (tcp_stat)            tcp_stat->tcps_accepts++;        goto trimthenstep6;            /*     * If the state is SYN_RECEIVED:     *  do just the ack and RST checks from SYN_SENT state.     * If the state is SYN_SENT:     *  if seg contains an ACK, but not for our SYN, drop the input.     *  if seg contains a RST, then drop the connection.     *  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_RECEIVED:    case TCPS_SYN_SENT:        if ((tiflags & TH_ACK) &&             (SEQ_LEQ(ti->ti_ack, tp->iss) ||             SEQ_GT(ti->ti_ack, tp->snd_max)))            goto dropwithreset;        if (tiflags & TH_RST) {            if (tiflags & TH_ACK)                tp = tcp_drop(node, tp, tcp_now, tcp_stat);            goto drop;        }        if (tp->t_state == TCPS_SYN_RECEIVED)            break;        if ((tiflags & TH_SYN) == 0)            goto drop;        tp->snd_wnd = ti->ti_win;   /* initial send window */        tp->irs = ti->ti_seq;        tcp_rcvseqinit(tp);        if (tiflags & TH_ACK) {            if (tcp_stat)                tcp_stat->tcps_connects++;            /* Do window scaling on this connection? */            if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==                (TF_RCVD_SCALE|TF_REQ_SCALE)) {                tp->snd_scale = tp->requested_s_scale;                tp->rcv_scale = tp->request_r_scale;            }            tp->rcv_adv += tp->rcv_wnd;            tp->snd_una++;      /* SYN is acked */            /*             * If there's data, delay ACK; if there's also a FIN             * ACKNOW will be turned on later.             */            if (ti->ti_len != 0)                tp->t_flags |= TF_DELACK;            else                tp->t_flags |= TF_ACKNOW;            /*             * Received <SYN,ACK> in SYN_SENT[*] state.             * Transitions:             *  SYN_SENT  --> ESTABLISHED             *  SYN_SENT* --> FIN_WAIT_1             */            if (tp->t_flags & TF_NEEDFIN) {                tp->t_state = TCPS_FIN_WAIT_1;                tp->t_flags &= ~TF_NEEDFIN;                tiflags &= ~TH_SYN;            } else {                Message *msg;                TransportToAppOpenResult *tcpOpenResult;                if (inp->usrreq == INPCB_USRREQ_OPEN)                    flag = TCP_CONN_ACTIVE_OPEN;                 else flag = TCP_CONN_PASSIVE_OPEN;                   msg = GLOMO_MsgAlloc(node, GLOMO_APP_LAYER,                                     inp->app_proto_type,                                      MSG_APP_FromTransOpenResult);                GLOMO_MsgInfoAlloc(node, msg, sizeof(TransportToAppOpenResult));                tcpOpenResult = (TransportToAppOpenResult *) msg->info;                tcpOpenResult->type = flag;                tcpOpenResult->localAddr = inp->inp_local_addr;                tcpOpenResult->localPort = inp->inp_local_port;                tcpOpenResult->remoteAddr = inp->inp_remote_addr;                tcpOpenResult->remotePort = inp->inp_remote_port;                tcpOpenResult->connectionId = inp->con_id;                tcpOpenResult->uniqueId = inp->unique_id;                GLOMO_MsgSend(node, msg, TRANSPORT_DELAY);                inp->usrreq = INPCB_USRREQ_CONNECTED;                tp->t_state = TCPS_ESTABLISHED;                tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;            }        } else {            /*             *  Received initial SYN in SYN-SENT[*] state => simul-             *  taneous open.               */            tp->t_flags |= TF_ACKNOW;            tp->t_timer[TCPT_REXMT] = 0;            tp->t_state = TCPS_SYN_RECEIVED;        }trimthenstep6:        /*         * Advance ti->ti_seq to correspond to first data byte.         * If data, trim to stay within window,         * dropping FIN if necessary.         */        ti->ti_seq++;        if (ti->ti_len > tp->rcv_wnd) {            todrop = ti->ti_len - tp->rcv_wnd;            ti->ti_len = tp->rcv_wnd;            tiflags &= ~TH_FIN;            if (tcp_stat) {                tcp_stat->tcps_rcvpackafterwin++;                tcp_stat->tcps_rcvbyteafterwin += todrop;            }        }        tp->snd_wl1 = ti->ti_seq - 1;        tp->rcv_up = ti->ti_seq;        if (tiflags & TH_ACK)            goto process_ACK;        goto step6;    case TCPS_LAST_ACK:    case TCPS_CLOSING:    case TCPS_TIME_WAIT:        break;  /* continue normal processing */    }    /*     * States other than LISTEN or SYN_SENT.     * First check timestamp, if present.     * Then check the connection count, 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 ((topt.to_flag & TOF_TS) != 0 && (tiflags & TH_RST) == 0 &&        tp->ts_recent && TSTMP_LT(topt.to_tsval, tp->ts_recent)) {        /* Check to see if ts_recent is over 24 days old.  */        if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {            /*             * 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.             */            tp->ts_recent = 0;        } else {            if (tcp_stat) {                tcp_stat->tcps_rcvduppack++;                tcp_stat->tcps_rcvdupbyte += ti->ti_len;                tcp_stat->tcps_pawsdrop++;            }            goto dropafterack;        }    }    todrop = tp->rcv_nxt - ti->ti_seq;    if (todrop > 0) {        if (tiflags & TH_SYN) {            tiflags &= ~TH_SYN;            ti->ti_seq++;            if (ti->ti_urp > 1)                ti->ti_urp --;            else                tiflags &= ~TH_URG;            todrop--;        }        /*         * Following if statement from Stevens, vol. 2, p. 960.         */        if (todrop > ti->ti_len            || (todrop == ti->ti_len && (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.             */            tp->t_flags |= TF_ACKNOW;            todrop = ti->ti_len;            if (tcp_stat) {                tcp_stat->tcps_rcvduppack++;                tcp_stat->tcps_rcvdupbyte += todrop;            }        } else {            if (tcp_stat) {                tcp_stat->tcps_rcvpartduppack++;                tcp_stat->tcps_rcvpartdupbyte += todrop;            }        }        data_adj(ti, todrop);        ti->ti_seq += todrop;        ti->ti_len -= todrop;        if (ti->ti_urp > todrop)            ti->ti_urp -= todrop;        else {            tiflags &= ~TH_URG;            ti->ti_urp = 0;        }    }    /*     * If new data are received on a connection after the     * user processes are gone, then RST the other end.     */        if (tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {        tp = tcp_close(node, tp, tcp_stat);        if (tcp_stat)            tcp_stat->tcps_rcvafterclose++;        goto dropwithreset;    }    /*     * If segment ends after window, drop trailing data     * (and PUSH and FIN); if nothing left, just ACK.     */    todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);    if (todrop > 0) {        if (tcp_stat)             tcp_stat->tcps_rcvpackafterwin++;        if (todrop >= ti->ti_len) {

⌨️ 快捷键说明

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