50 #include "lwip/ip_addr.h"
60 #if TCP_CHECKSUM_ON_COPY
61 #define TCP_DATA_COPY(dst, src, len, seg) do { \
62 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
63 len, &seg->chksum, &seg->chksum_swapped); \
64 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
65 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \
66 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
68 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len)
69 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
74 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
75 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
79 static void tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb);
92 tcp_output_alloc_header(
struct tcp_pcb *pcb,
u16_t optlen,
u16_t datalen,
95 struct tcp_hdr *tcphdr;
98 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
99 (p->
len >= TCP_HLEN + optlen));
100 tcphdr = (
struct tcp_hdr *)p->
payload;
101 tcphdr->src =
htons(pcb->local_port);
102 tcphdr->dest =
htons(pcb->remote_port);
103 tcphdr->seqno = seqno_be;
104 tcphdr->ackno =
htonl(pcb->rcv_nxt);
105 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
106 tcphdr->wnd =
htons(pcb->rcv_ann_wnd);
111 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
123 tcp_send_fin(
struct tcp_pcb *pcb)
126 if (pcb->unsent !=
NULL) {
127 struct tcp_seg *last_unsent;
128 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
129 last_unsent = last_unsent->next);
131 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
133 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
138 return tcp_enqueue_flags(pcb, TCP_FIN);
155 static struct tcp_seg *
159 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
166 seg->flags = optflags;
170 seg->len = p->
tot_len - optlen;
171 #if TCP_OVERSIZE_DBGCHECK
172 seg->oversize_left = 0;
174 #if TCP_CHECKSUM_ON_COPY
176 seg->chksum_swapped = 0;
178 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
179 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
189 seg->tcphdr = (
struct tcp_hdr *)seg->p->payload;
190 seg->tcphdr->src =
htons(pcb->local_port);
191 seg->tcphdr->dest =
htons(pcb->remote_port);
192 seg->tcphdr->seqno =
htonl(seqno);
194 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
196 seg->tcphdr->urgp = 0;
218 u16_t *oversize,
struct tcp_pcb *pcb,
u8_t apiflags,
222 u16_t alloc = length;
224 #if LWIP_NETIF_TX_SINGLE_PBUF
232 if (length < max_length) {
244 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
245 (!(pcb->flags & TF_NODELAY) &&
247 pcb->unsent !=
NULL ||
248 pcb->unacked !=
NULL))) {
258 *oversize = p->
len - length;
264 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
267 #if TCP_CHECKSUM_ON_COPY
271 u8_t *seg_chksum_swapped)
275 helper = chksum + *seg_chksum;
277 if ((len & 1) != 0) {
278 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
281 *seg_chksum = chksum;
292 tcp_write_checks(
struct tcp_pcb *pcb,
u16_t len)
295 if ((pcb->state != ESTABLISHED) &&
296 (pcb->state != CLOSE_WAIT) &&
297 (pcb->state != SYN_SENT) &&
298 (pcb->state != SYN_RCVD)) {
301 }
else if (len == 0) {
306 if (len > pcb->snd_buf) {
309 pcb->flags |= TF_NAGLEMEMERR;
318 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
322 pcb->flags |= TF_NAGLEMEMERR;
325 if (pcb->snd_queuelen != 0) {
326 LWIP_ASSERT(
"tcp_write: pbufs on queue => at least one queue non-empty",
327 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
329 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
330 pcb->unacked ==
NULL && pcb->unsent ==
NULL);
352 tcp_write(
struct tcp_pcb *pcb,
const void *arg,
u16_t len,
u8_t apiflags)
355 struct tcp_seg *last_unsent =
NULL, *seg =
NULL, *prev_seg =
NULL, *queue =
NULL;
362 u16_t oversize_used = 0;
364 #if TCP_CHECKSUM_ON_COPY
365 u16_t concat_chksum = 0;
366 u8_t concat_chksum_swapped = 0;
367 u16_t concat_chksummed = 0;
371 #if LWIP_NETIF_TX_SINGLE_PBUF
373 apiflags |= TCP_WRITE_FLAG_COPY;
377 (
void *)pcb, arg, len, (
u16_t)apiflags));
378 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
381 err = tcp_write_checks(pcb, len);
385 queuelen = pcb->snd_queuelen;
387 #if LWIP_TCP_TIMESTAMPS
388 if ((pcb->flags & TF_TIMESTAMP)) {
389 optflags = TF_SEG_OPTS_TS;
390 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
418 if (pcb->unsent !=
NULL) {
423 for (last_unsent = pcb->unsent; last_unsent->next !=
NULL;
424 last_unsent = last_unsent->next);
427 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
428 space = pcb->mss - (last_unsent->len + unsent_optlen);
438 #if TCP_OVERSIZE_DBGCHECK
440 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
441 pcb->unsent_oversize == last_unsent->oversize_left);
443 oversize = pcb->unsent_oversize;
445 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize_used <= space);
447 oversize_used = oversize < len ? oversize : len;
448 pos += oversize_used;
449 oversize -= oversize_used;
450 space -= oversize_used;
453 LWIP_ASSERT(
"inconsistend oversize vs. len", (oversize == 0) || (pos == len));
463 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
464 u16_t seglen = space < len - pos ? space : len - pos;
470 if (apiflags & TCP_WRITE_FLAG_COPY) {
472 if ((concat_p = tcp_pbuf_prealloc(
PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) ==
NULL) {
474 (
"tcp_write : could not allocate memory for pbuf copy size %"U16_F
"\n",
478 #if TCP_OVERSIZE_DBGCHECK
479 last_unsent->oversize_left = oversize;
481 TCP_DATA_COPY2(concat_p->
payload, (
u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
482 #if TCP_CHECKSUM_ON_COPY
483 concat_chksummed += seglen;
489 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
492 #if TCP_CHECKSUM_ON_COPY
495 &concat_chksum, &concat_chksum_swapped);
496 concat_chksummed += seglen;
507 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
508 pcb->unsent_oversize == 0);
520 u16_t left = len - pos;
521 u16_t max_len = pcb->mss - optlen;
522 u16_t seglen = left > max_len ? max_len : left;
523 #if TCP_CHECKSUM_ON_COPY
525 u8_t chksum_swapped = 0;
528 if (apiflags & TCP_WRITE_FLAG_COPY) {
531 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, pcb->mss, &oversize, pcb, apiflags, queue ==
NULL)) ==
NULL) {
535 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
537 TCP_DATA_COPY2((
char *)p->
payload + optlen, (
u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
552 #if TCP_CHECKSUM_ON_COPY
576 if ((queuelen >
TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
585 #if TCP_OVERSIZE_DBGCHECK
586 seg->oversize_left = oversize;
588 #if TCP_CHECKSUM_ON_COPY
589 seg->chksum = chksum;
590 seg->chksum_swapped = chksum_swapped;
591 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
594 if ((apiflags & TCP_WRITE_FLAG_COPY) == 0) {
595 seg->dataptr = (
u8_t*)arg + pos;
604 prev_seg->next = seg;
610 ntohl(seg->tcphdr->seqno),
611 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
626 if (oversize_used > 0) {
629 for (p = last_unsent->p; p; p = p->
next) {
632 TCP_DATA_COPY((
char *)p->
payload + p->
len, arg, oversize_used, last_unsent);
633 p->
len += oversize_used;
636 last_unsent->len += oversize_used;
637 #if TCP_OVERSIZE_DBGCHECK
638 last_unsent->oversize_left -= oversize_used;
641 pcb->unsent_oversize = oversize;
647 if (concat_p !=
NULL) {
648 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
649 (last_unsent !=
NULL));
651 last_unsent->len += concat_p->
tot_len;
652 #if TCP_CHECKSUM_ON_COPY
653 if (concat_chksummed) {
654 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
655 &last_unsent->chksum_swapped);
656 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
665 if (last_unsent ==
NULL) {
668 last_unsent->next = queue;
676 pcb->snd_queuelen = queuelen;
680 if (pcb->snd_queuelen != 0) {
682 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
686 if (seg !=
NULL && seg->tcphdr !=
NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
687 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
692 pcb->flags |= TF_NAGLEMEMERR;
695 if (concat_p !=
NULL) {
699 tcp_segs_free(queue);
701 if (pcb->snd_queuelen != 0) {
703 pcb->unsent !=
NULL);
720 tcp_enqueue_flags(
struct tcp_pcb *pcb,
u8_t flags)
729 LWIP_ASSERT(
"tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
730 (flags & (TCP_SYN | TCP_FIN)) != 0);
733 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
737 pcb->flags |= TF_NAGLEMEMERR;
741 if (flags & TCP_SYN) {
742 optflags = TF_SEG_OPTS_MSS;
744 #if LWIP_TCP_TIMESTAMPS
745 if ((pcb->flags & TF_TIMESTAMP)) {
746 optflags |= TF_SEG_OPTS_TS;
749 optlen = LWIP_TCP_OPT_LENGTH(optflags);
755 if (pcb->snd_buf == 0) {
763 pcb->flags |= TF_NAGLEMEMERR;
767 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
772 pcb->flags |= TF_NAGLEMEMERR;
777 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
780 (
"tcp_enqueue_flags: queueing %"U32_F
":%"U32_F
" (0x%"X16_F")\n",
781 ntohl(seg->tcphdr->seqno),
782 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
786 if (pcb->unsent ==
NULL) {
789 struct tcp_seg *useg;
790 for (useg = pcb->unsent; useg->next !=
NULL; useg = useg->next);
795 pcb->unsent_oversize = 0;
799 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
804 if (flags & TCP_FIN) {
805 pcb->flags |= TF_FIN;
811 if (pcb->snd_queuelen != 0) {
812 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
813 pcb->unacked !=
NULL || pcb->unsent !=
NULL);
820 #if LWIP_TCP_TIMESTAMPS
827 tcp_build_timestamp_option(
struct tcp_pcb *pcb,
u32_t *opts)
832 opts[2] =
htonl(pcb->ts_recent);
841 tcp_send_empty_ack(
struct tcp_pcb *pcb)
844 struct tcp_hdr *tcphdr;
847 #if LWIP_TCP_TIMESTAMPS
848 if (pcb->flags & TF_TIMESTAMP) {
849 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
853 p = tcp_output_alloc_header(pcb, optlen, 0,
htonl(pcb->snd_nxt));
858 tcphdr = (
struct tcp_hdr *)p->
payload;
860 (
"tcp_output: sending ACK for %"U32_F
"\n", pcb->rcv_nxt));
862 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
865 #if LWIP_TCP_TIMESTAMPS
866 pcb->ts_lastacksent = pcb->rcv_nxt;
868 if (pcb->flags & TF_TIMESTAMP) {
869 tcp_build_timestamp_option(pcb, (
u32_t *)(tcphdr + 1));
877 #if LWIP_NETIF_HWADDRHINT
878 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
881 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
897 tcp_output(
struct tcp_pcb *pcb)
899 struct tcp_seg *seg, *useg;
909 if (tcp_input_pcb == pcb) {
913 wnd =
LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
923 if (pcb->flags & TF_ACK_NOW &&
925 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
926 return tcp_send_empty_ack(pcb);
932 for (; useg->next !=
NULL; useg = useg->next);
938 (
void*)pcb->unsent));
944 ", cwnd %"U16_F
", wnd %"U32_F
945 ", seg == NULL, ack %"U32_F
"\n",
946 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
949 (
"tcp_output: snd_wnd %"U16_F
", cwnd %"U16_F
", wnd %"U32_F
950 ", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
"\n",
951 pcb->snd_wnd, pcb->cwnd, wnd,
952 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
953 ntohl(seg->tcphdr->seqno), pcb->lastack));
957 while (seg !=
NULL &&
958 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
960 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
968 if((tcp_do_output_nagle(pcb) == 0) &&
969 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
973 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_output: snd_wnd %"U16_F
", cwnd %"U16_F
", wnd %"U32_F
", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
", i %"S16_F"\n",
974 pcb->snd_wnd, pcb->cwnd, wnd,
975 ntohl(seg->tcphdr->seqno) + seg->len -
977 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
981 pcb->unsent = seg->next;
983 if (pcb->state != SYN_SENT) {
984 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
985 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
988 tcp_output_segment(seg, pcb);
989 snd_nxt =
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
990 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
991 pcb->snd_nxt = snd_nxt;
994 if (TCP_TCPLEN(seg) > 0) {
997 if (pcb->unacked ==
NULL) {
1005 if (TCP_SEQ_LT(
ntohl(seg->tcphdr->seqno),
ntohl(useg->tcphdr->seqno))) {
1007 struct tcp_seg **cur_seg = &(pcb->unacked);
1009 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1010 cur_seg = &((*cur_seg)->next );
1012 seg->next = (*cur_seg);
1027 if (pcb->unsent ==
NULL) {
1029 pcb->unsent_oversize = 0;
1033 if (seg !=
NULL && pcb->persist_backoff == 0 &&
1034 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
1036 pcb->persist_cnt = 0;
1037 pcb->persist_backoff = 1;
1040 pcb->flags &= ~TF_NAGLEMEMERR;
1051 tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb)
1062 seg->tcphdr->ackno =
htonl(pcb->rcv_nxt);
1065 seg->tcphdr->wnd =
htons(pcb->rcv_ann_wnd);
1067 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1072 opts = (
u32_t *)(
void *)(seg->tcphdr + 1);
1073 if (seg->flags & TF_SEG_OPTS_MSS) {
1074 TCP_BUILD_MSS_OPTION(*opts);
1077 #if LWIP_TCP_TIMESTAMPS
1078 pcb->ts_lastacksent = pcb->rcv_nxt;
1080 if (seg->flags & TF_SEG_OPTS_TS) {
1081 tcp_build_timestamp_option(pcb, opts);
1089 netif =
ip_route(&(pcb->remote_ip));
1090 if (netif ==
NULL) {
1097 if(pcb->rtime == -1) {
1101 if (pcb->rttest == 0) {
1102 pcb->rttest = tcp_ticks;
1103 pcb->rtseq =
ntohl(seg->tcphdr->seqno);
1108 htonl(seg->tcphdr->seqno),
htonl(seg->tcphdr->seqno) +
1111 len = (
u16_t)((
u8_t *)seg->tcphdr - (
u8_t *)seg->p->payload);
1114 seg->p->tot_len -= len;
1116 seg->p->payload = seg->tcphdr;
1118 seg->tcphdr->chksum = 0;
1119 #if CHECKSUM_GEN_TCP
1120 #if TCP_CHECKSUM_ON_COPY
1123 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1128 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1130 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
1136 IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
1138 if (seg->chksum_swapped) {
1140 seg->chksum_swapped = 0;
1142 acc += (
u16_t)~(seg->chksum);
1144 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
1145 if (chksum_slow != seg->tcphdr->chksum) {
1147 (
"tcp_output_segment: calculated checksum is %"X16_F
" instead of %"X16_F
"\n",
1148 seg->tcphdr->chksum, chksum_slow));
1149 seg->tcphdr->chksum = chksum_slow;
1161 #if LWIP_NETIF_HWADDRHINT
1162 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1165 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1196 struct tcp_hdr *tcphdr;
1202 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1203 (p->
len >=
sizeof(
struct tcp_hdr)));
1205 tcphdr = (
struct tcp_hdr *)p->
payload;
1206 tcphdr->src =
htons(local_port);
1207 tcphdr->dest =
htons(remote_port);
1208 tcphdr->seqno =
htonl(seqno);
1209 tcphdr->ackno =
htonl(ackno);
1210 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
1215 #if CHECKSUM_GEN_TCP
1235 tcp_rexmit_rto(
struct tcp_pcb *pcb)
1237 struct tcp_seg *seg;
1239 if (pcb->unacked ==
NULL) {
1244 for (seg = pcb->unacked; seg->next !=
NULL; seg = seg->next);
1246 seg->next = pcb->unsent;
1248 pcb->unsent = pcb->unacked;
1250 pcb->unacked =
NULL;
1270 tcp_rexmit(
struct tcp_pcb *pcb)
1272 struct tcp_seg *seg;
1273 struct tcp_seg **cur_seg;
1275 if (pcb->unacked ==
NULL) {
1282 pcb->unacked = seg->next;
1284 cur_seg = &(pcb->unsent);
1286 TCP_SEQ_LT(
ntohl((*cur_seg)->tcphdr->seqno),
ntohl(seg->tcphdr->seqno))) {
1287 cur_seg = &((*cur_seg)->next );
1289 seg->next = *cur_seg;
1310 tcp_rexmit_fast(
struct tcp_pcb *pcb)
1312 if (pcb->unacked !=
NULL && !(pcb->flags & TF_INFR)) {
1315 (
"tcp_receive: dupacks %"U16_F
" (%"U32_F
1316 "), fast retransmit %"U32_F
"\n",
1317 (
u16_t)pcb->dupacks, pcb->lastack,
1318 ntohl(pcb->unacked->tcphdr->seqno)));
1323 if (pcb->cwnd > pcb->snd_wnd) {
1324 pcb->ssthresh = pcb->snd_wnd / 2;
1326 pcb->ssthresh = pcb->cwnd / 2;
1330 if (pcb->ssthresh < 2*pcb->mss) {
1332 (
"tcp_receive: The minimum value for ssthresh %"U16_F
1333 " should be min 2 mss %"U16_F
"...\n",
1334 pcb->ssthresh, 2*pcb->mss));
1335 pcb->ssthresh = 2*pcb->mss;
1338 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1339 pcb->flags |= TF_INFR;
1353 tcp_keepalive(
struct tcp_pcb *pcb)
1356 struct tcp_hdr *tcphdr;
1358 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: sending KEEPALIVE probe to %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
1362 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: tcp_ticks %"U32_F
" pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1363 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1365 p = tcp_output_alloc_header(pcb, 0, 0,
htonl(pcb->snd_nxt - 1));
1368 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
1371 tcphdr = (
struct tcp_hdr *)p->
payload;
1380 #if LWIP_NETIF_HWADDRHINT
1381 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0,
IP_PROTO_TCP,
1390 pcb->snd_nxt - 1, pcb->rcv_nxt));
1403 tcp_zero_window_probe(
struct tcp_pcb *pcb)
1406 struct tcp_hdr *tcphdr;
1407 struct tcp_seg *seg;
1412 (
"tcp_zero_window_probe: sending ZERO WINDOW probe to %"
1413 U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
1418 (
"tcp_zero_window_probe: tcp_ticks %"U32_F
1419 " pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1420 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1431 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1433 len = is_fin ? 0 : 1;
1435 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1440 tcphdr = (
struct tcp_hdr *)p->
payload;
1444 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1447 *((
char *)p->
payload + TCP_HLEN) = *(
char *)seg->dataptr;
1450 #if CHECKSUM_GEN_TCP
1457 #if LWIP_NETIF_HWADDRHINT
1458 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0,
IP_PROTO_TCP,
1467 " ackno %"U32_F
".\n",
1468 pcb->snd_nxt - 1, pcb->rcv_nxt));