80 |
err_t |
err_t |
81 |
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy) |
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy) |
82 |
{ |
{ |
83 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb, |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb, |
84 |
arg, len, (unsigned int)copy)); |
arg, len, (u16_t)copy)); |
85 |
/* connection is in valid state for data transmission? */ |
/* connection is in valid state for data transmission? */ |
86 |
if (pcb->state == ESTABLISHED || |
if (pcb->state == ESTABLISHED || |
87 |
pcb->state == CLOSE_WAIT || |
pcb->state == CLOSE_WAIT || |
123 |
void *ptr; |
void *ptr; |
124 |
u8_t queuelen; |
u8_t queuelen; |
125 |
|
|
126 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n", |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n", |
127 |
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy)); |
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy)); |
128 |
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)", |
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)", |
129 |
len == 0 || optlen == 0); |
len == 0 || optlen == 0); |
130 |
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)", |
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)", |
131 |
arg == NULL || optdata == NULL); |
arg == NULL || optdata == NULL); |
132 |
/* fail on too much data */ |
/* fail on too much data */ |
133 |
if (len > pcb->snd_buf) { |
if (len > pcb->snd_buf) { |
134 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf)); |
135 |
return ERR_MEM; |
return ERR_MEM; |
136 |
} |
} |
137 |
left = len; |
left = len; |
141 |
* by the call to this function. */ |
* by the call to this function. */ |
142 |
seqno = pcb->snd_lbb; |
seqno = pcb->snd_lbb; |
143 |
|
|
144 |
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen)); |
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); |
145 |
|
|
146 |
/* If total number of pbufs on the unsent/unacked queues exceeds the |
/* If total number of pbufs on the unsent/unacked queues exceeds the |
147 |
* configured maximum, return an error */ |
* configured maximum, return an error */ |
148 |
queuelen = pcb->snd_queuelen; |
queuelen = pcb->snd_queuelen; |
149 |
if (queuelen >= TCP_SND_QUEUELEN) { |
if (queuelen >= TCP_SND_QUEUELEN) { |
150 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); |
151 |
TCP_STATS_INC(tcp.memerr); |
TCP_STATS_INC(tcp.memerr); |
152 |
return ERR_MEM; |
return ERR_MEM; |
153 |
} |
} |
207 |
/* copy from volatile memory? */ |
/* copy from volatile memory? */ |
208 |
else if (copy) { |
else if (copy) { |
209 |
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) { |
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) { |
210 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); |
211 |
goto memerr; |
goto memerr; |
212 |
} |
} |
213 |
++queuelen; |
++queuelen; |
250 |
/* Now that there are more segments queued, we check again if the |
/* Now that there are more segments queued, we check again if the |
251 |
length of the queue exceeds the configured maximum. */ |
length of the queue exceeds the configured maximum. */ |
252 |
if (queuelen > TCP_SND_QUEUELEN) { |
if (queuelen > TCP_SND_QUEUELEN) { |
253 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); |
254 |
goto memerr; |
goto memerr; |
255 |
} |
} |
256 |
|
|
281 |
segments such as SYN|ACK. */ |
segments such as SYN|ACK. */ |
282 |
memcpy(seg->dataptr, optdata, optlen); |
memcpy(seg->dataptr, optdata, optlen); |
283 |
} |
} |
284 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n", |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", |
285 |
ntohl(seg->tcphdr->seqno), |
ntohl(seg->tcphdr->seqno), |
286 |
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), |
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), |
287 |
flags)); |
(u16_t)flags)); |
288 |
|
|
289 |
left -= seglen; |
left -= seglen; |
290 |
seqno += seglen; |
seqno += seglen; |
291 |
ptr = (void *)((char *)ptr + seglen); |
ptr = (void *)((u8_t *)ptr + seglen); |
292 |
} |
} |
293 |
|
|
294 |
/* Now that the data to be enqueued has been broken up into TCP |
/* Now that the data to be enqueued has been broken up into TCP |
316 |
useg->len += queue->len; |
useg->len += queue->len; |
317 |
useg->next = queue->next; |
useg->next = queue->next; |
318 |
|
|
319 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %u\n", useg->len)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len)); |
320 |
if (seg == queue) { |
if (seg == queue) { |
321 |
seg = NULL; |
seg = NULL; |
322 |
} |
} |
343 |
|
|
344 |
/* update number of segments on the queues */ |
/* update number of segments on the queues */ |
345 |
pcb->snd_queuelen = queuelen; |
pcb->snd_queuelen = queuelen; |
346 |
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen)); |
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); |
347 |
if (pcb->snd_queuelen != 0) { |
if (pcb->snd_queuelen != 0) { |
348 |
LWIP_ASSERT("tcp_enqueue: valid queue length", |
LWIP_ASSERT("tcp_enqueue: valid queue length", |
349 |
pcb->unacked != NULL || pcb->unsent != NULL); |
pcb->unacked != NULL || pcb->unsent != NULL); |
366 |
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || |
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || |
367 |
pcb->unsent != NULL); |
pcb->unsent != NULL); |
368 |
} |
} |
369 |
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen)); |
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); |
370 |
return ERR_MEM; |
return ERR_MEM; |
371 |
} |
} |
372 |
|
|
379 |
struct tcp_seg *seg, *useg; |
struct tcp_seg *seg, *useg; |
380 |
u32_t wnd; |
u32_t wnd; |
381 |
#if TCP_CWND_DEBUG |
#if TCP_CWND_DEBUG |
382 |
int i = 0; |
s16_t i = 0; |
383 |
#endif /* TCP_CWND_DEBUG */ |
#endif /* TCP_CWND_DEBUG */ |
384 |
|
|
385 |
/* First, check if we are invoked by the TCP input processing |
/* First, check if we are invoked by the TCP input processing |
414 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); |
415 |
return ERR_BUF; |
return ERR_BUF; |
416 |
} |
} |
417 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); |
418 |
/* remove ACK flags from the PCB, as we send an empty ACK now */ |
/* remove ACK flags from the PCB, as we send an empty ACK now */ |
419 |
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); |
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); |
420 |
|
|
442 |
|
|
443 |
#if TCP_OUTPUT_DEBUG |
#if TCP_OUTPUT_DEBUG |
444 |
if (seg == NULL) { |
if (seg == NULL) { |
445 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent)); |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent)); |
446 |
} |
} |
447 |
#endif /* TCP_OUTPUT_DEBUG */ |
#endif /* TCP_OUTPUT_DEBUG */ |
448 |
#if TCP_CWND_DEBUG |
#if TCP_CWND_DEBUG |
449 |
if (seg == NULL) { |
if (seg == NULL) { |
450 |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n", |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n", |
451 |
pcb->snd_wnd, pcb->cwnd, wnd, |
pcb->snd_wnd, pcb->cwnd, wnd, |
452 |
pcb->lastack)); |
pcb->lastack)); |
453 |
} else { |
} else { |
454 |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n", |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", |
455 |
pcb->snd_wnd, pcb->cwnd, wnd, |
pcb->snd_wnd, pcb->cwnd, wnd, |
456 |
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, |
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, |
457 |
ntohl(seg->tcphdr->seqno), pcb->lastack)); |
ntohl(seg->tcphdr->seqno), pcb->lastack)); |
461 |
while (seg != NULL && |
while (seg != NULL && |
462 |
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { |
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { |
463 |
#if TCP_CWND_DEBUG |
#if TCP_CWND_DEBUG |
464 |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n", |
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", |
465 |
pcb->snd_wnd, pcb->cwnd, wnd, |
pcb->snd_wnd, pcb->cwnd, wnd, |
466 |
ntohl(seg->tcphdr->seqno) + seg->len - |
ntohl(seg->tcphdr->seqno) + seg->len - |
467 |
pcb->lastack, |
pcb->lastack, |
549 |
pcb->rttest = tcp_ticks; |
pcb->rttest = tcp_ticks; |
550 |
pcb->rtseq = ntohl(seg->tcphdr->seqno); |
pcb->rtseq = ntohl(seg->tcphdr->seqno); |
551 |
|
|
552 |
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq)); |
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); |
553 |
} |
} |
554 |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n", |
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", |
555 |
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + |
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + |
556 |
seg->len)); |
seg->len)); |
557 |
|
|
607 |
/* Send output with hardcoded TTL since we have no access to the pcb */ |
/* Send output with hardcoded TTL since we have no access to the pcb */ |
608 |
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); |
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); |
609 |
pbuf_free(p); |
pbuf_free(p); |
610 |
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno)); |
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); |
611 |
} |
} |
612 |
|
|
613 |
/* requeue all unacked segments for retransmission */ |
/* requeue all unacked segments for retransmission */ |
674 |
struct pbuf *p; |
struct pbuf *p; |
675 |
struct tcp_hdr *tcphdr; |
struct tcp_hdr *tcphdr; |
676 |
|
|
677 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n", |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", |
678 |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
679 |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); |
680 |
|
|
681 |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt)); |
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt)); |
682 |
|
|
683 |
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); |
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); |
684 |
|
|
707 |
|
|
708 |
pbuf_free(p); |
pbuf_free(p); |
709 |
|
|
710 |
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); |
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt)); |
711 |
} |
} |
712 |
|
|
713 |
#endif /* LWIP_TCP */ |
#endif /* LWIP_TCP */ |