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