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

📄 uip-tcpinput.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* Do different things depending on in what state the connection is. */  switch (conn->tcpstateflags & UIP_TS_MASK)    {      /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not       * implemented, since we force the application to close when the       * peer sends a FIN (hence the application goes directly from       * ESTABLISHED to LAST_ACK).       */      case UIP_SYN_RCVD:        /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and         * we are waiting for an ACK that acknowledges the data we sent         * out the last time. Therefore, we want to have the UIP_ACKDATA         * flag set. If so, we enter the ESTABLISHED state.         */        if (flags & UIP_ACKDATA)          {            conn->tcpstateflags = UIP_ESTABLISHED;            conn->len           = 0;            nvdbg("TCP state: UIP_ESTABLISHED\n");            flags               = UIP_CONNECTED;            if (dev->d_len > 0)              {                flags          |= UIP_NEWDATA;                uip_incr32(conn->rcv_nxt, dev->d_len);              }            dev->d_sndlen       = 0;            result              = uip_tcpcallback(dev, conn, flags);            uip_tcpappsend(dev, conn, result);            return;          }        goto drop;      case UIP_SYN_SENT:        /* In SYN_SENT, we wait for a SYNACK that is sent in response to         * our SYN. The rcv_nxt is set to sequence number in the SYNACK         * plus one, and we send an ACK. We move into the ESTABLISHED         * state.         */        if ((flags & UIP_ACKDATA) && (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))          {            /* Parse the TCP MSS option, if present. */            if ((BUF->tcpoffset & 0xf0) > 0x50)              {                for (i = 0; i < ((BUF->tcpoffset >> 4) - 5) << 2 ;)                  {                    opt = dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + i];                    if (opt == TCP_OPT_END)                      {                        /* End of options. */                        break;                      }                    else if (opt == TCP_OPT_NOOP)                      {                        /* NOP option. */                        ++i;                      }                    else if (opt == TCP_OPT_MSS &&                              dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == TCP_OPT_MSS_LEN)                      {                        /* An MSS option with the right option length. */                        tmp16 =                          (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + i] << 8) |                          dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + i];                        conn->initialmss =                          conn->mss =                          tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;                        /* And we are done processing options. */                        break;                      }                    else                      {                        /* All other options have a length field, so that we                         * easily can skip past them.                         */                        if (dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i] == 0)                          {                            /* If the length field is zero, the options are                             * malformed and we don't process them further.                             */                            break;                          }                        i += dev->d_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + i];                      }                  }              }            conn->tcpstateflags = UIP_ESTABLISHED;            memcpy(conn->rcv_nxt, BUF->seqno, 4);            nvdbg("TCP state: UIP_ESTABLISHED\n");            uip_incr32(conn->rcv_nxt, 1);            conn->len           = 0;            dev->d_len          = 0;            dev->d_sndlen       = 0;            result = uip_tcpcallback(dev, conn, UIP_CONNECTED | UIP_NEWDATA);            uip_tcpappsend(dev, conn, result);            return;          }        /* Inform the application that the connection failed */        (void)uip_tcpcallback(dev, conn, UIP_ABORT);        /* The connection is closed after we send the RST */        conn->tcpstateflags = UIP_CLOSED;        nvdbg("Connection failed - TCP state: UIP_CLOSED\n");        /* We do not send resets in response to resets. */        if (BUF->flags & TCP_RST)          {            goto drop;          }        uip_tcpreset(dev);        return;      case UIP_ESTABLISHED:        /* In the ESTABLISHED state, we call upon the application to feed         * data into the d_buf. If the UIP_ACKDATA flag is set, the         * application should put new data into the buffer, otherwise we are         * retransmitting an old segment, and the application should put that         * data into the buffer.         *         * If the incoming packet is a FIN, we should close the connection on         * this side as well, and we send out a FIN and enter the LAST_ACK         * state. We require that there is no outstanding data; otherwise the         * sequence numbers will be screwed up.         */        if (BUF->flags & TCP_FIN && !(conn->tcpstateflags & UIP_STOPPED))          {            if (uip_outstanding(conn))              {                goto drop;              }            uip_incr32(conn->rcv_nxt, dev->d_len + 1);            flags |= UIP_CLOSE;            if (dev->d_len > 0)              {                flags |= UIP_NEWDATA;              }            (void)uip_tcpcallback(dev, conn, flags);            conn->tcpstateflags = UIP_LAST_ACK;            conn->len           = 1;            conn->nrtx          = 0;            nvdbg("TCP state: UIP_LAST_ACK\n");            uip_tcpsend(dev, conn, TCP_FIN | TCP_ACK, UIP_IPTCPH_LEN);            return;          }        /* Check the URG flag. If this is set, the segment carries urgent         * data that we must pass to the application.         */        if ((BUF->flags & TCP_URG) != 0)          {#ifdef CONFIG_NET_TCPURGDATA            dev->d_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];            if (dev->d_urglen > dev->d_len)              {                /* There is more urgent data in the next segment to come. */                dev->d_urglen = dev->d_len;              }            uip_incr32(conn->rcv_nxt, dev->d_urglen);            dev->d_len     -= dev->d_urglen;            dev->d_urgdata  = dev->d_appdata;            dev->d_appdata += dev->d_urglen;          }        else          {            dev->d_urglen   = 0;#else /* CONFIG_NET_TCPURGDATA */            dev->d_appdata =              ((uint8*)dev->d_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);            dev->d_len    -=              (BUF->urgp[0] << 8) | BUF->urgp[1];#endif /* CONFIG_NET_TCPURGDATA */          }        /* If d_len > 0 we have TCP data in the packet, and we flag this         * by setting the UIP_NEWDATA flag and update the sequence number         * we acknowledge. If the application has stopped the dataflow         * using uip_stop(), we must not accept any data packets from the         * remote host.         */        if (dev->d_len > 0 && !(conn->tcpstateflags & UIP_STOPPED))          {            flags |= UIP_NEWDATA;            uip_incr32(conn->rcv_nxt, dev->d_len);          }        /* Check if the available buffer space advertised by the other end         * is smaller than the initial MSS for this connection. If so, we         * set the current MSS to the window size to ensure that the         * application does not send more data than the other end can         * handle.         *         * If the remote host advertises a zero window, we set the MSS to         * the initial MSS so that the application will send an entire MSS         * of data. This data will not be acknowledged by the receiver,         * and the application will retransmit it. This is called the         * "persistent timer" and uses the retransmission mechanim.         */        tmp16 = ((uint16)BUF->wnd[0] << 8) + (uint16)BUF->wnd[1];        if (tmp16 > conn->initialmss || tmp16 == 0)          {            tmp16 = conn->initialmss;          }        conn->mss = tmp16;        /* If this packet constitutes an ACK for outstanding data (flagged         * by the UIP_ACKDATA flag, we should call the application since it         * might want to send more data. If the incoming packet had data         * from the peer (as flagged by the UIP_NEWDATA flag), the         * application must also be notified.         *         * When the application is called, the d_len field         * contains the length of the incoming data. The application can         * access the incoming data through the global pointer         * d_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN         *  bytes into the d_buf array.         *         * If the application wishes to send any data, this data should be         * put into the d_appdata and the length of the data should be         * put into d_len. If the application don't have any data to         * send, d_len must be set to 0.         */        if (flags & (UIP_NEWDATA | UIP_ACKDATA))          {            dev->d_sndlen = 0;            result        = uip_tcpcallback(dev, conn, flags);            uip_tcpappsend(dev, conn, result);            return;          }        goto drop;      case UIP_LAST_ACK:        /* We can close this connection if the peer has acknowledged our         * FIN. This is indicated by the UIP_ACKDATA flag.         */        if (flags & UIP_ACKDATA)          {            conn->tcpstateflags = UIP_CLOSED;            nvdbg("UIP_LAST_ACK TCP state: UIP_CLOSED\n");            (void)uip_tcpcallback(dev, conn, UIP_CLOSE);          }        break;      case UIP_FIN_WAIT_1:        /* The application has closed the connection, but the remote host         * hasn't closed its end yet. Thus we do nothing but wait for a         * FIN from the other side.         */        if (dev->d_len > 0)          {            uip_incr32(conn->rcv_nxt, dev->d_len);          }        if (BUF->flags & TCP_FIN)          {            if (flags & UIP_ACKDATA)              {                conn->tcpstateflags = UIP_TIME_WAIT;                conn->timer         = 0;                conn->len           = 0;                nvdbg("TCP state: UIP_TIME_WAIT\n");              }            else              {                conn->tcpstateflags = UIP_CLOSING;                nvdbg("TCP state: UIP_CLOSING\n");              }            uip_incr32(conn->rcv_nxt, 1);            (void)uip_tcpcallback(dev, conn, UIP_CLOSE);            uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);            return;          }        else if (flags & UIP_ACKDATA)          {            conn->tcpstateflags = UIP_FIN_WAIT_2;            conn->len = 0;            nvdbg("TCP state: UIP_FIN_WAIT_2\n");            goto drop;          }        if (dev->d_len > 0)          {            uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);            return;          }        goto drop;      case UIP_FIN_WAIT_2:        if (dev->d_len > 0)          {            uip_incr32(conn->rcv_nxt, dev->d_len);          }        if (BUF->flags & TCP_FIN)          {            conn->tcpstateflags = UIP_TIME_WAIT;            conn->timer         = 0;            nvdbg("TCP state: UIP_TIME_WAIT\n");            uip_incr32(conn->rcv_nxt, 1);            (void)uip_tcpcallback(dev, conn, UIP_CLOSE);            uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);            return;          }        if (dev->d_len > 0)          {            uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);            return;          }        goto drop;      case UIP_TIME_WAIT:        uip_tcpsend(dev, conn, TCP_ACK, UIP_IPTCPH_LEN);        return;      case UIP_CLOSING:        if (flags & UIP_ACKDATA)          {            conn->tcpstateflags = UIP_TIME_WAIT;            conn->timer        = 0;            nvdbg("TCP state: UIP_TIME_WAIT\n");          }      default:        break;    }drop:  dev->d_len = 0;}#endif /* CONFIG_NET  && CONFIG_NET_TCP */

⌨️ 快捷键说明

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