74 #if LWIP_TCP_TIMESTAMPS 82 #if TCP_CHECKSUM_ON_COPY 83 #define TCP_DATA_COPY(dst, src, len, seg) do { \ 84 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ 85 len, &seg->chksum, &seg->chksum_swapped); \ 86 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) 87 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ 88 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); 90 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) 91 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) 96 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK 97 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 100 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 101 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL 102 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) 108 #ifndef TCP_OVERSIZE_CALC_LENGTH 109 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) 114 static err_t tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *
netif);
127 tcp_output_alloc_header(
struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
133 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
134 (p->
len >= TCP_HLEN + optlen));
136 tcphdr->src = lwip_htons(pcb->local_port);
137 tcphdr->dest = lwip_htons(pcb->remote_port);
138 tcphdr->seqno = seqno_be;
139 tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
140 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
141 tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
146 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
158 tcp_send_fin(
struct tcp_pcb *pcb)
161 if (pcb->unsent != NULL) {
162 struct tcp_seg *last_unsent;
163 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
164 last_unsent = last_unsent->next);
166 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
168 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
169 pcb->flags |= TF_FIN;
174 return tcp_enqueue_flags(pcb, TCP_FIN);
191 static struct tcp_seg *
192 tcp_create_segment(
struct tcp_pcb *pcb,
struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
195 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
197 if ((seg = (
struct tcp_seg *)
memp_malloc(MEMP_TCP_SEG)) == NULL) {
202 seg->flags = optflags;
205 LWIP_ASSERT(
"p->tot_len >= optlen", p->
tot_len >= optlen);
206 seg->len = p->
tot_len - optlen;
207 #if TCP_OVERSIZE_DBGCHECK 208 seg->oversize_left = 0;
210 #if TCP_CHECKSUM_ON_COPY 212 seg->chksum_swapped = 0;
214 LWIP_ASSERT(
"invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
215 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
221 TCP_STATS_INC(tcp.err);
225 seg->tcphdr = (
struct tcp_hdr *)seg->p->payload;
226 seg->tcphdr->src = lwip_htons(pcb->local_port);
227 seg->tcphdr->dest = lwip_htons(pcb->remote_port);
228 seg->tcphdr->seqno = lwip_htonl(seqno);
230 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
232 seg->tcphdr->urgp = 0;
252 tcp_pbuf_prealloc(
pbuf_layer layer, u16_t length, u16_t max_length,
253 u16_t *oversize,
struct tcp_pcb *pcb, u8_t apiflags,
257 u16_t alloc = length;
259 #if LWIP_NETIF_TX_SINGLE_PBUF 266 if (length < max_length) {
278 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
279 (!(pcb->flags & TF_NODELAY) &&
281 pcb->unsent != NULL ||
282 pcb->unacked != NULL))) {
291 LWIP_ASSERT(
"need unchained pbuf", p->
next == NULL);
292 *oversize = p->
len - length;
298 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) 301 #if TCP_CHECKSUM_ON_COPY 304 tcp_seg_add_chksum(u16_t chksum, u16_t
len, u16_t *seg_chksum,
305 u8_t *seg_chksum_swapped)
309 helper = chksum + *seg_chksum;
311 if ((len & 1) != 0) {
312 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
315 *seg_chksum = chksum;
326 tcp_write_checks(
struct tcp_pcb *pcb, u16_t len)
329 if ((pcb->state != ESTABLISHED) &&
330 (pcb->state != CLOSE_WAIT) &&
331 (pcb->state != SYN_SENT) &&
332 (pcb->state != SYN_RCVD)) {
335 }
else if (len == 0) {
340 if (len > pcb->snd_buf) {
343 pcb->flags |= TF_NAGLEMEMERR;
352 if ((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
355 TCP_STATS_INC(tcp.memerr);
356 pcb->flags |= TF_NAGLEMEMERR;
359 if (pcb->snd_queuelen != 0) {
360 LWIP_ASSERT(
"tcp_write: pbufs on queue => at least one queue non-empty",
361 pcb->unacked != NULL || pcb->unsent != NULL);
363 LWIP_ASSERT(
"tcp_write: no pbufs on queue => both queues empty",
364 pcb->unacked == NULL && pcb->unsent == NULL);
387 tcp_write(
struct tcp_pcb *pcb,
const void *arg, u16_t len, u8_t apiflags)
389 struct pbuf *concat_p = NULL;
390 struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
397 u16_t oversize_used = 0;
398 #if TCP_OVERSIZE_DBGCHECK 399 u16_t oversize_add = 0;
403 #if TCP_CHECKSUM_ON_COPY 404 u16_t concat_chksum = 0;
405 u8_t concat_chksum_swapped = 0;
406 u16_t concat_chksummed = 0;
410 u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2));
411 mss_local = mss_local ? mss_local : pcb->mss;
413 #if LWIP_NETIF_TX_SINGLE_PBUF 415 apiflags |= TCP_WRITE_FLAG_COPY;
419 (
void *)pcb, arg, len, (u16_t)apiflags));
420 LWIP_ERROR(
"tcp_write: arg == NULL (programmer violates API)",
423 err = tcp_write_checks(pcb, len);
427 queuelen = pcb->snd_queuelen;
429 #if LWIP_TCP_TIMESTAMPS 430 if ((pcb->flags & TF_TIMESTAMP)) {
433 optflags = TF_SEG_OPTS_TS;
434 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
436 mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
464 if (pcb->unsent != NULL) {
469 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
470 last_unsent = last_unsent->next);
473 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
474 LWIP_ASSERT(
"mss_local is too small", mss_local >= last_unsent->len + unsent_optlen);
475 space = mss_local - (last_unsent->len + unsent_optlen);
485 #if TCP_OVERSIZE_DBGCHECK 487 LWIP_ASSERT(
"unsent_oversize mismatch (pcb vs. last_unsent)",
488 pcb->unsent_oversize == last_unsent->oversize_left);
490 oversize = pcb->unsent_oversize;
492 LWIP_ASSERT(
"inconsistent oversize vs. space", oversize <= space);
494 oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
495 pos += oversize_used;
496 oversize -= oversize_used;
497 space -= oversize_used;
500 LWIP_ASSERT(
"inconsistent oversize vs. len", (oversize == 0) || (pos == len));
514 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
515 u16_t seglen = LWIP_MIN(space, len - pos);
521 if (apiflags & TCP_WRITE_FLAG_COPY) {
523 if ((concat_p = tcp_pbuf_prealloc(
PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
525 (
"tcp_write : could not allocate memory for pbuf copy size %"U16_F
"\n",
529 #if TCP_OVERSIZE_DBGCHECK 530 oversize_add = oversize;
532 TCP_DATA_COPY2(concat_p->
payload, (
const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
533 #if TCP_CHECKSUM_ON_COPY 534 concat_chksummed += seglen;
541 for (p = last_unsent->p; p->
next != NULL; p = p->
next);
543 LWIP_ASSERT(
"tcp_write: ROM pbufs cannot be oversized", pos == 0);
548 (
"tcp_write: could not allocate memory for zero-copy pbuf\n"));
552 ((
struct pbuf_rom*)concat_p)->payload = (
const u8_t*)arg + pos;
555 #if TCP_CHECKSUM_ON_COPY 557 tcp_seg_add_chksum(~inet_chksum((
const u8_t*)arg + pos, seglen), seglen,
558 &concat_chksum, &concat_chksum_swapped);
559 concat_chksummed += seglen;
567 LWIP_ASSERT(
"unsent_oversize mismatch (pcb->unsent is NULL)",
568 pcb->unsent_oversize == 0);
580 u16_t left = len - pos;
581 u16_t max_len = mss_local - optlen;
582 u16_t seglen = LWIP_MIN(left, max_len);
583 #if TCP_CHECKSUM_ON_COPY 585 u8_t chksum_swapped = 0;
588 if (apiflags & TCP_WRITE_FLAG_COPY) {
591 if ((p = tcp_pbuf_prealloc(
PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
595 LWIP_ASSERT(
"tcp_write: check that first pbuf can hold the complete seglen",
597 TCP_DATA_COPY2((
char *)p->
payload + optlen, (
const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
606 LWIP_ASSERT(
"oversize == 0", oversize == 0);
612 #if TCP_CHECKSUM_ON_COPY 614 chksum = ~inet_chksum((
const u8_t*)arg + pos, seglen);
621 ((
struct pbuf_rom*)p2)->payload = (
const u8_t*)arg + pos;
640 if ((queuelen >
TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
647 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
650 #if TCP_OVERSIZE_DBGCHECK 651 seg->oversize_left = oversize;
653 #if TCP_CHECKSUM_ON_COPY 654 seg->chksum = chksum;
655 seg->chksum_swapped = chksum_swapped;
656 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
664 LWIP_ASSERT(
"prev_seg != NULL", prev_seg != NULL);
665 prev_seg->next = seg;
671 lwip_ntohl(seg->tcphdr->seqno),
672 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
681 #if TCP_OVERSIZE_DBGCHECK 682 if ((last_unsent != NULL) && (oversize_add != 0)) {
683 last_unsent->oversize_left += oversize_add;
692 if (oversize_used > 0) {
695 for (p = last_unsent->p; p; p = p->
next) {
697 if (p->
next == NULL) {
698 TCP_DATA_COPY((
char *)p->
payload + p->
len, arg, oversize_used, last_unsent);
699 p->
len += oversize_used;
702 last_unsent->len += oversize_used;
703 #if TCP_OVERSIZE_DBGCHECK 704 LWIP_ASSERT(
"last_unsent->oversize_left >= oversize_used",
705 last_unsent->oversize_left >= oversize_used);
706 last_unsent->oversize_left -= oversize_used;
709 pcb->unsent_oversize = oversize;
716 if (concat_p != NULL) {
717 LWIP_ASSERT(
"tcp_write: cannot concatenate when pcb->unsent is empty",
718 (last_unsent != NULL));
720 last_unsent->len += concat_p->
tot_len;
721 }
else if (extendlen > 0) {
723 LWIP_ASSERT(
"tcp_write: extension of reference requires reference",
724 last_unsent != NULL && last_unsent->p != NULL);
725 for (p = last_unsent->p; p->
next != NULL; p = p->
next) {
730 last_unsent->len += extendlen;
733 #if TCP_CHECKSUM_ON_COPY 734 if (concat_chksummed) {
735 LWIP_ASSERT(
"tcp_write: concat checksum needs concatenated data",
736 concat_p != NULL || extendlen > 0);
738 if (concat_chksum_swapped) {
741 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
742 &last_unsent->chksum_swapped);
743 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
751 if (last_unsent == NULL) {
754 last_unsent->next = queue;
762 pcb->snd_queuelen = queuelen;
766 if (pcb->snd_queuelen != 0) {
767 LWIP_ASSERT(
"tcp_write: valid queue length",
768 pcb->unacked != NULL || pcb->unsent != NULL);
772 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
773 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
778 pcb->flags |= TF_NAGLEMEMERR;
779 TCP_STATS_INC(tcp.memerr);
781 if (concat_p != NULL) {
785 tcp_segs_free(queue);
787 if (pcb->snd_queuelen != 0) {
788 LWIP_ASSERT(
"tcp_write: valid queue length", pcb->unacked != NULL ||
789 pcb->unsent != NULL);
804 tcp_enqueue_flags(
struct tcp_pcb *pcb, u8_t flags)
813 LWIP_ASSERT(
"tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
814 (flags & (TCP_SYN | TCP_FIN)) != 0);
817 if (((pcb->snd_queuelen >=
TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
818 ((flags & TCP_FIN) == 0)) {
821 TCP_STATS_INC(tcp.memerr);
822 pcb->flags |= TF_NAGLEMEMERR;
826 if (flags & TCP_SYN) {
827 optflags = TF_SEG_OPTS_MSS;
829 if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
832 optflags |= TF_SEG_OPTS_WND_SCALE;
836 #if LWIP_TCP_TIMESTAMPS 837 if ((pcb->flags & TF_TIMESTAMP)) {
840 optflags |= TF_SEG_OPTS_TS;
843 optlen = LWIP_TCP_OPT_LENGTH(optflags);
847 pcb->flags |= TF_NAGLEMEMERR;
848 TCP_STATS_INC(tcp.memerr);
851 LWIP_ASSERT(
"tcp_enqueue_flags: check that first pbuf can hold optlen",
855 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
856 pcb->flags |= TF_NAGLEMEMERR;
857 TCP_STATS_INC(tcp.memerr);
860 LWIP_ASSERT(
"seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0);
861 LWIP_ASSERT(
"tcp_enqueue_flags: invalid segment length", seg->len == 0);
864 (
"tcp_enqueue_flags: queueing %"U32_F
":%"U32_F
" (0x%"X16_F
")\n",
865 lwip_ntohl(seg->tcphdr->seqno),
866 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
870 if (pcb->unsent == NULL) {
873 struct tcp_seg *useg;
874 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
879 pcb->unsent_oversize = 0;
883 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
887 if (flags & TCP_FIN) {
888 pcb->flags |= TF_FIN;
894 if (pcb->snd_queuelen != 0) {
895 LWIP_ASSERT(
"tcp_enqueue_flags: invalid queue length",
896 pcb->unacked != NULL || pcb->unsent != NULL);
902 #if LWIP_TCP_TIMESTAMPS 909 tcp_build_timestamp_option(
struct tcp_pcb *pcb, u32_t *opts)
912 opts[0] = PP_HTONL(0x0101080A);
913 opts[1] = lwip_htonl(
sys_now());
914 opts[2] = lwip_htonl(pcb->ts_recent);
924 tcp_build_wnd_scale_option(u32_t *opts)
927 opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE);
937 tcp_send_empty_ack(
struct tcp_pcb *pcb)
943 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 947 #if LWIP_TCP_TIMESTAMPS 948 if (pcb->flags & TF_TIMESTAMP) {
949 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
953 p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
956 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
960 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP 964 (
"tcp_output: sending ACK for %"U32_F
"\n", pcb->rcv_nxt));
967 #if LWIP_TCP_TIMESTAMPS 968 pcb->ts_lastacksent = pcb->rcv_nxt;
970 if (pcb->flags & TF_TIMESTAMP) {
971 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
975 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
980 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
981 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->
tot_len,
982 &pcb->local_ip, &pcb->remote_ip);
985 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
986 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip,
987 pcb->ttl, pcb->tos, IP_PROTO_TCP, netif);
988 NETIF_SET_HWADDRHINT(netif, NULL);
994 pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
997 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
1012 tcp_output(
struct tcp_pcb *pcb)
1014 struct tcp_seg *seg, *useg;
1017 struct netif *netif;
1023 LWIP_ASSERT(
"don't call tcp_output for listen-pcbs",
1024 pcb->state != LISTEN);
1030 if (tcp_input_pcb == pcb) {
1034 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
1044 if (pcb->flags & TF_ACK_NOW &&
1046 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
1047 return tcp_send_empty_ack(pcb);
1051 useg = pcb->unacked;
1053 for (; useg->next != NULL; useg = useg->next);
1056 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1057 if (netif == NULL) {
1062 if (ip_addr_isany(&pcb->local_ip)) {
1063 const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip);
1064 if (local_ip == NULL) {
1067 ip_addr_copy(pcb->local_ip, *local_ip);
1070 #if TCP_OUTPUT_DEBUG 1073 (
void*)pcb->unsent));
1079 ", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1080 ", seg == NULL, ack %"U32_F
"\n",
1081 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
1084 (
"tcp_output: snd_wnd %"TCPWNDSIZE_F
", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
1085 ", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
"\n",
1086 pcb->snd_wnd, pcb->cwnd, wnd,
1087 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
1088 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
1100 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
1101 wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
1103 if (pcb->persist_backoff == 0) {
1104 pcb->persist_cnt = 0;
1105 pcb->persist_backoff = 1;
1110 while (seg != NULL &&
1111 lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
1112 LWIP_ASSERT(
"RST not expected here!",
1113 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
1121 if ((tcp_do_output_nagle(pcb) == 0) &&
1122 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
1126 LWIP_DEBUGF(
TCP_CWND_DEBUG, (
"tcp_output: snd_wnd %"TCPWNDSIZE_F
", cwnd %"TCPWNDSIZE_F
", wnd %"U32_F
", effwnd %"U32_F
", seq %"U32_F
", ack %"U32_F
", i %"S16_F
"\n",
1127 pcb->snd_wnd, pcb->cwnd, wnd,
1128 lwip_ntohl(seg->tcphdr->seqno) + seg->len -
1130 lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
1134 if (pcb->state != SYN_SENT) {
1135 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
1138 #if TCP_OVERSIZE_DBGCHECK 1139 seg->oversize_left = 0;
1141 err = tcp_output_segment(seg, pcb, netif);
1144 pcb->flags |= TF_NAGLEMEMERR;
1147 pcb->unsent = seg->next;
1148 if (pcb->state != SYN_SENT) {
1149 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
1151 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
1152 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
1153 pcb->snd_nxt = snd_nxt;
1156 if (TCP_TCPLEN(seg) > 0) {
1159 if (pcb->unacked == NULL) {
1167 if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
1169 struct tcp_seg **cur_seg = &(pcb->unacked);
1171 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1172 cur_seg = &((*cur_seg)->next );
1174 seg->next = (*cur_seg);
1190 if (pcb->unsent == NULL) {
1192 pcb->unsent_oversize = 0;
1196 pcb->flags &= ~TF_NAGLEMEMERR;
1208 tcp_output_segment(
struct tcp_seg *seg,
struct tcp_pcb *pcb,
struct netif *netif)
1214 if (seg->p->ref != 1) {
1223 seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
1227 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1230 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
1234 seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
1237 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1242 opts = (u32_t *)(
void *)(seg->tcphdr + 1);
1243 if (seg->flags & TF_SEG_OPTS_MSS) {
1245 #if TCP_CALCULATE_EFF_SEND_MSS 1246 mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip);
1250 *opts = TCP_BUILD_MSS_OPTION(mss);
1253 #if LWIP_TCP_TIMESTAMPS 1254 pcb->ts_lastacksent = pcb->rcv_nxt;
1256 if (seg->flags & TF_SEG_OPTS_TS) {
1257 tcp_build_timestamp_option(pcb, opts);
1262 if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
1263 tcp_build_wnd_scale_option(opts);
1270 if (pcb->rtime < 0) {
1274 if (pcb->rttest == 0) {
1275 pcb->rttest = tcp_ticks;
1276 pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);
1281 lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
1284 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
1287 MIB2_STATS_INC(mib2.tcpoutsegs);
1291 seg->p->tot_len -= len;
1293 seg->p->payload = seg->tcphdr;
1295 seg->tcphdr->chksum = 0;
1296 #if CHECKSUM_GEN_TCP 1297 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1298 #if TCP_CHECKSUM_ON_COPY 1300 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1301 u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1302 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1304 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
1305 LWIP_ASSERT(
"data included but not checksummed",
1306 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
1310 acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP,
1311 seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
1313 if (seg->chksum_swapped) {
1315 seg->chksum_swapped = 0;
1317 acc += (u16_t)~(seg->chksum);
1319 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1320 if (chksum_slow != seg->tcphdr->chksum) {
1321 TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(
1322 (
"tcp_output_segment: calculated checksum is %"X16_F
" instead of %"X16_F
"\n",
1323 seg->tcphdr->chksum, chksum_slow));
1324 seg->tcphdr->chksum = chksum_slow;
1328 seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
1329 seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
1333 TCP_STATS_INC(tcp.xmit);
1335 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1336 err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1337 pcb->tos, IP_PROTO_TCP, netif);
1338 NETIF_SET_HWADDRHINT(netif, NULL);
1363 tcp_rst(u32_t seqno, u32_t ackno,
1364 const ip_addr_t *local_ip,
const ip_addr_t *remote_ip,
1365 u16_t local_port, u16_t remote_port)
1369 struct netif *netif;
1375 LWIP_ASSERT(
"check that first pbuf can hold struct tcp_hdr",
1379 tcphdr->src = lwip_htons(local_port);
1380 tcphdr->dest = lwip_htons(remote_port);
1381 tcphdr->seqno = lwip_htonl(seqno);
1382 tcphdr->ackno = lwip_htonl(ackno);
1383 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
1385 tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
1387 tcphdr->wnd = PP_HTONS(TCP_WND);
1392 TCP_STATS_INC(tcp.xmit);
1393 MIB2_STATS_INC(mib2.tcpoutrsts);
1395 netif = ip_route(local_ip, remote_ip);
1396 if (netif != NULL) {
1397 #if CHECKSUM_GEN_TCP 1398 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1399 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->
tot_len,
1400 local_ip, remote_ip);
1404 ip_output_if(p, local_ip, remote_ip,
TCP_TTL, 0, IP_PROTO_TCP, netif);
1418 tcp_rexmit_rto(
struct tcp_pcb *pcb)
1420 struct tcp_seg *seg;
1422 if (pcb->unacked == NULL) {
1427 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
1429 seg->next = pcb->unsent;
1430 #if TCP_OVERSIZE_DBGCHECK 1432 if (pcb->unsent == NULL) {
1433 pcb->unsent_oversize = seg->oversize_left;
1437 pcb->unsent = pcb->unacked;
1439 pcb->unacked = NULL;
1442 if (pcb->nrtx < 0xFF) {
1461 tcp_rexmit(
struct tcp_pcb *pcb)
1463 struct tcp_seg *seg;
1464 struct tcp_seg **cur_seg;
1466 if (pcb->unacked == NULL) {
1473 pcb->unacked = seg->next;
1475 cur_seg = &(pcb->unsent);
1477 TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
1478 cur_seg = &((*cur_seg)->next );
1480 seg->next = *cur_seg;
1483 if (seg->next == NULL) {
1485 pcb->unsent_oversize = 0;
1489 if (pcb->nrtx < 0xFF) {
1497 MIB2_STATS_INC(mib2.tcpretranssegs);
1509 tcp_rexmit_fast(
struct tcp_pcb *pcb)
1511 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
1514 (
"tcp_receive: dupacks %"U16_F
" (%"U32_F
1515 "), fast retransmit %"U32_F
"\n",
1516 (u16_t)pcb->dupacks, pcb->lastack,
1517 lwip_ntohl(pcb->unacked->tcphdr->seqno)));
1522 pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
1525 if (pcb->ssthresh < (2U * pcb->mss)) {
1527 (
"tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F
1528 " should be min 2 mss %"U16_F
"...\n",
1529 pcb->ssthresh, (u16_t)(2*pcb->mss)));
1530 pcb->ssthresh = 2*pcb->mss;
1533 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1534 pcb->flags |= TF_INFR;
1551 tcp_keepalive(
struct tcp_pcb *pcb)
1555 struct netif *netif;
1558 ip_addr_debug_print(
TCP_DEBUG, &pcb->remote_ip);
1561 LWIP_DEBUGF(
TCP_DEBUG, (
"tcp_keepalive: tcp_ticks %"U32_F
" pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1562 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
1564 p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1));
1567 (
"tcp_keepalive: could not allocate memory for pbuf\n"));
1570 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1571 if (netif == NULL) {
1574 #if CHECKSUM_GEN_TCP 1575 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1577 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->
tot_len,
1578 &pcb->local_ip, &pcb->remote_ip);
1581 TCP_STATS_INC(tcp.xmit);
1584 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1585 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif);
1586 NETIF_SET_HWADDRHINT(netif, NULL);
1591 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
1605 tcp_zero_window_probe(
struct tcp_pcb *pcb)
1610 struct tcp_seg *seg;
1614 struct netif *netif;
1617 ip_addr_debug_print(
TCP_DEBUG, &pcb->remote_ip);
1621 (
"tcp_zero_window_probe: tcp_ticks %"U32_F
1622 " pcb->tmr %"U32_F
" pcb->keep_cnt_sent %"U16_F
"\n",
1623 tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
1635 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1637 len = is_fin ? 0 : 1;
1639 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1648 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1651 char *d = ((
char *)p->
payload + TCP_HLEN);
1659 snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
1660 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
1661 pcb->snd_nxt = snd_nxt;
1664 netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
1665 if (netif == NULL) {
1668 #if CHECKSUM_GEN_TCP 1669 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
1670 tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->
tot_len,
1671 &pcb->local_ip, &pcb->remote_ip);
1674 TCP_STATS_INC(tcp.xmit);
1677 NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
1678 err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
1679 0, IP_PROTO_TCP, netif);
1680 NETIF_SET_HWADDRHINT(netif, NULL);
1686 " ackno %"U32_F
" err %d.\n",
1687 pcb->snd_nxt - 1, pcb->rcv_nxt, (
int)err));
u16_t pbuf_clen(const struct pbuf *p)
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
#define LWIP_DBG_LEVEL_SERIOUS
#define SWAP_BYTES_IN_WORD(w)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
#define LWIP_DEBUGF(debug, message)
#define LWIP_MEM_ALIGN_SIZE(size)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define LWIP_UNUSED_ARG(x)
u8_t pbuf_free(struct pbuf *p)
#define LWIP_DBG_LEVEL_SEVERE
void * memp_malloc(memp_t type)