|
@@ -6,7 +6,7 @@
|
|
*
|
|
*
|
|
* These functions are generally called in the order (ip_input() ->)
|
|
* These functions are generally called in the order (ip_input() ->)
|
|
* tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
|
|
* tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
|
|
- *
|
|
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -91,7 +91,6 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
|
|
void
|
|
void
|
|
tcp_input(struct pbuf *p, struct netif *inp)
|
|
tcp_input(struct pbuf *p, struct netif *inp)
|
|
{
|
|
{
|
|
- printf("----TCP_INPUT()\n");
|
|
|
|
struct tcp_pcb *pcb, *prev;
|
|
struct tcp_pcb *pcb, *prev;
|
|
struct tcp_pcb_listen *lpcb;
|
|
struct tcp_pcb_listen *lpcb;
|
|
#if SO_REUSE
|
|
#if SO_REUSE
|
|
@@ -167,7 +166,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
for an active connection. */
|
|
for an active connection. */
|
|
prev = NULL;
|
|
prev = NULL;
|
|
|
|
|
|
-
|
|
|
|
|
|
+
|
|
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
|
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
|
|
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
|
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
|
|
@@ -254,7 +253,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
/* put this listening pcb at the head of the listening list */
|
|
/* put this listening pcb at the head of the listening list */
|
|
tcp_listen_pcbs.listen_pcbs = lpcb;
|
|
tcp_listen_pcbs.listen_pcbs = lpcb;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
|
|
tcp_listen_input(lpcb);
|
|
tcp_listen_input(lpcb);
|
|
pbuf_free(p);
|
|
pbuf_free(p);
|
|
@@ -268,10 +267,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
|
|
#endif /* TCP_INPUT_DEBUG */
|
|
#endif /* TCP_INPUT_DEBUG */
|
|
|
|
|
|
- if(pcb == NULL)
|
|
|
|
- {
|
|
|
|
- printf ("--------------PCB == NULL!\n");
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
if (pcb != NULL) {
|
|
if (pcb != NULL) {
|
|
/* The incoming segment belongs to a connection. */
|
|
/* The incoming segment belongs to a connection. */
|
|
#if TCP_INPUT_DEBUG
|
|
#if TCP_INPUT_DEBUG
|
|
@@ -305,7 +301,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tcp_input_pcb = pcb;
|
|
tcp_input_pcb = pcb;
|
|
- printf(" > TCP_PROCESS()\n");
|
|
|
|
err = tcp_process(pcb);
|
|
err = tcp_process(pcb);
|
|
/* A return value of ERR_ABRT means that tcp_abort() was called
|
|
/* A return value of ERR_ABRT means that tcp_abort() was called
|
|
and that the pcb has been freed. If so, we don't do anything. */
|
|
and that the pcb has been freed. If so, we don't do anything. */
|
|
@@ -579,7 +574,6 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
|
static err_t
|
|
static err_t
|
|
tcp_process(struct tcp_pcb *pcb)
|
|
tcp_process(struct tcp_pcb *pcb)
|
|
{
|
|
{
|
|
- printf("------TCP_PROCESS()\n");
|
|
|
|
struct tcp_seg *rseg;
|
|
struct tcp_seg *rseg;
|
|
u8_t acceptable = 0;
|
|
u8_t acceptable = 0;
|
|
err_t err;
|
|
err_t err;
|
|
@@ -594,7 +588,7 @@ tcp_process(struct tcp_pcb *pcb)
|
|
acceptable = 1;
|
|
acceptable = 1;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
|
|
|
|
|
+ if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
|
pcb->rcv_nxt+pcb->rcv_wnd)) {
|
|
pcb->rcv_nxt+pcb->rcv_wnd)) {
|
|
acceptable = 1;
|
|
acceptable = 1;
|
|
}
|
|
}
|
|
@@ -615,12 +609,12 @@ tcp_process(struct tcp_pcb *pcb)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
|
|
|
|
|
|
+ if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
|
|
/* Cope with new connection attempt after remote end crashed */
|
|
/* Cope with new connection attempt after remote end crashed */
|
|
tcp_ack_now(pcb);
|
|
tcp_ack_now(pcb);
|
|
return ERR_OK;
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if ((pcb->flags & TF_RXCLOSED) == 0) {
|
|
if ((pcb->flags & TF_RXCLOSED) == 0) {
|
|
/* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
|
|
/* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
|
|
pcb->tmr = tcp_ticks;
|
|
pcb->tmr = tcp_ticks;
|
|
@@ -629,8 +623,6 @@ tcp_process(struct tcp_pcb *pcb)
|
|
|
|
|
|
tcp_parseopt(pcb);
|
|
tcp_parseopt(pcb);
|
|
|
|
|
|
-printf("------TCP_PROCESS(): pcb->state = %d\n", pcb->state);
|
|
|
|
-
|
|
|
|
/* Do different things depending on the TCP state. */
|
|
/* Do different things depending on the TCP state. */
|
|
switch (pcb->state) {
|
|
switch (pcb->state) {
|
|
case SYN_SENT:
|
|
case SYN_SENT:
|
|
@@ -900,7 +892,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
#if TCP_WND_DEBUG
|
|
#if TCP_WND_DEBUG
|
|
} else {
|
|
} else {
|
|
if (pcb->snd_wnd != tcphdr->wnd) {
|
|
if (pcb->snd_wnd != tcphdr->wnd) {
|
|
- LWIP_DEBUGF(TCP_WND_DEBUG,
|
|
|
|
|
|
+ LWIP_DEBUGF(TCP_WND_DEBUG,
|
|
("tcp_receive: no window update lastack %"U32_F" ackno %"
|
|
("tcp_receive: no window update lastack %"U32_F" ackno %"
|
|
U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
|
|
U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
|
|
pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
|
pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
|
|
@@ -910,17 +902,17 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
|
|
|
|
/* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
|
|
/* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
|
|
* duplicate ack if:
|
|
* duplicate ack if:
|
|
- * 1) It doesn't ACK new data
|
|
|
|
- * 2) length of received packet is zero (i.e. no payload)
|
|
|
|
- * 3) the advertised window hasn't changed
|
|
|
|
|
|
+ * 1) It doesn't ACK new data
|
|
|
|
+ * 2) length of received packet is zero (i.e. no payload)
|
|
|
|
+ * 3) the advertised window hasn't changed
|
|
* 4) There is outstanding unacknowledged data (retransmission timer running)
|
|
* 4) There is outstanding unacknowledged data (retransmission timer running)
|
|
* 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
|
|
* 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
|
|
- *
|
|
|
|
- * If it passes all five, should process as a dupack:
|
|
|
|
- * a) dupacks < 3: do nothing
|
|
|
|
- * b) dupacks == 3: fast retransmit
|
|
|
|
- * c) dupacks > 3: increase cwnd
|
|
|
|
- *
|
|
|
|
|
|
+ *
|
|
|
|
+ * If it passes all five, should process as a dupack:
|
|
|
|
+ * a) dupacks < 3: do nothing
|
|
|
|
+ * b) dupacks == 3: fast retransmit
|
|
|
|
+ * c) dupacks > 3: increase cwnd
|
|
|
|
+ *
|
|
* If it only passes 1-3, should reset dupack counter (and add to
|
|
* If it only passes 1-3, should reset dupack counter (and add to
|
|
* stats, which we don't do in lwIP)
|
|
* stats, which we don't do in lwIP)
|
|
*
|
|
*
|
|
@@ -1036,8 +1028,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
|
|
|
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
|
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
|
|
if (pcb->snd_queuelen != 0) {
|
|
if (pcb->snd_queuelen != 0) {
|
|
- //LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
|
|
|
- // pcb->unsent != NULL);
|
|
|
|
|
|
+ LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
|
|
|
|
+ pcb->unsent != NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1061,7 +1053,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
->unsent list after a retransmission, so these segments may
|
|
->unsent list after a retransmission, so these segments may
|
|
in fact have been sent once. */
|
|
in fact have been sent once. */
|
|
while (pcb->unsent != NULL &&
|
|
while (pcb->unsent != NULL &&
|
|
- TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
|
|
|
|
|
|
+ TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
|
|
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
|
|
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
|
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
|
|
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
|
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
|
|
@@ -1073,7 +1065,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
if (pcb->unsent == NULL) {
|
|
if (pcb->unsent == NULL) {
|
|
pcb->unsent_oversize = 0;
|
|
pcb->unsent_oversize = 0;
|
|
}
|
|
}
|
|
-#endif /* TCP_OVERSIZE */
|
|
|
|
|
|
+#endif /* TCP_OVERSIZE */
|
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
|
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
|
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
|
|
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
|
|
/* Prevent ACK for FIN to generate a sent event */
|
|
/* Prevent ACK for FIN to generate a sent event */
|
|
@@ -1219,7 +1211,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
/* The sequence number must be within the window (above rcv_nxt
|
|
/* The sequence number must be within the window (above rcv_nxt
|
|
and below rcv_nxt + rcv_wnd) in order to be further
|
|
and below rcv_nxt + rcv_wnd) in order to be further
|
|
processed. */
|
|
processed. */
|
|
- if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
|
|
|
|
|
+ if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
|
|
pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
|
pcb->rcv_nxt + pcb->rcv_wnd - 1)){
|
|
if (pcb->rcv_nxt == seqno) {
|
|
if (pcb->rcv_nxt == seqno) {
|
|
/* The incoming segment is the next in sequence. We check if
|
|
/* The incoming segment is the next in sequence. We check if
|
|
@@ -1228,12 +1220,12 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
tcplen = TCP_TCPLEN(&inseg);
|
|
tcplen = TCP_TCPLEN(&inseg);
|
|
|
|
|
|
if (tcplen > pcb->rcv_wnd) {
|
|
if (tcplen > pcb->rcv_wnd) {
|
|
- LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
|
|
|
|
+ LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
("tcp_receive: other end overran receive window"
|
|
("tcp_receive: other end overran receive window"
|
|
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
|
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
|
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
|
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
|
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
|
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
|
- /* Must remove the FIN from the header as we're trimming
|
|
|
|
|
|
+ /* Must remove the FIN from the header as we're trimming
|
|
* that byte of sequence-space from the packet */
|
|
* that byte of sequence-space from the packet */
|
|
TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
|
|
TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
|
|
}
|
|
}
|
|
@@ -1253,7 +1245,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
- inseq overlaps with ooseq */
|
|
- inseq overlaps with ooseq */
|
|
if (pcb->ooseq != NULL) {
|
|
if (pcb->ooseq != NULL) {
|
|
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
|
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
|
- LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
|
|
|
|
+ LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
|
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
|
/* Received in-order FIN means anything that was received
|
|
/* Received in-order FIN means anything that was received
|
|
* out of order must now have been received in-order, so
|
|
* out of order must now have been received in-order, so
|
|
@@ -1360,7 +1352,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
recv_flags |= TF_GOT_FIN;
|
|
recv_flags |= TF_GOT_FIN;
|
|
if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
|
|
if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
|
|
pcb->state = CLOSE_WAIT;
|
|
pcb->state = CLOSE_WAIT;
|
|
- }
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
pcb->ooseq = cseg->next;
|
|
pcb->ooseq = cseg->next;
|
|
@@ -1473,12 +1465,12 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
}
|
|
}
|
|
/* check if the remote side overruns our receive window */
|
|
/* check if the remote side overruns our receive window */
|
|
if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
|
|
if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
|
|
- LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
|
|
|
|
+ LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
|
("tcp_receive: other end overran receive window"
|
|
("tcp_receive: other end overran receive window"
|
|
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
|
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
|
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
|
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
|
if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
|
|
if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
|
|
- /* Must remove the FIN from the header as we're trimming
|
|
|
|
|
|
+ /* Must remove the FIN from the header as we're trimming
|
|
* that byte of sequence-space from the packet */
|
|
* that byte of sequence-space from the packet */
|
|
TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
|
|
TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
|
|
}
|
|
}
|
|
@@ -1539,7 +1531,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Parses the options contained in the incoming segment.
|
|
|
|
|
|
+ * Parses the options contained in the incoming segment.
|
|
*
|
|
*
|
|
* Called from tcp_listen_input() and tcp_process().
|
|
* Called from tcp_listen_input() and tcp_process().
|
|
* Currently, only the MSS option is supported!
|
|
* Currently, only the MSS option is supported!
|
|
@@ -1596,7 +1588,7 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
/* TCP timestamp option with valid length */
|
|
/* TCP timestamp option with valid length */
|
|
- tsval = (opts[c+2]) | (opts[c+3] << 8) |
|
|
|
|
|
|
+ tsval = (opts[c+2]) | (opts[c+3] << 8) |
|
|
(opts[c+4] << 16) | (opts[c+5] << 24);
|
|
(opts[c+4] << 16) | (opts[c+5] << 24);
|
|
if (flags & TCP_SYN) {
|
|
if (flags & TCP_SYN) {
|
|
pcb->ts_recent = ntohl(tsval);
|
|
pcb->ts_recent = ntohl(tsval);
|