00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "lwip/opt.h"
00042
00043 #if LWIP_TCP
00044
00045 #include "lwip/tcp_impl.h"
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/memp.h"
00049 #include "lwip/ip_addr.h"
00050 #include "lwip/netif.h"
00051 #include "lwip/inet_chksum.h"
00052 #include "lwip/stats.h"
00053 #include "lwip/snmp.h"
00054 #if LWIP_TCP_TIMESTAMPS
00055 #include "lwip/sys.h"
00056 #endif
00057
00058 #include <string.h>
00059
00060
00061
00062 #if TCP_CHECKSUM_ON_COPY
00063 #define TCP_DATA_COPY(dst, src, len, seg) do { \
00064 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
00065 len, &seg->chksum, &seg->chksum_swapped); \
00066 seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
00067 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \
00068 tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
00069 #else
00070 #define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len)
00071 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
00072 #endif
00073
00074
00075
00076 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
00077 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0
00078 #endif
00079
00080
00081 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 static struct pbuf *
00094 tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
00095 u32_t seqno_be )
00096 {
00097 struct tcp_hdr *tcphdr;
00098 struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM);
00099 if (p != NULL) {
00100 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00101 (p->len >= TCP_HLEN + optlen));
00102 tcphdr = (struct tcp_hdr *)p->payload;
00103 tcphdr->src = htons(pcb->local_port);
00104 tcphdr->dest = htons(pcb->remote_port);
00105 tcphdr->seqno = seqno_be;
00106 tcphdr->ackno = htonl(pcb->rcv_nxt);
00107 TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
00108 tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00109 tcphdr->chksum = 0;
00110 tcphdr->urgp = 0;
00111
00112
00113 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00114 }
00115 return p;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124 err_t
00125 tcp_send_fin(struct tcp_pcb *pcb)
00126 {
00127
00128 if (pcb->unsent != NULL) {
00129 struct tcp_seg *last_unsent;
00130 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
00131 last_unsent = last_unsent->next);
00132
00133 if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
00134
00135 TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
00136 pcb->flags |= TF_FIN;
00137 return ERR_OK;
00138 }
00139 }
00140
00141 return tcp_enqueue_flags(pcb, TCP_FIN);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static struct tcp_seg *
00159 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
00160 {
00161 struct tcp_seg *seg;
00162 u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
00163
00164 if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
00165 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n"));
00166 pbuf_free(p);
00167 return NULL;
00168 }
00169 seg->flags = optflags;
00170 seg->next = NULL;
00171 seg->p = p;
00172 seg->len = p->tot_len - optlen;
00173 #if TCP_OVERSIZE_DBGCHECK
00174 seg->oversize_left = 0;
00175 #endif
00176 #if TCP_CHECKSUM_ON_COPY
00177 seg->chksum = 0;
00178 seg->chksum_swapped = 0;
00179
00180 LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
00181 (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
00182 #endif
00183
00184
00185 if (pbuf_header(p, TCP_HLEN)) {
00186 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n"));
00187 TCP_STATS_INC(tcp.err);
00188 tcp_seg_free(seg);
00189 return NULL;
00190 }
00191 seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
00192 seg->tcphdr->src = htons(pcb->local_port);
00193 seg->tcphdr->dest = htons(pcb->remote_port);
00194 seg->tcphdr->seqno = htonl(seqno);
00195
00196 TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
00197
00198 seg->tcphdr->urgp = 0;
00199 return seg;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 #if TCP_OVERSIZE
00218 static struct pbuf *
00219 tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
00220 u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags,
00221 u8_t first_seg)
00222 {
00223 struct pbuf *p;
00224 u16_t alloc = length;
00225
00226 #if LWIP_NETIF_TX_SINGLE_PBUF
00227 LWIP_UNUSED_ARG(max_length);
00228 LWIP_UNUSED_ARG(pcb);
00229 LWIP_UNUSED_ARG(apiflags);
00230 LWIP_UNUSED_ARG(first_seg);
00231
00232 alloc = max_length;
00233 #else
00234 if (length < max_length) {
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 if ((apiflags & TCP_WRITE_FLAG_MORE) ||
00247 (!(pcb->flags & TF_NODELAY) &&
00248 (!first_seg ||
00249 pcb->unsent != NULL ||
00250 pcb->unacked != NULL))) {
00251 alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE));
00252 }
00253 }
00254 #endif
00255 p = pbuf_alloc(layer, alloc, PBUF_RAM);
00256 if (p == NULL) {
00257 return NULL;
00258 }
00259 LWIP_ASSERT("need unchained pbuf", p->next == NULL);
00260 *oversize = p->len - length;
00261
00262 p->len = p->tot_len = length;
00263 return p;
00264 }
00265 #else
00266 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
00267 #endif
00268
00269 #if TCP_CHECKSUM_ON_COPY
00270
00271 static void
00272 tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum,
00273 u8_t *seg_chksum_swapped)
00274 {
00275 u32_t helper;
00276
00277 helper = chksum + *seg_chksum;
00278 chksum = FOLD_U32T(helper);
00279 if ((len & 1) != 0) {
00280 *seg_chksum_swapped = 1 - *seg_chksum_swapped;
00281 chksum = SWAP_BYTES_IN_WORD(chksum);
00282 }
00283 *seg_chksum = chksum;
00284 }
00285 #endif
00286
00287
00288
00289
00290
00291
00292
00293 static err_t
00294 tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
00295 {
00296
00297 if ((pcb->state != ESTABLISHED) &&
00298 (pcb->state != CLOSE_WAIT) &&
00299 (pcb->state != SYN_SENT) &&
00300 (pcb->state != SYN_RCVD)) {
00301 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
00302 return ERR_CONN;
00303 } else if (len == 0) {
00304 return ERR_OK;
00305 }
00306
00307
00308 if (len > pcb->snd_buf) {
00309 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n",
00310 len, pcb->snd_buf));
00311 pcb->flags |= TF_NAGLEMEMERR;
00312 return ERR_MEM;
00313 }
00314
00315 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00316
00317
00318
00319
00320 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00321 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
00322 pcb->snd_queuelen, TCP_SND_QUEUELEN));
00323 TCP_STATS_INC(tcp.memerr);
00324 pcb->flags |= TF_NAGLEMEMERR;
00325 return ERR_MEM;
00326 }
00327 if (pcb->snd_queuelen != 0) {
00328 LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
00329 pcb->unacked != NULL || pcb->unsent != NULL);
00330 } else {
00331 LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
00332 pcb->unacked == NULL && pcb->unsent == NULL);
00333 }
00334 return ERR_OK;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 err_t
00354 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
00355 {
00356 struct pbuf *concat_p = NULL;
00357 struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
00358 u16_t pos = 0;
00359 u16_t queuelen;
00360 u8_t optlen = 0;
00361 u8_t optflags = 0;
00362 #if TCP_OVERSIZE
00363 u16_t oversize = 0;
00364 u16_t oversize_used = 0;
00365 #endif
00366 #if TCP_CHECKSUM_ON_COPY
00367 u16_t concat_chksum = 0;
00368 u8_t concat_chksum_swapped = 0;
00369 u16_t concat_chksummed = 0;
00370 #endif
00371 err_t err;
00372
00373 u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2);
00374
00375 #if LWIP_NETIF_TX_SINGLE_PBUF
00376
00377 apiflags |= TCP_WRITE_FLAG_COPY;
00378 #endif
00379
00380 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
00381 (void *)pcb, arg, len, (u16_t)apiflags));
00382 LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)",
00383 arg != NULL, return ERR_ARG;);
00384
00385 err = tcp_write_checks(pcb, len);
00386 if (err != ERR_OK) {
00387 return err;
00388 }
00389 queuelen = pcb->snd_queuelen;
00390
00391 #if LWIP_TCP_TIMESTAMPS
00392 if ((pcb->flags & TF_TIMESTAMP)) {
00393 optflags = TF_SEG_OPTS_TS;
00394 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00395 }
00396 #endif
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 if (pcb->unsent != NULL) {
00423 u16_t space;
00424 u16_t unsent_optlen;
00425
00426
00427 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
00428 last_unsent = last_unsent->next);
00429
00430
00431 unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
00432 space = mss_local - (last_unsent->len + unsent_optlen);
00433
00434
00435
00436
00437
00438
00439
00440
00441 #if TCP_OVERSIZE
00442 #if TCP_OVERSIZE_DBGCHECK
00443
00444 LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
00445 pcb->unsent_oversize == last_unsent->oversize_left);
00446 #endif
00447 oversize = pcb->unsent_oversize;
00448 if (oversize > 0) {
00449 LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
00450 seg = last_unsent;
00451 oversize_used = oversize < len ? oversize : len;
00452 pos += oversize_used;
00453 oversize -= oversize_used;
00454 space -= oversize_used;
00455 }
00456
00457 LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
00458 #endif
00459
00460
00461
00462
00463
00464
00465
00466
00467 if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
00468 u16_t seglen = space < len - pos ? space : len - pos;
00469 seg = last_unsent;
00470
00471
00472
00473
00474 if (apiflags & TCP_WRITE_FLAG_COPY) {
00475
00476 if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
00477 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
00478 ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n",
00479 seglen));
00480 goto memerr;
00481 }
00482 #if TCP_OVERSIZE_DBGCHECK
00483 last_unsent->oversize_left += oversize;
00484 #endif
00485 TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
00486 #if TCP_CHECKSUM_ON_COPY
00487 concat_chksummed += seglen;
00488 #endif
00489 } else {
00490
00491 if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
00492 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2,
00493 ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
00494 goto memerr;
00495 }
00496 #if TCP_CHECKSUM_ON_COPY
00497
00498 tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen,
00499 &concat_chksum, &concat_chksum_swapped);
00500 concat_chksummed += seglen;
00501 #endif
00502
00503 concat_p->payload = (u8_t*)arg + pos;
00504 }
00505
00506 pos += seglen;
00507 queuelen += pbuf_clen(concat_p);
00508 }
00509 } else {
00510 #if TCP_OVERSIZE
00511 LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
00512 pcb->unsent_oversize == 0);
00513 #endif
00514 }
00515
00516
00517
00518
00519
00520
00521
00522 while (pos < len) {
00523 struct pbuf *p;
00524 u16_t left = len - pos;
00525 u16_t max_len = mss_local - optlen;
00526 u16_t seglen = left > max_len ? max_len : left;
00527 #if TCP_CHECKSUM_ON_COPY
00528 u16_t chksum = 0;
00529 u8_t chksum_swapped = 0;
00530 #endif
00531
00532 if (apiflags & TCP_WRITE_FLAG_COPY) {
00533
00534
00535 if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
00536 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
00537 goto memerr;
00538 }
00539 LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen",
00540 (p->len >= seglen));
00541 TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
00542 } else {
00543
00544
00545
00546
00547
00548 struct pbuf *p2;
00549 #if TCP_OVERSIZE
00550 LWIP_ASSERT("oversize == 0", oversize == 0);
00551 #endif
00552 if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
00553 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
00554 goto memerr;
00555 }
00556 #if TCP_CHECKSUM_ON_COPY
00557
00558 chksum = ~inet_chksum((u8_t*)arg + pos, seglen);
00559 #endif
00560
00561 p2->payload = (u8_t*)arg + pos;
00562
00563
00564 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00565
00566
00567 pbuf_free(p2);
00568 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n"));
00569 goto memerr;
00570 }
00571
00572 pbuf_cat(p, p2);
00573 }
00574
00575 queuelen += pbuf_clen(p);
00576
00577
00578
00579
00580 if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00581 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00582 pbuf_free(p);
00583 goto memerr;
00584 }
00585
00586 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
00587 goto memerr;
00588 }
00589 #if TCP_OVERSIZE_DBGCHECK
00590 seg->oversize_left = oversize;
00591 #endif
00592 #if TCP_CHECKSUM_ON_COPY
00593 seg->chksum = chksum;
00594 seg->chksum_swapped = chksum_swapped;
00595 seg->flags |= TF_SEG_DATA_CHECKSUMMED;
00596 #endif
00597
00598
00599 if (queue == NULL) {
00600 queue = seg;
00601 } else {
00602
00603 LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL);
00604 prev_seg->next = seg;
00605 }
00606
00607 prev_seg = seg;
00608
00609 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
00610 ntohl(seg->tcphdr->seqno),
00611 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
00612
00613 pos += seglen;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 #if TCP_OVERSIZE
00626 if (oversize_used > 0) {
00627 struct pbuf *p;
00628
00629 for (p = last_unsent->p; p; p = p->next) {
00630 p->tot_len += oversize_used;
00631 if (p->next == NULL) {
00632 TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent);
00633 p->len += oversize_used;
00634 }
00635 }
00636 last_unsent->len += oversize_used;
00637 #if TCP_OVERSIZE_DBGCHECK
00638 LWIP_ASSERT("last_unsent->oversize_left >= oversize_used",
00639 last_unsent->oversize_left >= oversize_used);
00640 last_unsent->oversize_left -= oversize_used;
00641 #endif
00642 }
00643 pcb->unsent_oversize = oversize;
00644 #endif
00645
00646
00647
00648
00649 if (concat_p != NULL) {
00650 LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
00651 (last_unsent != NULL));
00652 pbuf_cat(last_unsent->p, concat_p);
00653 last_unsent->len += concat_p->tot_len;
00654 #if TCP_CHECKSUM_ON_COPY
00655 if (concat_chksummed) {
00656 tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
00657 &last_unsent->chksum_swapped);
00658 last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
00659 }
00660 #endif
00661 }
00662
00663
00664
00665
00666
00667 if (last_unsent == NULL) {
00668 pcb->unsent = queue;
00669 } else {
00670 last_unsent->next = queue;
00671 }
00672
00673
00674
00675
00676 pcb->snd_lbb += len;
00677 pcb->snd_buf -= len;
00678 pcb->snd_queuelen = queuelen;
00679
00680 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
00681 pcb->snd_queuelen));
00682 if (pcb->snd_queuelen != 0) {
00683 LWIP_ASSERT("tcp_write: valid queue length",
00684 pcb->unacked != NULL || pcb->unsent != NULL);
00685 }
00686
00687
00688 if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
00689 TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
00690 }
00691
00692 return ERR_OK;
00693 memerr:
00694 pcb->flags |= TF_NAGLEMEMERR;
00695 TCP_STATS_INC(tcp.memerr);
00696
00697 if (concat_p != NULL) {
00698 pbuf_free(concat_p);
00699 }
00700 if (queue != NULL) {
00701 tcp_segs_free(queue);
00702 }
00703 if (pcb->snd_queuelen != 0) {
00704 LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
00705 pcb->unsent != NULL);
00706 }
00707 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
00708 return ERR_MEM;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 err_t
00722 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
00723 {
00724 struct pbuf *p;
00725 struct tcp_seg *seg;
00726 u8_t optflags = 0;
00727 u8_t optlen = 0;
00728
00729 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00730
00731 LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
00732 (flags & (TCP_SYN | TCP_FIN)) != 0);
00733
00734
00735 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00736 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n",
00737 pcb->snd_queuelen, TCP_SND_QUEUELEN));
00738 TCP_STATS_INC(tcp.memerr);
00739 pcb->flags |= TF_NAGLEMEMERR;
00740 return ERR_MEM;
00741 }
00742
00743 if (flags & TCP_SYN) {
00744 optflags = TF_SEG_OPTS_MSS;
00745 }
00746 #if LWIP_TCP_TIMESTAMPS
00747 if ((pcb->flags & TF_TIMESTAMP)) {
00748 optflags |= TF_SEG_OPTS_TS;
00749 }
00750 #endif
00751 optlen = LWIP_TCP_OPT_LENGTH(optflags);
00752
00753
00754
00755
00756
00757 if (pcb->snd_buf == 0) {
00758 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n"));
00759 TCP_STATS_INC(tcp.memerr);
00760 return ERR_MEM;
00761 }
00762
00763
00764 if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00765 pcb->flags |= TF_NAGLEMEMERR;
00766 TCP_STATS_INC(tcp.memerr);
00767 return ERR_MEM;
00768 }
00769 LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen",
00770 (p->len >= optlen));
00771
00772
00773 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
00774 pcb->flags |= TF_NAGLEMEMERR;
00775 TCP_STATS_INC(tcp.memerr);
00776 return ERR_MEM;
00777 }
00778 LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0);
00779 LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
00780
00781 LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
00782 ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
00783 ntohl(seg->tcphdr->seqno),
00784 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00785 (u16_t)flags));
00786
00787
00788 if (pcb->unsent == NULL) {
00789 pcb->unsent = seg;
00790 } else {
00791 struct tcp_seg *useg;
00792 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00793 useg->next = seg;
00794 }
00795 #if TCP_OVERSIZE
00796
00797 pcb->unsent_oversize = 0;
00798 #endif
00799
00800
00801 if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
00802 pcb->snd_lbb++;
00803
00804 pcb->snd_buf--;
00805 }
00806 if (flags & TCP_FIN) {
00807 pcb->flags |= TF_FIN;
00808 }
00809
00810
00811 pcb->snd_queuelen += pbuf_clen(seg->p);
00812 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
00813 if (pcb->snd_queuelen != 0) {
00814 LWIP_ASSERT("tcp_enqueue_flags: invalid queue length",
00815 pcb->unacked != NULL || pcb->unsent != NULL);
00816 }
00817
00818 return ERR_OK;
00819 }
00820
00821 #if LWIP_TCP_TIMESTAMPS
00822
00823
00824
00825
00826
00827 static void
00828 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
00829 {
00830
00831 opts[0] = PP_HTONL(0x0101080A);
00832 opts[1] = htonl(sys_now());
00833 opts[2] = htonl(pcb->ts_recent);
00834 }
00835 #endif
00836
00837
00838
00839
00840
00841 err_t
00842 tcp_send_empty_ack(struct tcp_pcb *pcb)
00843 {
00844 struct pbuf *p;
00845 struct tcp_hdr *tcphdr;
00846 u8_t optlen = 0;
00847
00848 #if LWIP_TCP_TIMESTAMPS
00849 if (pcb->flags & TF_TIMESTAMP) {
00850 optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00851 }
00852 #endif
00853
00854 p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
00855 if (p == NULL) {
00856 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00857 return ERR_BUF;
00858 }
00859 tcphdr = (struct tcp_hdr *)p->payload;
00860 LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
00861 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
00862
00863 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00864
00865
00866 #if LWIP_TCP_TIMESTAMPS
00867 pcb->ts_lastacksent = pcb->rcv_nxt;
00868
00869 if (pcb->flags & TF_TIMESTAMP) {
00870 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
00871 }
00872 #endif
00873
00874 #if CHECKSUM_GEN_TCP
00875 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
00876 IP_PROTO_TCP, p->tot_len);
00877 #endif
00878 #if LWIP_NETIF_HWADDRHINT
00879 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00880 IP_PROTO_TCP, &(pcb->addr_hint));
00881 #else
00882 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00883 IP_PROTO_TCP);
00884 #endif
00885 pbuf_free(p);
00886
00887 return ERR_OK;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897 err_t
00898 tcp_output(struct tcp_pcb *pcb)
00899 {
00900 struct tcp_seg *seg, *useg;
00901 u32_t wnd, snd_nxt;
00902 #if TCP_CWND_DEBUG
00903 s16_t i = 0;
00904 #endif
00905
00906
00907 LWIP_ASSERT("don't call tcp_output for listen-pcbs",
00908 pcb->state != LISTEN);
00909
00910
00911
00912
00913
00914 if (tcp_input_pcb == pcb) {
00915 return ERR_OK;
00916 }
00917
00918 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
00919
00920 seg = pcb->unsent;
00921
00922
00923
00924
00925
00926
00927
00928 if (pcb->flags & TF_ACK_NOW &&
00929 (seg == NULL ||
00930 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00931 return tcp_send_empty_ack(pcb);
00932 }
00933
00934
00935 useg = pcb->unacked;
00936 if (useg != NULL) {
00937 for (; useg->next != NULL; useg = useg->next);
00938 }
00939
00940 #if TCP_OUTPUT_DEBUG
00941 if (seg == NULL) {
00942 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
00943 (void*)pcb->unsent));
00944 }
00945 #endif
00946 #if TCP_CWND_DEBUG
00947 if (seg == NULL) {
00948 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
00949 ", cwnd %"U16_F", wnd %"U32_F
00950 ", seg == NULL, ack %"U32_F"\n",
00951 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
00952 } else {
00953 LWIP_DEBUGF(TCP_CWND_DEBUG,
00954 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
00955 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
00956 pcb->snd_wnd, pcb->cwnd, wnd,
00957 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
00958 ntohl(seg->tcphdr->seqno), pcb->lastack));
00959 }
00960 #endif
00961
00962 while (seg != NULL &&
00963 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
00964 LWIP_ASSERT("RST not expected here!",
00965 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
00966
00967
00968
00969
00970
00971
00972
00973 if((tcp_do_output_nagle(pcb) == 0) &&
00974 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
00975 break;
00976 }
00977 #if TCP_CWND_DEBUG
00978 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",
00979 pcb->snd_wnd, pcb->cwnd, wnd,
00980 ntohl(seg->tcphdr->seqno) + seg->len -
00981 pcb->lastack,
00982 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
00983 ++i;
00984 #endif
00985
00986 pcb->unsent = seg->next;
00987
00988 if (pcb->state != SYN_SENT) {
00989 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
00990 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00991 }
00992
00993 tcp_output_segment(seg, pcb);
00994 snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
00995 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
00996 pcb->snd_nxt = snd_nxt;
00997 }
00998
00999 if (TCP_TCPLEN(seg) > 0) {
01000 seg->next = NULL;
01001
01002 if (pcb->unacked == NULL) {
01003 pcb->unacked = seg;
01004 useg = seg;
01005
01006 } else {
01007
01008
01009
01010 if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
01011
01012 struct tcp_seg **cur_seg = &(pcb->unacked);
01013 while (*cur_seg &&
01014 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
01015 cur_seg = &((*cur_seg)->next );
01016 }
01017 seg->next = (*cur_seg);
01018 (*cur_seg) = seg;
01019 } else {
01020
01021 useg->next = seg;
01022 useg = useg->next;
01023 }
01024 }
01025
01026 } else {
01027 tcp_seg_free(seg);
01028 }
01029 seg = pcb->unsent;
01030 }
01031 #if TCP_OVERSIZE
01032 if (pcb->unsent == NULL) {
01033
01034 pcb->unsent_oversize = 0;
01035 }
01036 #endif
01037
01038 pcb->flags &= ~TF_NAGLEMEMERR;
01039 return ERR_OK;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 static void
01049 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
01050 {
01051 u16_t len;
01052 struct netif *netif;
01053 u32_t *opts;
01054
01055
01056 snmp_inc_tcpoutsegs();
01057
01058
01059
01060 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
01061
01062
01063 seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
01064
01065 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
01066
01067
01068
01069 opts = (u32_t *)(void *)(seg->tcphdr + 1);
01070 if (seg->flags & TF_SEG_OPTS_MSS) {
01071 u16_t mss;
01072 #if TCP_CALCULATE_EFF_SEND_MSS
01073 mss = tcp_eff_send_mss(TCP_MSS, &pcb->remote_ip);
01074 #else
01075 mss = TCP_MSS;
01076 #endif
01077 *opts = TCP_BUILD_MSS_OPTION(mss);
01078 opts += 1;
01079 }
01080 #if LWIP_TCP_TIMESTAMPS
01081 pcb->ts_lastacksent = pcb->rcv_nxt;
01082
01083 if (seg->flags & TF_SEG_OPTS_TS) {
01084 tcp_build_timestamp_option(pcb, opts);
01085 opts += 3;
01086 }
01087 #endif
01088
01089
01090
01091 if (pcb->rtime == -1) {
01092 pcb->rtime = 0;
01093 }
01094
01095
01096
01097 if (ip_addr_isany(&(pcb->local_ip))) {
01098 netif = ip_route(&(pcb->remote_ip));
01099 if (netif == NULL) {
01100 return;
01101 }
01102 ip_addr_copy(pcb->local_ip, netif->ip_addr);
01103 }
01104
01105 if (pcb->rttest == 0) {
01106 pcb->rttest = tcp_ticks;
01107 pcb->rtseq = ntohl(seg->tcphdr->seqno);
01108
01109 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
01110 }
01111 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
01112 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
01113 seg->len));
01114
01115 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
01116
01117 seg->p->len -= len;
01118 seg->p->tot_len -= len;
01119
01120 seg->p->payload = seg->tcphdr;
01121
01122 seg->tcphdr->chksum = 0;
01123 #if CHECKSUM_GEN_TCP
01124 #if TCP_CHECKSUM_ON_COPY
01125 {
01126 u32_t acc;
01127 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
01128 u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
01129 &(pcb->remote_ip),
01130 IP_PROTO_TCP, seg->p->tot_len);
01131 #endif
01132 if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
01133 LWIP_ASSERT("data included but not checksummed",
01134 seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
01135 }
01136
01137
01138 acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip),
01139 &(pcb->remote_ip),
01140 IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4);
01141
01142 if (seg->chksum_swapped) {
01143 seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
01144 seg->chksum_swapped = 0;
01145 }
01146 acc += (u16_t)~(seg->chksum);
01147 seg->tcphdr->chksum = FOLD_U32T(acc);
01148 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
01149 if (chksum_slow != seg->tcphdr->chksum) {
01150 LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING,
01151 ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n",
01152 seg->tcphdr->chksum, chksum_slow));
01153 seg->tcphdr->chksum = chksum_slow;
01154 }
01155 #endif
01156 }
01157 #else
01158 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
01159 &(pcb->remote_ip),
01160 IP_PROTO_TCP, seg->p->tot_len);
01161 #endif
01162 #endif
01163 TCP_STATS_INC(tcp.xmit);
01164
01165 #if LWIP_NETIF_HWADDRHINT
01166 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
01167 IP_PROTO_TCP, &(pcb->addr_hint));
01168 #else
01169 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
01170 IP_PROTO_TCP);
01171 #endif
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 void
01195 tcp_rst(u32_t seqno, u32_t ackno,
01196 ip_addr_t *local_ip, ip_addr_t *remote_ip,
01197 u16_t local_port, u16_t remote_port)
01198 {
01199 struct pbuf *p;
01200 struct tcp_hdr *tcphdr;
01201 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
01202 if (p == NULL) {
01203 LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
01204 return;
01205 }
01206 LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
01207 (p->len >= sizeof(struct tcp_hdr)));
01208
01209 tcphdr = (struct tcp_hdr *)p->payload;
01210 tcphdr->src = htons(local_port);
01211 tcphdr->dest = htons(remote_port);
01212 tcphdr->seqno = htonl(seqno);
01213 tcphdr->ackno = htonl(ackno);
01214 TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
01215 tcphdr->wnd = PP_HTONS(TCP_WND);
01216 tcphdr->chksum = 0;
01217 tcphdr->urgp = 0;
01218
01219 #if CHECKSUM_GEN_TCP
01220 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
01221 IP_PROTO_TCP, p->tot_len);
01222 #endif
01223 TCP_STATS_INC(tcp.xmit);
01224 snmp_inc_tcpoutrsts();
01225
01226 ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
01227 pbuf_free(p);
01228 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238 void
01239 tcp_rexmit_rto(struct tcp_pcb *pcb)
01240 {
01241 struct tcp_seg *seg;
01242
01243 if (pcb->unacked == NULL) {
01244 return;
01245 }
01246
01247
01248 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
01249
01250 seg->next = pcb->unsent;
01251
01252 pcb->unsent = pcb->unacked;
01253
01254 pcb->unacked = NULL;
01255
01256
01257
01258 ++pcb->nrtx;
01259
01260
01261 pcb->rttest = 0;
01262
01263
01264 tcp_output(pcb);
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274 void
01275 tcp_rexmit(struct tcp_pcb *pcb)
01276 {
01277 struct tcp_seg *seg;
01278 struct tcp_seg **cur_seg;
01279
01280 if (pcb->unacked == NULL) {
01281 return;
01282 }
01283
01284
01285
01286 seg = pcb->unacked;
01287 pcb->unacked = seg->next;
01288
01289 cur_seg = &(pcb->unsent);
01290 while (*cur_seg &&
01291 TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
01292 cur_seg = &((*cur_seg)->next );
01293 }
01294 seg->next = *cur_seg;
01295 *cur_seg = seg;
01296 #if TCP_OVERSIZE
01297 if (seg->next == NULL) {
01298
01299 pcb->unsent_oversize = 0;
01300 }
01301 #endif
01302
01303 ++pcb->nrtx;
01304
01305
01306 pcb->rttest = 0;
01307
01308
01309 snmp_inc_tcpretranssegs();
01310
01311
01312 }
01313
01314
01315
01316
01317
01318
01319
01320 void
01321 tcp_rexmit_fast(struct tcp_pcb *pcb)
01322 {
01323 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
01324
01325 LWIP_DEBUGF(TCP_FR_DEBUG,
01326 ("tcp_receive: dupacks %"U16_F" (%"U32_F
01327 "), fast retransmit %"U32_F"\n",
01328 (u16_t)pcb->dupacks, pcb->lastack,
01329 ntohl(pcb->unacked->tcphdr->seqno)));
01330 tcp_rexmit(pcb);
01331
01332
01333
01334 if (pcb->cwnd > pcb->snd_wnd) {
01335 pcb->ssthresh = pcb->snd_wnd / 2;
01336 } else {
01337 pcb->ssthresh = pcb->cwnd / 2;
01338 }
01339
01340
01341 if (pcb->ssthresh < 2*pcb->mss) {
01342 LWIP_DEBUGF(TCP_FR_DEBUG,
01343 ("tcp_receive: The minimum value for ssthresh %"U16_F
01344 " should be min 2 mss %"U16_F"...\n",
01345 pcb->ssthresh, 2*pcb->mss));
01346 pcb->ssthresh = 2*pcb->mss;
01347 }
01348
01349 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
01350 pcb->flags |= TF_INFR;
01351 }
01352 }
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 void
01364 tcp_keepalive(struct tcp_pcb *pcb)
01365 {
01366 struct pbuf *p;
01367 struct tcp_hdr *tcphdr;
01368
01369 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
01370 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
01371 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
01372
01373 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
01374 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
01375
01376 p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
01377 if(p == NULL) {
01378 LWIP_DEBUGF(TCP_DEBUG,
01379 ("tcp_keepalive: could not allocate memory for pbuf\n"));
01380 return;
01381 }
01382 tcphdr = (struct tcp_hdr *)p->payload;
01383
01384 #if CHECKSUM_GEN_TCP
01385 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
01386 IP_PROTO_TCP, p->tot_len);
01387 #endif
01388 TCP_STATS_INC(tcp.xmit);
01389
01390
01391 #if LWIP_NETIF_HWADDRHINT
01392 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
01393 &(pcb->addr_hint));
01394 #else
01395 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
01396 #endif
01397
01398 pbuf_free(p);
01399
01400 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
01401 pcb->snd_nxt - 1, pcb->rcv_nxt));
01402 }
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 void
01414 tcp_zero_window_probe(struct tcp_pcb *pcb)
01415 {
01416 struct pbuf *p;
01417 struct tcp_hdr *tcphdr;
01418 struct tcp_seg *seg;
01419 u16_t len;
01420 u8_t is_fin;
01421
01422 LWIP_DEBUGF(TCP_DEBUG,
01423 ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
01424 U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
01425 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
01426 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
01427
01428 LWIP_DEBUGF(TCP_DEBUG,
01429 ("tcp_zero_window_probe: tcp_ticks %"U32_F
01430 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
01431 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
01432
01433 seg = pcb->unacked;
01434
01435 if(seg == NULL) {
01436 seg = pcb->unsent;
01437 }
01438 if(seg == NULL) {
01439 return;
01440 }
01441
01442 is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
01443
01444 len = is_fin ? 0 : 1;
01445
01446 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
01447 if(p == NULL) {
01448 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
01449 return;
01450 }
01451 tcphdr = (struct tcp_hdr *)p->payload;
01452
01453 if (is_fin) {
01454
01455 TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
01456 } else {
01457
01458 char *d = ((char *)p->payload + TCP_HLEN);
01459
01460
01461
01462 pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
01463 }
01464
01465 #if CHECKSUM_GEN_TCP
01466 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
01467 IP_PROTO_TCP, p->tot_len);
01468 #endif
01469 TCP_STATS_INC(tcp.xmit);
01470
01471
01472 #if LWIP_NETIF_HWADDRHINT
01473 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
01474 &(pcb->addr_hint));
01475 #else
01476 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
01477 #endif
01478
01479 pbuf_free(p);
01480
01481 LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
01482 " ackno %"U32_F".\n",
01483 pcb->snd_nxt - 1, pcb->rcv_nxt));
01484 }
01485 #endif