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

📄 tcp_in.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 4 页
字号:
        tcp_debug_print_state(pcb->state);#endif /* TCP_DEBUG */#endif /* TCP_INPUT_DEBUG */      }    }    /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).       Below this line, 'pcb' may not be dereferenced! */aborted:    tcp_input_pcb = NULL;    recv_data = NULL;    /* give up our reference to inseg.p */    if (inseg.p != NULL)    {      pbuf_free(inseg.p);      inseg.p = NULL;    }  } else {    /* If no matching PCB was found, send a TCP RST (reset) to the       sender. */    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));    if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {      TCP_STATS_INC(tcp.proterr);      TCP_STATS_INC(tcp.drop);      tcp_rst(ackno, seqno + tcplen,        ip_current_dest_addr(), ip_current_src_addr(),        tcphdr->dest, tcphdr->src);    }    pbuf_free(p);  }  LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());  PERF_STOP("tcp_input");}/** * Called by tcp_input() when a segment arrives for a listening * connection (from tcp_input()). * * @param pcb the tcp_pcb_listen for which a segment arrived * @return ERR_OK if the segment was processed *         another err_t on error * * @note the return value is not (yet?) used in tcp_input() * @note the segment which arrived is saved in global variables, therefore only the pcb *       involved is passed as a parameter to this function */static err_ttcp_listen_input(struct tcp_pcb_listen *pcb){  struct tcp_pcb *npcb;  err_t rc;  /* In the LISTEN state, we check for incoming SYN segments,     creates a new PCB, and responds with a SYN|ACK. */  if (flags & TCP_ACK) {    /* For incoming segments with the ACK flag set, respond with a       RST. */    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));    tcp_rst(ackno + 1, seqno + tcplen,      ip_current_dest_addr(), ip_current_src_addr(),      tcphdr->dest, tcphdr->src);  } else if (flags & TCP_SYN) {    LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));#if TCP_LISTEN_BACKLOG    if (pcb->accepts_pending >= pcb->backlog) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));      return ERR_ABRT;    }#endif /* TCP_LISTEN_BACKLOG */    npcb = tcp_alloc(pcb->prio);    /* If a new PCB could not be created (probably due to lack of memory),       we don't do anything, but rely on the sender will retransmit the       SYN at a time when we have more memory available. */    if (npcb == NULL) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));      TCP_STATS_INC(tcp.memerr);      return ERR_MEM;    }#if TCP_LISTEN_BACKLOG    pcb->accepts_pending++;#endif /* TCP_LISTEN_BACKLOG */    /* Set up the new PCB. */    ip_addr_copy(npcb->local_ip, current_iphdr_dest);    npcb->local_port = pcb->local_port;    ip_addr_copy(npcb->remote_ip, current_iphdr_src);    npcb->remote_port = tcphdr->src;    npcb->state = SYN_RCVD;    npcb->rcv_nxt = seqno + 1;    npcb->rcv_ann_right_edge = npcb->rcv_nxt;    npcb->snd_wnd = tcphdr->wnd;    npcb->ssthresh = npcb->snd_wnd;    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */    npcb->callback_arg = pcb->callback_arg;#if LWIP_CALLBACK_API    npcb->accept = pcb->accept;#endif /* LWIP_CALLBACK_API */    /* inherit socket options */    npcb->so_options = pcb->so_options & SOF_INHERITED;    /* Register the new PCB so that we can begin receiving segments       for it. */    TCP_REG(&tcp_active_pcbs, npcb);    /* Parse any options in the SYN. */    tcp_parseopt(npcb);#if TCP_CALCULATE_EFF_SEND_MSS    npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));#endif /* TCP_CALCULATE_EFF_SEND_MSS */    snmp_inc_tcppassiveopens();    /* Send a SYN|ACK together with the MSS option. */    rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);    if (rc != ERR_OK) {      tcp_abandon(npcb, 0);      return rc;    }    return tcp_output(npcb);  }  return ERR_OK;}/** * Called by tcp_input() when a segment arrives for a connection in * TIME_WAIT. * * @param pcb the tcp_pcb for which a segment arrived * * @note the segment which arrived is saved in global variables, therefore only the pcb *       involved is passed as a parameter to this function */static err_ttcp_timewait_input(struct tcp_pcb *pcb){  /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */  /* RFC 793 3.9 Event Processing - Segment Arrives:   * - first check sequence number - we skip that one in TIME_WAIT (always   *   acceptable since we only send ACKs)   * - second check the RST bit (... return) */  if (flags & TCP_RST)  {    return ERR_OK;  }  /* - fourth, check the SYN bit, */  if (flags & TCP_SYN) {    /* If an incoming segment is not acceptable, an acknowledgment       should be sent in reply */    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {      /* If the SYN is in the window it is an error, send a reset */      tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),        tcphdr->dest, tcphdr->src);      return ERR_OK;    }  } else if (flags & TCP_FIN) {    /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.         Restart the 2 MSL time-wait timeout.*/    pcb->tmr = tcp_ticks;  }  if ((tcplen > 0))  {    /* Acknowledge data, FIN or out-of-window SYN */    pcb->flags |= TF_ACK_NOW;    return tcp_output(pcb);  }  return ERR_OK;}/** * Implements the TCP state machine. Called by tcp_input. In some * states tcp_receive() is called to receive data. The tcp_seg * argument will be freed by the caller (tcp_input()) unless the * recv_data pointer in the pcb is set. * * @param pcb the tcp_pcb for which a segment arrived * * @note the segment which arrived is saved in global variables, therefore only the pcb *       involved is passed as a parameter to this function */static err_ttcp_process(struct tcp_pcb *pcb){  struct tcp_seg *rseg;  u8_t acceptable = 0;  err_t err;  err = ERR_OK;  /* Process incoming RST segments. */  if (flags & TCP_RST) {    /* First, determine if the reset is acceptable. */    if (pcb->state == SYN_SENT) {      if (ackno == pcb->snd_nxt) {        acceptable = 1;      }    } else {      if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,                           pcb->rcv_nxt+pcb->rcv_wnd)) {        acceptable = 1;      }    }    if (acceptable) {      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));      LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);      recv_flags |= TF_RESET;      pcb->flags &= ~TF_ACK_DELAY;      return ERR_RST;    } else {      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",       seqno, pcb->rcv_nxt));      LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",       seqno, pcb->rcv_nxt));      return ERR_OK;    }  }  if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {     /* Cope with new connection attempt after remote end crashed */    tcp_ack_now(pcb);    return ERR_OK;  }    if ((pcb->flags & TF_RXCLOSED) == 0) {    /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */    pcb->tmr = tcp_ticks;  }  pcb->keep_cnt_sent = 0;  tcp_parseopt(pcb);  /* Do different things depending on the TCP state. */  switch (pcb->state) {  case SYN_SENT:    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,     pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));    /* received SYN ACK with expected sequence number? */    if ((flags & TCP_ACK) && (flags & TCP_SYN)        && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {      pcb->snd_buf++;      pcb->rcv_nxt = seqno + 1;      pcb->rcv_ann_right_edge = pcb->rcv_nxt;      pcb->lastack = ackno;      pcb->snd_wnd = tcphdr->wnd;      pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */      pcb->state = ESTABLISHED;#if TCP_CALCULATE_EFF_SEND_MSS      pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));#endif /* TCP_CALCULATE_EFF_SEND_MSS */      /* Set ssthresh again after changing pcb->mss (already set in tcp_connect       * but for the default value of pcb->mss) */      pcb->ssthresh = pcb->mss * 10;      pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);      LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));      --pcb->snd_queuelen;      LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));      rseg = pcb->unacked;      pcb->unacked = rseg->next;      /* If there's nothing left to acknowledge, stop the retransmit         timer, otherwise reset it to start again */      if(pcb->unacked == NULL)        pcb->rtime = -1;      else {        pcb->rtime = 0;        pcb->nrtx = 0;      }      tcp_seg_free(rseg);      /* Call the user specified function to call when sucessfully       * connected. */      TCP_EVENT_CONNECTED(pcb, ERR_OK, err);      if (err == ERR_ABRT) {        return ERR_ABRT;      }      tcp_ack_now(pcb);    }    /* received ACK? possibly a half-open connection */    else if (flags & TCP_ACK) {      /* send a RST to bring the other side in a non-synchronized state. */      tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),        tcphdr->dest, tcphdr->src);    }    break;  case SYN_RCVD:    if (flags & TCP_ACK) {      /* expected ACK number? */      if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {        u16_t old_cwnd;        pcb->state = ESTABLISHED;        LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));#if LWIP_CALLBACK_API        LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);#endif        /* Call the accept function. */        TCP_EVENT_ACCEPT(pcb, ERR_OK, err);        if (err != ERR_OK) {          /* If the accept function returns with an error, we abort           * the connection. */          /* Already aborted? */          if (err != ERR_ABRT) {            tcp_abort(pcb);          }          return ERR_ABRT;        }        old_cwnd = pcb->cwnd;        /* If there was any data contained within this ACK,         * we'd better pass it on to the application as well. */        tcp_receive(pcb);        /* Prevent ACK for SYN to generate a sent event */        if (pcb->acked != 0) {          pcb->acked--;        }        pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);        if (recv_flags & TF_GOT_FIN) {          tcp_ack_now(pcb);          pcb->state = CLOSE_WAIT;        }      } else {        /* incorrect ACK number, send RST */        tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),                tcphdr->dest, tcphdr->src);      }    } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {      /* Looks like another copy of the SYN - retransmit our SYN-ACK */      tcp_rexmit(pcb);    }    break;  case CLOSE_WAIT:    /* FALLTHROUGH */  case ESTABLISHED:    tcp_receive(pcb);    if (recv_flags & TF_GOT_FIN) { /* passive close */      tcp_ack_now(pcb);      pcb->state = CLOSE_WAIT;    }    break;  case FIN_WAIT_1:    tcp_receive(pcb);    if (recv_flags & TF_GOT_FIN) {      if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {        LWIP_DEBUGF(TCP_DEBUG,          ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));        tcp_ack_now(pcb);        tcp_pcb_purge(pcb);        TCP_RMV(&tcp_active_pcbs, pcb);        pcb->state = TIME_WAIT;        TCP_REG(&tcp_tw_pcbs, pcb);      } else {        tcp_ack_now(pcb);        pcb->state = CLOSING;      }    } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {      pcb->state = FIN_WAIT_2;    }    break;  case FIN_WAIT_2:    tcp_receive(pcb);    if (recv_flags & TF_GOT_FIN) {      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));      tcp_ack_now(pcb);      tcp_pcb_purge(pcb);      TCP_RMV(&tcp_active_pcbs, pcb);      pcb->state = TIME_WAIT;      TCP_REG(&tcp_tw_pcbs, pcb);    }    break;  case CLOSING:    tcp_receive(pcb);    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));      tcp_pcb_purge(pcb);      TCP_RMV(&tcp_active_pcbs, pcb);      pcb->state = TIME_WAIT;      TCP_REG(&tcp_tw_pcbs, pcb);    }    break;  case LAST_ACK:    tcp_receive(pcb);    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));      /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */      recv_flags |= TF_CLOSED;    }    break;  default:

⌨️ 快捷键说明

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