ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_tcp_out.c Source File

lwip_tcp_out.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Transmission Control Protocol, outgoing traffic
00004  *
00005  * The output functions of TCP.
00006  *
00007  */
00008 
00009 /*
00010  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  * 3. The name of the author may not be used to endorse or promote products
00022  *    derived from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00025  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00027  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00029  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00032  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00033  * OF SUCH DAMAGE.
00034  *
00035  * This file is part of the lwIP TCP/IP stack.
00036  *
00037  * Author: Adam Dunkels <adam@sics.se>
00038  *
00039  */
00040 
00041 #include "lwip/opt.h"
00042 
00043 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
00044 
00045 #include "lwip/priv/tcp_priv.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/ip6.h"
00054 #include "lwip/ip6_addr.h"
00055 #include "lwip/inet_chksum.h"
00056 #if LWIP_TCP_TIMESTAMPS
00057 #include "lwip/sys.h"
00058 #endif
00059 
00060 #include <string.h>
00061 
00062 /* Define some copy-macros for checksum-on-copy so that the code looks
00063    nicer by preventing too many ifdef's. */
00064 #if TCP_CHECKSUM_ON_COPY
00065 #define TCP_DATA_COPY(dst, src, len, seg) do { \
00066   tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \
00067                      len, &seg->chksum, &seg->chksum_swapped); \
00068   seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0)
00069 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped)  \
00070   tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped);
00071 #else /* TCP_CHECKSUM_ON_COPY*/
00072 #define TCP_DATA_COPY(dst, src, len, seg)                     MEMCPY(dst, src, len)
00073 #define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len)
00074 #endif /* TCP_CHECKSUM_ON_COPY*/
00075 
00076 /** Define this to 1 for an extra check that the output checksum is valid
00077  * (usefule when the checksum is generated by the application, not the stack) */
00078 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK
00079 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK   0
00080 #endif
00081 /* Allow to override the failure of sanity check from warning to e.g. hard failure */
00082 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
00083 #ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL
00084 #define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg)
00085 #endif
00086 #endif
00087 
00088 #if TCP_OVERSIZE
00089 /** The size of segment pbufs created when TCP_OVERSIZE is enabled */
00090 #ifndef TCP_OVERSIZE_CALC_LENGTH
00091 #define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE)
00092 #endif
00093 #endif
00094 
00095 /* Forward declarations.*/
00096 static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif);
00097 
00098 /** Allocate a pbuf and create a tcphdr at p->payload, used for output
00099  * functions other than the default tcp_output -> tcp_output_segment
00100  * (e.g. tcp_send_empty_ack, etc.)
00101  *
00102  * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr)
00103  * @param optlen length of header-options
00104  * @param datalen length of tcp data to reserve in pbuf
00105  * @param seqno_be seqno in network byte order (big-endian)
00106  * @return pbuf with p->payload being the tcp_hdr
00107  */
00108 static struct pbuf *
00109 tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
00110                       u32_t seqno_be /* already in network byte order */)
00111 {
00112   struct tcp_hdr *tcphdr;
00113   struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM);
00114   if (p != NULL) {
00115     LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00116                  (p->len >= TCP_HLEN + optlen));
00117     tcphdr = (struct tcp_hdr *)p->payload;
00118     tcphdr->src = htons(pcb->local_port);
00119     tcphdr->dest = htons(pcb->remote_port);
00120     tcphdr->seqno = seqno_be;
00121     tcphdr->ackno = htonl(pcb->rcv_nxt);
00122     TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
00123     tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
00124     tcphdr->chksum = 0;
00125     tcphdr->urgp = 0;
00126 
00127     /* If we're sending a packet, update the announced right window edge */
00128     pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00129   }
00130   return p;
00131 }
00132 
00133 /**
00134  * Called by tcp_close() to send a segment including FIN flag but not data.
00135  *
00136  * @param pcb the tcp_pcb over which to send a segment
00137  * @return ERR_OK if sent, another err_t otherwise
00138  */
00139 err_t
00140 tcp_send_fin(struct tcp_pcb *pcb)
00141 {
00142   /* first, try to add the fin to the last unsent segment */
00143   if (pcb->unsent != NULL) {
00144     struct tcp_seg *last_unsent;
00145     for (last_unsent = pcb->unsent; last_unsent->next != NULL;
00146          last_unsent = last_unsent->next);
00147 
00148     if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
00149       /* no SYN/FIN/RST flag in the header, we can add the FIN flag */
00150       TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN);
00151       pcb->flags |= TF_FIN;
00152       return ERR_OK;
00153     }
00154   }
00155   /* no data, no length, flags, copy=1, no optdata */
00156   return tcp_enqueue_flags(pcb, TCP_FIN);
00157 }
00158 
00159 /**
00160  * Create a TCP segment with prefilled header.
00161  *
00162  * Called by tcp_write and tcp_enqueue_flags.
00163  *
00164  * @param pcb Protocol control block for the TCP connection.
00165  * @param p pbuf that is used to hold the TCP header.
00166  * @param flags TCP flags for header.
00167  * @param seqno TCP sequence number of this packet
00168  * @param optflags options to include in TCP header
00169  * @return a new tcp_seg pointing to p, or NULL.
00170  * The TCP header is filled in except ackno and wnd.
00171  * p is freed on failure.
00172  */
00173 static struct tcp_seg *
00174 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
00175 {
00176   struct tcp_seg *seg;
00177   u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
00178 
00179   if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
00180     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n"));
00181     pbuf_free(p);
00182     return NULL;
00183   }
00184   seg->flags = optflags;
00185   seg->next = NULL;
00186   seg->p = p;
00187   LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen);
00188   seg->len = p->tot_len - optlen;
00189 #if TCP_OVERSIZE_DBGCHECK
00190   seg->oversize_left = 0;
00191 #endif /* TCP_OVERSIZE_DBGCHECK */
00192 #if TCP_CHECKSUM_ON_COPY
00193   seg->chksum = 0;
00194   seg->chksum_swapped = 0;
00195   /* check optflags */
00196   LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED",
00197               (optflags & TF_SEG_DATA_CHECKSUMMED) == 0);
00198 #endif /* TCP_CHECKSUM_ON_COPY */
00199 
00200   /* build TCP header */
00201   if (pbuf_header(p, TCP_HLEN)) {
00202     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n"));
00203     TCP_STATS_INC(tcp.err);
00204     tcp_seg_free(seg);
00205     return NULL;
00206   }
00207   seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
00208   seg->tcphdr->src = htons(pcb->local_port);
00209   seg->tcphdr->dest = htons(pcb->remote_port);
00210   seg->tcphdr->seqno = htonl(seqno);
00211   /* ackno is set in tcp_output */
00212   TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
00213   /* wnd and chksum are set in tcp_output */
00214   seg->tcphdr->urgp = 0;
00215   return seg;
00216 }
00217 
00218 /**
00219  * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end.
00220  *
00221  * This function is like pbuf_alloc(layer, length, PBUF_RAM) except
00222  * there may be extra bytes available at the end.
00223  *
00224  * @param layer flag to define header size.
00225  * @param length size of the pbuf's payload.
00226  * @param max_length maximum usable size of payload+oversize.
00227  * @param oversize pointer to a u16_t that will receive the number of usable tail bytes.
00228  * @param pcb The TCP connection that willo enqueue the pbuf.
00229  * @param apiflags API flags given to tcp_write.
00230  * @param first_seg true when this pbuf will be used in the first enqueued segment.
00231  */
00232 #if TCP_OVERSIZE
00233 static struct pbuf *
00234 tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
00235                   u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags,
00236                   u8_t first_seg)
00237 {
00238   struct pbuf *p;
00239   u16_t alloc = length;
00240 
00241 #if LWIP_NETIF_TX_SINGLE_PBUF
00242   LWIP_UNUSED_ARG(max_length);
00243   LWIP_UNUSED_ARG(pcb);
00244   LWIP_UNUSED_ARG(apiflags);
00245   LWIP_UNUSED_ARG(first_seg);
00246   /* always create MSS-sized pbufs */
00247   alloc = max_length;
00248 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
00249   if (length < max_length) {
00250     /* Should we allocate an oversized pbuf, or just the minimum
00251      * length required? If tcp_write is going to be called again
00252      * before this segment is transmitted, we want the oversized
00253      * buffer. If the segment will be transmitted immediately, we can
00254      * save memory by allocating only length. We use a simple
00255      * heuristic based on the following information:
00256      *
00257      * Did the user set TCP_WRITE_FLAG_MORE?
00258      *
00259      * Will the Nagle algorithm defer transmission of this segment?
00260      */
00261     if ((apiflags & TCP_WRITE_FLAG_MORE) ||
00262         (!(pcb->flags & TF_NODELAY) &&
00263          (!first_seg ||
00264           pcb->unsent != NULL ||
00265           pcb->unacked != NULL))) {
00266       alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length)));
00267     }
00268   }
00269 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
00270   p = pbuf_alloc(layer, alloc, PBUF_RAM);
00271   if (p == NULL) {
00272     return NULL;
00273   }
00274   LWIP_ASSERT("need unchained pbuf", p->next == NULL);
00275   *oversize = p->len - length;
00276   /* trim p->len to the currently used size */
00277   p->len = p->tot_len = length;
00278   return p;
00279 }
00280 #else /* TCP_OVERSIZE */
00281 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
00282 #endif /* TCP_OVERSIZE */
00283 
00284 #if TCP_CHECKSUM_ON_COPY
00285 /** Add a checksum of newly added data to the segment */
00286 static void
00287 tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum,
00288                    u8_t *seg_chksum_swapped)
00289 {
00290   u32_t helper;
00291   /* add chksum to old chksum and fold to u16_t */
00292   helper = chksum + *seg_chksum;
00293   chksum = FOLD_U32T(helper);
00294   if ((len & 1) != 0) {
00295     *seg_chksum_swapped = 1 - *seg_chksum_swapped;
00296     chksum = SWAP_BYTES_IN_WORD(chksum);
00297   }
00298   *seg_chksum = chksum;
00299 }
00300 #endif /* TCP_CHECKSUM_ON_COPY */
00301 
00302 /** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen).
00303  *
00304  * @param pcb the tcp pcb to check for
00305  * @param len length of data to send (checked agains snd_buf)
00306  * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise
00307  */
00308 static err_t
00309 tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
00310 {
00311   /* connection is in invalid state for data transmission? */
00312   if ((pcb->state != ESTABLISHED) &&
00313       (pcb->state != CLOSE_WAIT) &&
00314       (pcb->state != SYN_SENT) &&
00315       (pcb->state != SYN_RCVD)) {
00316     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
00317     return ERR_CONN;
00318   } else if (len == 0) {
00319     return ERR_OK;
00320   }
00321 
00322   /* fail on too much data */
00323   if (len > pcb->snd_buf) {
00324     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n",
00325       len, pcb->snd_buf));
00326     pcb->flags |= TF_NAGLEMEMERR;
00327     return ERR_MEM;
00328   }
00329 
00330   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen));
00331 
00332   /* If total number of pbufs on the unsent/unacked queues exceeds the
00333    * configured maximum, return an error */
00334   /* check for configured max queuelen and possible overflow */
00335   if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00336     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n",
00337       pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN));
00338     TCP_STATS_INC(tcp.memerr);
00339     pcb->flags |= TF_NAGLEMEMERR;
00340     return ERR_MEM;
00341   }
00342   if (pcb->snd_queuelen != 0) {
00343     LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
00344       pcb->unacked != NULL || pcb->unsent != NULL);
00345   } else {
00346     LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
00347       pcb->unacked == NULL && pcb->unsent == NULL);
00348   }
00349   return ERR_OK;
00350 }
00351 
00352 /**
00353  * Write data for sending (but does not send it immediately).
00354  *
00355  * It waits in the expectation of more data being sent soon (as
00356  * it can send them more efficiently by combining them together).
00357  * To prompt the system to send data now, call tcp_output() after
00358  * calling tcp_write().
00359  *
00360  * @param pcb Protocol control block for the TCP connection to enqueue data for.
00361  * @param arg Pointer to the data to be enqueued for sending.
00362  * @param len Data length in bytes
00363  * @param apiflags combination of following flags :
00364  * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
00365  * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent,
00366  * @return ERR_OK if enqueued, another err_t on error
00367  */
00368 err_t
00369 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
00370 {
00371   struct pbuf *concat_p = NULL;
00372   struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
00373   u16_t pos = 0; /* position in 'arg' data */
00374   u16_t queuelen;
00375   u8_t optlen = 0;
00376   u8_t optflags = 0;
00377 #if TCP_OVERSIZE
00378   u16_t oversize = 0;
00379   u16_t oversize_used = 0;
00380 #endif /* TCP_OVERSIZE */
00381 #if TCP_CHECKSUM_ON_COPY
00382   u16_t concat_chksum = 0;
00383   u8_t concat_chksum_swapped = 0;
00384   u16_t concat_chksummed = 0;
00385 #endif /* TCP_CHECKSUM_ON_COPY */
00386   err_t err;
00387   /* don't allocate segments bigger than half the maximum window we ever received */
00388   u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2));
00389   mss_local = mss_local ? mss_local : pcb->mss;
00390 
00391 #if LWIP_NETIF_TX_SINGLE_PBUF
00392   /* Always copy to try to create single pbufs for TX */
00393   apiflags |= TCP_WRITE_FLAG_COPY;
00394 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
00395 
00396   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
00397     (void *)pcb, arg, len, (u16_t)apiflags));
00398   LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)",
00399              arg != NULL, return ERR_ARG;);
00400 
00401   err = tcp_write_checks(pcb, len);
00402   if (err != ERR_OK) {
00403     return err;
00404   }
00405   queuelen = pcb->snd_queuelen;
00406 
00407 #if LWIP_TCP_TIMESTAMPS
00408   if ((pcb->flags & TF_TIMESTAMP)) {
00409     /* Make sure the timestamp option is only included in data segments if we
00410        agreed about it with the remote host. */
00411     optflags = TF_SEG_OPTS_TS;
00412     optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00413     /* ensure that segments can hold at least one data byte... */
00414     mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1);
00415   }
00416 #endif /* LWIP_TCP_TIMESTAMPS */
00417 
00418 
00419   /*
00420    * TCP segmentation is done in three phases with increasing complexity:
00421    *
00422    * 1. Copy data directly into an oversized pbuf.
00423    * 2. Chain a new pbuf to the end of pcb->unsent.
00424    * 3. Create new segments.
00425    *
00426    * We may run out of memory at any point. In that case we must
00427    * return ERR_MEM and not change anything in pcb. Therefore, all
00428    * changes are recorded in local variables and committed at the end
00429    * of the function. Some pcb fields are maintained in local copies:
00430    *
00431    * queuelen = pcb->snd_queuelen
00432    * oversize = pcb->unsent_oversize
00433    *
00434    * These variables are set consistently by the phases:
00435    *
00436    * seg points to the last segment tampered with.
00437    *
00438    * pos records progress as data is segmented.
00439    */
00440 
00441   /* Find the tail of the unsent queue. */
00442   if (pcb->unsent != NULL) {
00443     u16_t space;
00444     u16_t unsent_optlen;
00445 
00446     /* @todo: this could be sped up by keeping last_unsent in the pcb */
00447     for (last_unsent = pcb->unsent; last_unsent->next != NULL;
00448          last_unsent = last_unsent->next);
00449 
00450     /* Usable space at the end of the last unsent segment */
00451     unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags);
00452     LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen);
00453     space = mss_local - (last_unsent->len + unsent_optlen);
00454 
00455     /*
00456      * Phase 1: Copy data directly into an oversized pbuf.
00457      *
00458      * The number of bytes copied is recorded in the oversize_used
00459      * variable. The actual copying is done at the bottom of the
00460      * function.
00461      */
00462 #if TCP_OVERSIZE
00463 #if TCP_OVERSIZE_DBGCHECK
00464     /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
00465     LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
00466                 pcb->unsent_oversize == last_unsent->oversize_left);
00467 #endif /* TCP_OVERSIZE_DBGCHECK */
00468     oversize = pcb->unsent_oversize;
00469     if (oversize > 0) {
00470       LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
00471       seg = last_unsent;
00472       oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
00473       pos += oversize_used;
00474       oversize -= oversize_used;
00475       space -= oversize_used;
00476     }
00477     /* now we are either finished or oversize is zero */
00478     LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
00479 #endif /* TCP_OVERSIZE */
00480 
00481     /*
00482      * Phase 2: Chain a new pbuf to the end of pcb->unsent.
00483      *
00484      * We don't extend segments containing SYN/FIN flags or options
00485      * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
00486      * the end.
00487      */
00488     if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
00489       u16_t seglen = space < len - pos ? space : len - pos;
00490       seg = last_unsent;
00491 
00492       /* Create a pbuf with a copy or reference to seglen bytes. We
00493        * can use PBUF_RAW here since the data appears in the middle of
00494        * a segment. A header will never be prepended. */
00495       if (apiflags & TCP_WRITE_FLAG_COPY) {
00496         /* Data is copied */
00497         if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
00498           LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00499                       ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n",
00500                        seglen));
00501           goto memerr;
00502         }
00503 #if TCP_OVERSIZE_DBGCHECK
00504         last_unsent->oversize_left += oversize;
00505 #endif /* TCP_OVERSIZE_DBGCHECK */
00506         TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
00507 #if TCP_CHECKSUM_ON_COPY
00508         concat_chksummed += seglen;
00509 #endif /* TCP_CHECKSUM_ON_COPY */
00510       } else {
00511         /* Data is not copied */
00512         if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
00513           LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00514                       ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
00515           goto memerr;
00516         }
00517 #if TCP_CHECKSUM_ON_COPY
00518         /* calculate the checksum of nocopy-data */
00519         tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen,
00520           &concat_chksum, &concat_chksum_swapped);
00521         concat_chksummed += seglen;
00522 #endif /* TCP_CHECKSUM_ON_COPY */
00523         /* reference the non-volatile payload data */
00524         ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
00525       }
00526 
00527       pos += seglen;
00528       queuelen += pbuf_clen(concat_p);
00529     }
00530   } else {
00531 #if TCP_OVERSIZE
00532     LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
00533                 pcb->unsent_oversize == 0);
00534 #endif /* TCP_OVERSIZE */
00535   }
00536 
00537   /*
00538    * Phase 3: Create new segments.
00539    *
00540    * The new segments are chained together in the local 'queue'
00541    * variable, ready to be appended to pcb->unsent.
00542    */
00543   while (pos < len) {
00544     struct pbuf *p;
00545     u16_t left = len - pos;
00546     u16_t max_len = mss_local - optlen;
00547     u16_t seglen = left > max_len ? max_len : left;
00548 #if TCP_CHECKSUM_ON_COPY
00549     u16_t chksum = 0;
00550     u8_t chksum_swapped = 0;
00551 #endif /* TCP_CHECKSUM_ON_COPY */
00552 
00553     if (apiflags & TCP_WRITE_FLAG_COPY) {
00554       /* If copy is set, memory should be allocated and data copied
00555        * into pbuf */
00556       if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
00557         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
00558         goto memerr;
00559       }
00560       LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen",
00561                   (p->len >= seglen));
00562       TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped);
00563     } else {
00564       /* Copy is not set: First allocate a pbuf for holding the data.
00565        * Since the referenced data is available at least until it is
00566        * sent out on the link (as it has to be ACKed by the remote
00567        * party) we can safely use PBUF_ROM instead of PBUF_REF here.
00568        */
00569       struct pbuf *p2;
00570 #if TCP_OVERSIZE
00571       LWIP_ASSERT("oversize == 0", oversize == 0);
00572 #endif /* TCP_OVERSIZE */
00573       if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
00574         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
00575         goto memerr;
00576       }
00577 #if TCP_CHECKSUM_ON_COPY
00578       /* calculate the checksum of nocopy-data */
00579       chksum = ~inet_chksum((const u8_t*)arg + pos, seglen);
00580       if (seglen & 1) {
00581         chksum_swapped = 1;
00582         chksum = SWAP_BYTES_IN_WORD(chksum);
00583       }
00584 #endif /* TCP_CHECKSUM_ON_COPY */
00585       /* reference the non-volatile payload data */
00586       ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos;
00587 
00588       /* Second, allocate a pbuf for the headers. */
00589       if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00590         /* If allocation fails, we have to deallocate the data pbuf as
00591          * well. */
00592         pbuf_free(p2);
00593         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n"));
00594         goto memerr;
00595       }
00596       /* Concatenate the headers and data pbufs together. */
00597       pbuf_cat(p/*header*/, p2/*data*/);
00598     }
00599 
00600     queuelen += pbuf_clen(p);
00601 
00602     /* Now that there are more segments queued, we check again if the
00603      * length of the queue exceeds the configured maximum or
00604      * overflows. */
00605     if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00606       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n",
00607         queuelen, (int)TCP_SND_QUEUELEN));
00608       pbuf_free(p);
00609       goto memerr;
00610     }
00611 
00612     if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
00613       goto memerr;
00614     }
00615 #if TCP_OVERSIZE_DBGCHECK
00616     seg->oversize_left = oversize;
00617 #endif /* TCP_OVERSIZE_DBGCHECK */
00618 #if TCP_CHECKSUM_ON_COPY
00619     seg->chksum = chksum;
00620     seg->chksum_swapped = chksum_swapped;
00621     seg->flags |= TF_SEG_DATA_CHECKSUMMED;
00622 #endif /* TCP_CHECKSUM_ON_COPY */
00623 
00624     /* first segment of to-be-queued data? */
00625     if (queue == NULL) {
00626       queue = seg;
00627     } else {
00628       /* Attach the segment to the end of the queued segments */
00629       LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL);
00630       prev_seg->next = seg;
00631     }
00632     /* remember last segment of to-be-queued data for next iteration */
00633     prev_seg = seg;
00634 
00635     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
00636       ntohl(seg->tcphdr->seqno),
00637       ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
00638 
00639     pos += seglen;
00640   }
00641 
00642   /*
00643    * All three segmentation phases were successful. We can commit the
00644    * transaction.
00645    */
00646 
00647   /*
00648    * Phase 1: If data has been added to the preallocated tail of
00649    * last_unsent, we update the length fields of the pbuf chain.
00650    */
00651 #if TCP_OVERSIZE
00652   if (oversize_used > 0) {
00653     struct pbuf *p;
00654     /* Bump tot_len of whole chain, len of tail */
00655     for (p = last_unsent->p; p; p = p->next) {
00656       p->tot_len += oversize_used;
00657       if (p->next == NULL) {
00658         TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent);
00659         p->len += oversize_used;
00660       }
00661     }
00662     last_unsent->len += oversize_used;
00663 #if TCP_OVERSIZE_DBGCHECK
00664     LWIP_ASSERT("last_unsent->oversize_left >= oversize_used",
00665                 last_unsent->oversize_left >= oversize_used);
00666     last_unsent->oversize_left -= oversize_used;
00667 #endif /* TCP_OVERSIZE_DBGCHECK */
00668   }
00669   pcb->unsent_oversize = oversize;
00670 #endif /* TCP_OVERSIZE */
00671 
00672   /*
00673    * Phase 2: concat_p can be concatenated onto last_unsent->p
00674    */
00675   if (concat_p != NULL) {
00676     LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
00677       (last_unsent != NULL));
00678     pbuf_cat(last_unsent->p, concat_p);
00679     last_unsent->len += concat_p->tot_len;
00680 #if TCP_CHECKSUM_ON_COPY
00681     if (concat_chksummed) {
00682       /*if concat checksumm swapped - swap it back */
00683       if (concat_chksum_swapped) {
00684         concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
00685       }
00686       tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
00687         &last_unsent->chksum_swapped);
00688       last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
00689     }
00690 #endif /* TCP_CHECKSUM_ON_COPY */
00691   }
00692 
00693   /*
00694    * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
00695    * is harmless
00696    */
00697   if (last_unsent == NULL) {
00698     pcb->unsent = queue;
00699   } else {
00700     last_unsent->next = queue;
00701   }
00702 
00703   /*
00704    * Finally update the pcb state.
00705    */
00706   pcb->snd_lbb += len;
00707   pcb->snd_buf -= len;
00708   pcb->snd_queuelen = queuelen;
00709 
00710   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
00711     pcb->snd_queuelen));
00712   if (pcb->snd_queuelen != 0) {
00713     LWIP_ASSERT("tcp_write: valid queue length",
00714                 pcb->unacked != NULL || pcb->unsent != NULL);
00715   }
00716 
00717   /* Set the PSH flag in the last segment that we enqueued. */
00718   if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
00719     TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
00720   }
00721 
00722   return ERR_OK;
00723 memerr:
00724   pcb->flags |= TF_NAGLEMEMERR;
00725   TCP_STATS_INC(tcp.memerr);
00726 
00727   if (concat_p != NULL) {
00728     pbuf_free(concat_p);
00729   }
00730   if (queue != NULL) {
00731     tcp_segs_free(queue);
00732   }
00733   if (pcb->snd_queuelen != 0) {
00734     LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
00735       pcb->unsent != NULL);
00736   }
00737   LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
00738   return ERR_MEM;
00739 }
00740 
00741 /**
00742  * Enqueue TCP options for transmission.
00743  *
00744  * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl().
00745  *
00746  * @param pcb Protocol control block for the TCP connection.
00747  * @param flags TCP header flags to set in the outgoing segment.
00748  */
00749 err_t
00750 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
00751 {
00752   struct pbuf *p;
00753   struct tcp_seg *seg;
00754   u8_t optflags = 0;
00755   u8_t optlen = 0;
00756 
00757   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00758 
00759   LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)",
00760               (flags & (TCP_SYN | TCP_FIN)) != 0);
00761 
00762   /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */
00763   if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) &&
00764       ((flags & TCP_FIN) == 0)) {
00765     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n",
00766                                        pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN));
00767     TCP_STATS_INC(tcp.memerr);
00768     pcb->flags |= TF_NAGLEMEMERR;
00769     return ERR_MEM;
00770   }
00771 
00772   if (flags & TCP_SYN) {
00773     optflags = TF_SEG_OPTS_MSS;
00774 #if LWIP_WND_SCALE
00775     if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) {
00776       /* In a <SYN,ACK> (sent in state SYN_RCVD), the window scale option may only
00777          be sent if we received a window scale option from the remote host. */
00778       optflags |= TF_SEG_OPTS_WND_SCALE;
00779     }
00780 #endif /* LWIP_WND_SCALE */
00781   }
00782 #if LWIP_TCP_TIMESTAMPS
00783   if ((pcb->flags & TF_TIMESTAMP)) {
00784     /* Make sure the timestamp option is only included in data segments if we
00785        agreed about it with the remote host. */
00786     optflags |= TF_SEG_OPTS_TS;
00787   }
00788 #endif /* LWIP_TCP_TIMESTAMPS */
00789   optlen = LWIP_TCP_OPT_LENGTH(optflags);
00790 
00791   /* Allocate pbuf with room for TCP header + options */
00792   if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00793     pcb->flags |= TF_NAGLEMEMERR;
00794     TCP_STATS_INC(tcp.memerr);
00795     return ERR_MEM;
00796   }
00797   LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen",
00798               (p->len >= optlen));
00799 
00800   /* Allocate memory for tcp_seg, and fill in fields. */
00801   if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
00802     pcb->flags |= TF_NAGLEMEMERR;
00803     TCP_STATS_INC(tcp.memerr);
00804     return ERR_MEM;
00805   }
00806   LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0);
00807   LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0);
00808 
00809   LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
00810               ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
00811                ntohl(seg->tcphdr->seqno),
00812                ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00813                (u16_t)flags));
00814 
00815   /* Now append seg to pcb->unsent queue */
00816   if (pcb->unsent == NULL) {
00817     pcb->unsent = seg;
00818   } else {
00819     struct tcp_seg *useg;
00820     for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00821     useg->next = seg;
00822   }
00823 #if TCP_OVERSIZE
00824   /* The new unsent tail has no space */
00825   pcb->unsent_oversize = 0;
00826 #endif /* TCP_OVERSIZE */
00827 
00828   /* SYN and FIN bump the sequence number */
00829   if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
00830     pcb->snd_lbb++;
00831     /* optlen does not influence snd_buf */
00832   }
00833   if (flags & TCP_FIN) {
00834     pcb->flags |= TF_FIN;
00835   }
00836 
00837   /* update number of segments on the queues */
00838   pcb->snd_queuelen += pbuf_clen(seg->p);
00839   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
00840   if (pcb->snd_queuelen != 0) {
00841     LWIP_ASSERT("tcp_enqueue_flags: invalid queue length",
00842       pcb->unacked != NULL || pcb->unsent != NULL);
00843   }
00844 
00845   return ERR_OK;
00846 }
00847 
00848 #if LWIP_TCP_TIMESTAMPS
00849 /* Build a timestamp option (12 bytes long) at the specified options pointer)
00850  *
00851  * @param pcb tcp_pcb
00852  * @param opts option pointer where to store the timestamp option
00853  */
00854 static void
00855 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
00856 {
00857   /* Pad with two NOP options to make everything nicely aligned */
00858   opts[0] = PP_HTONL(0x0101080A);
00859   opts[1] = htonl(sys_now());
00860   opts[2] = htonl(pcb->ts_recent);
00861 }
00862 #endif
00863 
00864 #if LWIP_WND_SCALE
00865 /** Build a window scale option (3 bytes long) at the specified options pointer)
00866  *
00867  * @param opts option pointer where to store the window scale option
00868  */
00869 static void
00870 tcp_build_wnd_scale_option(u32_t *opts)
00871 {
00872   /* Pad with one NOP option to make everything nicely aligned */
00873   opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE);
00874 }
00875 #endif
00876 
00877 /** Send an ACK without data.
00878  *
00879  * @param pcb Protocol control block for the TCP connection to send the ACK
00880  */
00881 err_t
00882 tcp_send_empty_ack(struct tcp_pcb *pcb)
00883 {
00884   err_t err;
00885   struct pbuf *p;
00886   u8_t optlen = 0;
00887   struct netif *netif;
00888 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
00889   struct tcp_hdr *tcphdr;
00890 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
00891 
00892 #if LWIP_TCP_TIMESTAMPS
00893   if (pcb->flags & TF_TIMESTAMP) {
00894     optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00895   }
00896 #endif
00897 
00898   p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
00899   if (p == NULL) {
00900     /* let tcp_fasttmr retry sending this ACK */
00901     pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
00902     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00903     return ERR_BUF;
00904   }
00905 #if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
00906   tcphdr = (struct tcp_hdr *)p->payload;
00907 #endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
00908   LWIP_DEBUGF(TCP_OUTPUT_DEBUG,
00909               ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
00910 
00911   /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */
00912 #if LWIP_TCP_TIMESTAMPS
00913   pcb->ts_lastacksent = pcb->rcv_nxt;
00914 
00915   if (pcb->flags & TF_TIMESTAMP) {
00916     tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
00917   }
00918 #endif
00919 
00920   netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
00921   if (netif == NULL) {
00922     err = ERR_RTE;
00923   } else {
00924 #if CHECKSUM_GEN_TCP
00925     IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
00926       tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
00927         &pcb->local_ip, &pcb->remote_ip);
00928     }
00929 #endif
00930     NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
00931     err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip,
00932       pcb->ttl, pcb->tos, IP_PROTO_TCP, netif);
00933     NETIF_SET_HWADDRHINT(netif, NULL);
00934   }
00935   pbuf_free(p);
00936 
00937   if (err != ERR_OK) {
00938     /* let tcp_fasttmr retry sending this ACK */
00939     pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
00940   } else {
00941     /* remove ACK flags from the PCB, as we sent an empty ACK now */
00942     pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00943   }
00944 
00945   return err;
00946 }
00947 
00948 /**
00949  * Find out what we can send and send it
00950  *
00951  * @param pcb Protocol control block for the TCP connection to send data
00952  * @return ERR_OK if data has been sent or nothing to send
00953  *         another err_t on error
00954  */
00955 err_t
00956 tcp_output(struct tcp_pcb *pcb)
00957 {
00958   struct tcp_seg *seg, *useg;
00959   u32_t wnd, snd_nxt;
00960   err_t err;
00961   struct netif *netif;
00962 #if TCP_CWND_DEBUG
00963   s16_t i = 0;
00964 #endif /* TCP_CWND_DEBUG */
00965 
00966   /* pcb->state LISTEN not allowed here */
00967   LWIP_ASSERT("don't call tcp_output for listen-pcbs",
00968     pcb->state != LISTEN);
00969 
00970   /* First, check if we are invoked by the TCP input processing
00971      code. If so, we do not output anything. Instead, we rely on the
00972      input processing code to call us when input processing is done
00973      with. */
00974   if (tcp_input_pcb == pcb) {
00975     return ERR_OK;
00976   }
00977 
00978   wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
00979 
00980   seg = pcb->unsent;
00981 
00982   /* If the TF_ACK_NOW flag is set and no data will be sent (either
00983    * because the ->unsent queue is empty or because the window does
00984    * not allow it), construct an empty ACK segment and send it.
00985    *
00986    * If data is to be sent, we will just piggyback the ACK (see below).
00987    */
00988   if (pcb->flags & TF_ACK_NOW &&
00989      (seg == NULL ||
00990       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00991      return tcp_send_empty_ack(pcb);
00992   }
00993 
00994   /* useg should point to last segment on unacked queue */
00995   useg = pcb->unacked;
00996   if (useg != NULL) {
00997     for (; useg->next != NULL; useg = useg->next);
00998   }
00999 
01000   netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
01001   if (netif == NULL) {
01002     return ERR_RTE;
01003   }
01004 
01005   /* If we don't have a local IP address, we get one from netif */
01006   if (ip_addr_isany(&pcb->local_ip)) {
01007     const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip);
01008     if (local_ip == NULL) {
01009       return ERR_RTE;
01010     }
01011     ip_addr_copy(pcb->local_ip, *local_ip);
01012   }
01013 
01014 #if TCP_OUTPUT_DEBUG
01015   if (seg == NULL) {
01016     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
01017                                    (void*)pcb->unsent));
01018   }
01019 #endif /* TCP_OUTPUT_DEBUG */
01020 #if TCP_CWND_DEBUG
01021   if (seg == NULL) {
01022     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F
01023                                  ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
01024                                  ", seg == NULL, ack %"U32_F"\n",
01025                                  pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
01026   } else {
01027     LWIP_DEBUGF(TCP_CWND_DEBUG,
01028                 ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
01029                  ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
01030                  pcb->snd_wnd, pcb->cwnd, wnd,
01031                  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
01032                  ntohl(seg->tcphdr->seqno), pcb->lastack));
01033   }
01034 #endif /* TCP_CWND_DEBUG */
01035   /* data available and window allows it to be sent? */
01036   while (seg != NULL &&
01037          ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
01038     LWIP_ASSERT("RST not expected here!",
01039                 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
01040     /* Stop sending if the nagle algorithm would prevent it
01041      * Don't stop:
01042      * - if tcp_write had a memory error before (prevent delayed ACK timeout) or
01043      * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
01044      *   either seg->next != NULL or pcb->unacked == NULL;
01045      *   RST is no sent using tcp_write/tcp_output.
01046      */
01047     if ((tcp_do_output_nagle(pcb) == 0) &&
01048       ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
01049       break;
01050     }
01051 #if TCP_CWND_DEBUG
01052     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",
01053                             pcb->snd_wnd, pcb->cwnd, wnd,
01054                             ntohl(seg->tcphdr->seqno) + seg->len -
01055                             pcb->lastack,
01056                             ntohl(seg->tcphdr->seqno), pcb->lastack, i));
01057     ++i;
01058 #endif /* TCP_CWND_DEBUG */
01059 
01060     if (pcb->state != SYN_SENT) {
01061       TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
01062     }
01063 
01064 #if TCP_OVERSIZE_DBGCHECK
01065     seg->oversize_left = 0;
01066 #endif /* TCP_OVERSIZE_DBGCHECK */
01067     err = tcp_output_segment(seg, pcb, netif);
01068     if (err != ERR_OK) {
01069       /* segment could not be sent, for whatever reason */
01070       pcb->flags |= TF_NAGLEMEMERR;
01071       return err;
01072     }
01073     pcb->unsent = seg->next;
01074     if (pcb->state != SYN_SENT) {
01075       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
01076     }
01077     snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
01078     if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
01079       pcb->snd_nxt = snd_nxt;
01080     }
01081     /* put segment on unacknowledged list if length > 0 */
01082     if (TCP_TCPLEN(seg) > 0) {
01083       seg->next = NULL;
01084       /* unacked list is empty? */
01085       if (pcb->unacked == NULL) {
01086         pcb->unacked = seg;
01087         useg = seg;
01088       /* unacked list is not empty? */
01089       } else {
01090         /* In the case of fast retransmit, the packet should not go to the tail
01091          * of the unacked queue, but rather somewhere before it. We need to check for
01092          * this case. -STJ Jul 27, 2004 */
01093         if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
01094           /* add segment to before tail of unacked list, keeping the list sorted */
01095           struct tcp_seg **cur_seg = &(pcb->unacked);
01096           while (*cur_seg &&
01097             TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
01098               cur_seg = &((*cur_seg)->next );
01099           }
01100           seg->next = (*cur_seg);
01101           (*cur_seg) = seg;
01102         } else {
01103           /* add segment to tail of unacked list */
01104           useg->next = seg;
01105           useg = useg->next;
01106         }
01107       }
01108     /* do not queue empty segments on the unacked list */
01109     } else {
01110       tcp_seg_free(seg);
01111     }
01112     seg = pcb->unsent;
01113   }
01114 #if TCP_OVERSIZE
01115   if (pcb->unsent == NULL) {
01116     /* last unsent has been removed, reset unsent_oversize */
01117     pcb->unsent_oversize = 0;
01118   }
01119 #endif /* TCP_OVERSIZE */
01120 
01121   pcb->flags &= ~TF_NAGLEMEMERR;
01122   return ERR_OK;
01123 }
01124 
01125 /**
01126  * Called by tcp_output() to actually send a TCP segment over IP.
01127  *
01128  * @param seg the tcp_seg to send
01129  * @param pcb the tcp_pcb for the TCP connection used to send the segment
01130  * @param netif the netif used to send the segment
01131  */
01132 static err_t
01133 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif)
01134 {
01135   err_t err;
01136   u16_t len;
01137   u32_t *opts;
01138 
01139   if (seg->p->ref != 1) {
01140     /* This can happen if the pbuf of this segment is still referenced by the
01141        netif driver due to deferred transmission. Since this function modifies
01142        p->len, we must not continue in this case. */
01143     return ERR_OK;
01144   }
01145 
01146   /* The TCP header has already been constructed, but the ackno and
01147    wnd fields remain. */
01148   seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
01149 
01150   /* advertise our receive window size in this TCP segment */
01151 #if LWIP_WND_SCALE
01152   if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
01153     /* The Window field in a SYN segment itself (the only type where we send
01154        the window scale option) is never scaled. */
01155     seg->tcphdr->wnd = htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
01156   } else
01157 #endif /* LWIP_WND_SCALE */
01158   {
01159     seg->tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
01160   }
01161 
01162   pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
01163 
01164   /* Add any requested options.  NB MSS option is only set on SYN
01165      packets, so ignore it here */
01166   /* cast through void* to get rid of alignment warnings */
01167   opts = (u32_t *)(void *)(seg->tcphdr + 1);
01168   if (seg->flags & TF_SEG_OPTS_MSS) {
01169     u16_t mss;
01170 #if TCP_CALCULATE_EFF_SEND_MSS
01171     mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip);
01172 #else /* TCP_CALCULATE_EFF_SEND_MSS */
01173     mss = TCP_MSS;
01174 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
01175     *opts = TCP_BUILD_MSS_OPTION(mss);
01176     opts += 1;
01177   }
01178 #if LWIP_TCP_TIMESTAMPS
01179   pcb->ts_lastacksent = pcb->rcv_nxt;
01180 
01181   if (seg->flags & TF_SEG_OPTS_TS) {
01182     tcp_build_timestamp_option(pcb, opts);
01183     opts += 3;
01184   }
01185 #endif
01186 #if LWIP_WND_SCALE
01187   if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
01188     tcp_build_wnd_scale_option(opts);
01189     opts += 1;
01190   }
01191 #endif
01192 
01193   /* Set retransmission timer running if it is not currently enabled
01194      This must be set before checking the route. */
01195   if (pcb->rtime < 0) {
01196     pcb->rtime = 0;
01197   }
01198 
01199   if (pcb->rttest == 0) {
01200     pcb->rttest = tcp_ticks;
01201     pcb->rtseq = ntohl(seg->tcphdr->seqno);
01202 
01203     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
01204   }
01205   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
01206           htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
01207           seg->len));
01208 
01209   len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
01210   if (len == 0) {
01211     /** Exclude retransmitted segments from this count. */
01212     MIB2_STATS_INC(mib2.tcpoutsegs);
01213   }
01214 
01215   seg->p->len -= len;
01216   seg->p->tot_len -= len;
01217 
01218   seg->p->payload = seg->tcphdr;
01219 
01220   seg->tcphdr->chksum = 0;
01221 #if CHECKSUM_GEN_TCP
01222   IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
01223 #if TCP_CHECKSUM_ON_COPY
01224     u32_t acc;
01225 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
01226     u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
01227       seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
01228 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
01229     if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
01230       LWIP_ASSERT("data included but not checksummed",
01231         seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4));
01232     }
01233 
01234     /* rebuild TCP header checksum (TCP header changes for retransmissions!) */
01235     acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP,
01236       seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip);
01237     /* add payload checksum */
01238     if (seg->chksum_swapped) {
01239       seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
01240       seg->chksum_swapped = 0;
01241     }
01242     acc += (u16_t)~(seg->chksum);
01243     seg->tcphdr->chksum = FOLD_U32T(acc);
01244 #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
01245     if (chksum_slow != seg->tcphdr->chksum) {
01246       TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(
01247                   ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n",
01248                   seg->tcphdr->chksum, chksum_slow));
01249       seg->tcphdr->chksum = chksum_slow;
01250     }
01251 #endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
01252 #else /* TCP_CHECKSUM_ON_COPY */
01253     seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
01254       seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
01255 #endif /* TCP_CHECKSUM_ON_COPY */
01256   }
01257 #endif /* CHECKSUM_GEN_TCP */
01258   TCP_STATS_INC(tcp.xmit);
01259 
01260   NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
01261   err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
01262     pcb->tos, IP_PROTO_TCP, netif);
01263   NETIF_SET_HWADDRHINT(netif, NULL);
01264   return err;
01265 }
01266 
01267 /**
01268  * Send a TCP RESET packet (empty segment with RST flag set) either to
01269  * abort a connection or to show that there is no matching local connection
01270  * for a received segment.
01271  *
01272  * Called by tcp_abort() (to abort a local connection), tcp_input() (if no
01273  * matching local pcb was found), tcp_listen_input() (if incoming segment
01274  * has ACK flag set) and tcp_process() (received segment in the wrong state)
01275  *
01276  * Since a RST segment is in most cases not sent for an active connection,
01277  * tcp_rst() has a number of arguments that are taken from a tcp_pcb for
01278  * most other segment output functions.
01279  *
01280  * @param seqno the sequence number to use for the outgoing segment
01281  * @param ackno the acknowledge number to use for the outgoing segment
01282  * @param local_ip the local IP address to send the segment from
01283  * @param remote_ip the remote IP address to send the segment to
01284  * @param local_port the local TCP port to send the segment from
01285  * @param remote_port the remote TCP port to send the segment to
01286  */
01287 void
01288 tcp_rst(u32_t seqno, u32_t ackno,
01289   const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
01290   u16_t local_port, u16_t remote_port)
01291 {
01292   struct pbuf *p;
01293   struct tcp_hdr *tcphdr;
01294   struct netif *netif;
01295   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
01296   if (p == NULL) {
01297     LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
01298     return;
01299   }
01300   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
01301               (p->len >= sizeof(struct tcp_hdr)));
01302 
01303   tcphdr = (struct tcp_hdr *)p->payload;
01304   tcphdr->src = htons(local_port);
01305   tcphdr->dest = htons(remote_port);
01306   tcphdr->seqno = htonl(seqno);
01307   tcphdr->ackno = htonl(ackno);
01308   TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
01309 #if LWIP_WND_SCALE
01310   tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
01311 #else
01312   tcphdr->wnd = PP_HTONS(TCP_WND);
01313 #endif
01314   tcphdr->chksum = 0;
01315   tcphdr->urgp = 0;
01316 
01317   TCP_STATS_INC(tcp.xmit);
01318   MIB2_STATS_INC(mib2.tcpoutrsts);
01319 
01320   netif = ip_route(local_ip, remote_ip);
01321   if (netif != NULL) {
01322 #if CHECKSUM_GEN_TCP
01323     IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
01324       tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
01325                                         local_ip, remote_ip);
01326     }
01327 #endif
01328     /* Send output with hardcoded TTL/HL since we have no access to the pcb */
01329     ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif);
01330   }
01331   pbuf_free(p);
01332   LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
01333 }
01334 
01335 /**
01336  * Requeue all unacked segments for retransmission
01337  *
01338  * Called by tcp_slowtmr() for slow retransmission.
01339  *
01340  * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
01341  */
01342 void
01343 tcp_rexmit_rto(struct tcp_pcb *pcb)
01344 {
01345   struct tcp_seg *seg;
01346 
01347   if (pcb->unacked == NULL) {
01348     return;
01349   }
01350 
01351   /* Move all unacked segments to the head of the unsent queue */
01352   for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
01353   /* concatenate unsent queue after unacked queue */
01354   seg->next = pcb->unsent;
01355 #if TCP_OVERSIZE_DBGCHECK
01356   /* if last unsent changed, we need to update unsent_oversize */
01357   if (pcb->unsent == NULL) {
01358     pcb->unsent_oversize = seg->oversize_left;
01359   }
01360 #endif /* TCP_OVERSIZE_DBGCHECK */
01361   /* unsent queue is the concatenated queue (of unacked, unsent) */
01362   pcb->unsent = pcb->unacked;
01363   /* unacked queue is now empty */
01364   pcb->unacked = NULL;
01365 
01366   /* increment number of retransmissions */
01367   ++pcb->nrtx;
01368 
01369   /* Don't take any RTT measurements after retransmitting. */
01370   pcb->rttest = 0;
01371 
01372   /* Do the actual retransmission */
01373   tcp_output(pcb);
01374 }
01375 
01376 /**
01377  * Requeue the first unacked segment for retransmission
01378  *
01379  * Called by tcp_receive() for fast retramsmit.
01380  *
01381  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
01382  */
01383 void
01384 tcp_rexmit(struct tcp_pcb *pcb)
01385 {
01386   struct tcp_seg *seg;
01387   struct tcp_seg **cur_seg;
01388 
01389   if (pcb->unacked == NULL) {
01390     return;
01391   }
01392 
01393   /* Move the first unacked segment to the unsent queue */
01394   /* Keep the unsent queue sorted. */
01395   seg = pcb->unacked;
01396   pcb->unacked = seg->next;
01397 
01398   cur_seg = &(pcb->unsent);
01399   while (*cur_seg &&
01400     TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
01401       cur_seg = &((*cur_seg)->next );
01402   }
01403   seg->next = *cur_seg;
01404   *cur_seg = seg;
01405 #if TCP_OVERSIZE
01406   if (seg->next == NULL) {
01407     /* the retransmitted segment is last in unsent, so reset unsent_oversize */
01408     pcb->unsent_oversize = 0;
01409   }
01410 #endif /* TCP_OVERSIZE */
01411 
01412   ++pcb->nrtx;
01413 
01414   /* Don't take any rtt measurements after retransmitting. */
01415   pcb->rttest = 0;
01416 
01417   /* Do the actual retransmission. */
01418   MIB2_STATS_INC(mib2.tcpretranssegs);
01419   /* No need to call tcp_output: we are always called from tcp_input()
01420      and thus tcp_output directly returns. */
01421 }
01422 
01423 
01424 /**
01425  * Handle retransmission after three dupacks received
01426  *
01427  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
01428  */
01429 void
01430 tcp_rexmit_fast(struct tcp_pcb *pcb)
01431 {
01432   if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
01433     /* This is fast retransmit. Retransmit the first unacked segment. */
01434     LWIP_DEBUGF(TCP_FR_DEBUG,
01435                 ("tcp_receive: dupacks %"U16_F" (%"U32_F
01436                  "), fast retransmit %"U32_F"\n",
01437                  (u16_t)pcb->dupacks, pcb->lastack,
01438                  ntohl(pcb->unacked->tcphdr->seqno)));
01439     tcp_rexmit(pcb);
01440 
01441     /* Set ssthresh to half of the minimum of the current
01442      * cwnd and the advertised window */
01443     if (pcb->cwnd > pcb->snd_wnd) {
01444       pcb->ssthresh = pcb->snd_wnd / 2;
01445     } else {
01446       pcb->ssthresh = pcb->cwnd / 2;
01447     }
01448 
01449     /* The minimum value for ssthresh should be 2 MSS */
01450     if (pcb->ssthresh < (2U * pcb->mss)) {
01451       LWIP_DEBUGF(TCP_FR_DEBUG,
01452                   ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F
01453                    " should be min 2 mss %"U16_F"...\n",
01454                    pcb->ssthresh, (u16_t)(2*pcb->mss)));
01455       pcb->ssthresh = 2*pcb->mss;
01456     }
01457 
01458     pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
01459     pcb->flags |= TF_INFR;
01460 
01461     /* Reset the retransmission timer to prevent immediate rto retransmissions */
01462     pcb->rtime = 0;
01463   }
01464 }
01465 
01466 
01467 /**
01468  * Send keepalive packets to keep a connection active although
01469  * no data is sent over it.
01470  *
01471  * Called by tcp_slowtmr()
01472  *
01473  * @param pcb the tcp_pcb for which to send a keepalive packet
01474  */
01475 err_t
01476 tcp_keepalive(struct tcp_pcb *pcb)
01477 {
01478   err_t err;
01479   struct pbuf *p;
01480   struct netif *netif;
01481 
01482   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
01483   ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
01484   LWIP_DEBUGF(TCP_DEBUG, ("\n"));
01485 
01486   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
01487                           tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
01488 
01489   p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
01490   if (p == NULL) {
01491     LWIP_DEBUGF(TCP_DEBUG,
01492                 ("tcp_keepalive: could not allocate memory for pbuf\n"));
01493     return ERR_MEM;
01494   }
01495   netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
01496   if (netif == NULL) {
01497     err = ERR_RTE;
01498   } else {
01499 #if CHECKSUM_GEN_TCP
01500     IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
01501       struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
01502       tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
01503         &pcb->local_ip, &pcb->remote_ip);
01504     }
01505 #endif /* CHECKSUM_GEN_TCP */
01506     TCP_STATS_INC(tcp.xmit);
01507 
01508     /* Send output to IP */
01509     NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
01510     err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif);
01511     NETIF_SET_HWADDRHINT(netif, NULL);
01512   }
01513   pbuf_free(p);
01514 
01515   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
01516                           pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
01517   return err;
01518 }
01519 
01520 
01521 /**
01522  * Send persist timer zero-window probes to keep a connection active
01523  * when a window update is lost.
01524  *
01525  * Called by tcp_slowtmr()
01526  *
01527  * @param pcb the tcp_pcb for which to send a zero-window probe packet
01528  */
01529 err_t
01530 tcp_zero_window_probe(struct tcp_pcb *pcb)
01531 {
01532   err_t err;
01533   struct pbuf *p;
01534   struct tcp_hdr *tcphdr;
01535   struct tcp_seg *seg;
01536   u16_t len;
01537   u8_t is_fin;
01538   struct netif *netif;
01539 
01540   LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
01541   ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
01542   LWIP_DEBUGF(TCP_DEBUG, ("\n"));
01543 
01544   LWIP_DEBUGF(TCP_DEBUG,
01545               ("tcp_zero_window_probe: tcp_ticks %"U32_F
01546                "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
01547                tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
01548 
01549   seg = pcb->unacked;
01550 
01551   if (seg == NULL) {
01552     seg = pcb->unsent;
01553   }
01554   if (seg == NULL) {
01555     /* nothing to send, zero window probe not needed */
01556     return ERR_OK;
01557   }
01558 
01559   is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
01560   /* we want to send one seqno: either FIN or data (no options) */
01561   len = is_fin ? 0 : 1;
01562 
01563   p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
01564   if (p == NULL) {
01565     LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
01566     return ERR_MEM;
01567   }
01568   tcphdr = (struct tcp_hdr *)p->payload;
01569 
01570   if (is_fin) {
01571     /* FIN segment, no data */
01572     TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
01573   } else {
01574     /* Data segment, copy in one byte from the head of the unacked queue */
01575     char *d = ((char *)p->payload + TCP_HLEN);
01576     /* Depending on whether the segment has already been sent (unacked) or not
01577        (unsent), seg->p->payload points to the IP header or TCP header.
01578        Ensure we copy the first TCP data byte: */
01579     pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
01580   }
01581 
01582   netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
01583   if (netif == NULL) {
01584     err = ERR_RTE;
01585   } else {
01586 #if CHECKSUM_GEN_TCP
01587     IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
01588       tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
01589         &pcb->local_ip, &pcb->remote_ip);
01590     }
01591 #endif
01592     TCP_STATS_INC(tcp.xmit);
01593 
01594     /* Send output to IP */
01595     NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
01596     err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
01597       0, IP_PROTO_TCP, netif);
01598     NETIF_SET_HWADDRHINT(netif, NULL);
01599   }
01600 
01601   pbuf_free(p);
01602 
01603   LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
01604                           " ackno %"U32_F" err %d.\n",
01605                           pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
01606   return err;
01607 }
01608 #endif /* LWIP_TCP */