SAMV71 Xplained Ultra Software Package 1.3

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/tcp.h"
00046 #include "lwip/def.h"
00047 #include "lwip/mem.h"
00048 #include "lwip/memp.h"
00049 #include "lwip/sys.h"
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/netif.h"
00052 #include "lwip/inet.h"
00053 #include "lwip/inet_chksum.h"
00054 #include "lwip/stats.h"
00055 #include "lwip/snmp.h"
00056 
00057 #include <string.h>
00058 
00059 /* Forward declarations.*/
00060 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
00061 
00062 static struct tcp_hdr *
00063 tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
00064                       u32_t seqno_be /* already in network byte order */)
00065 {
00066   struct tcp_hdr *tcphdr = p->payload;
00067   tcphdr->src = htons(pcb->local_port);
00068   tcphdr->dest = htons(pcb->remote_port);
00069   tcphdr->seqno = seqno_be;
00070   tcphdr->ackno = htonl(pcb->rcv_nxt);
00071   TCPH_FLAGS_SET(tcphdr, TCP_ACK);
00072   tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00073   tcphdr->urgp = 0;
00074   TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
00075   tcphdr->chksum = 0;
00076 
00077   /* If we're sending a packet, update the announced right window edge */
00078   pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00079 
00080   return tcphdr;
00081 }
00082 
00083 /**
00084  * Called by tcp_close() to send a segment including flags but not data.
00085  *
00086  * @param pcb the tcp_pcb over which to send a segment
00087  * @param flags the flags to set in the segment header
00088  * @return ERR_OK if sent, another err_t otherwise
00089  */
00090 err_t
00091 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
00092 {
00093   /* no data, no length, flags, copy=1, no optdata */
00094   return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
00095 }
00096 
00097 /**
00098  * Write data for sending (but does not send it immediately).
00099  *
00100  * It waits in the expectation of more data being sent soon (as
00101  * it can send them more efficiently by combining them together).
00102  * To prompt the system to send data now, call tcp_output() after
00103  * calling tcp_write().
00104  * 
00105  * @param pcb Protocol control block of the TCP connection to enqueue data for.
00106  * @param data pointer to the data to send
00107  * @param len length (in bytes) of the data to send
00108  * @param apiflags combination of following flags :
00109  * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
00110  * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
00111  * @return ERR_OK if enqueued, another err_t on error
00112  * 
00113  * @see tcp_write()
00114  */
00115 err_t
00116 tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
00117 {
00118   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
00119     data, len, (u16_t)apiflags));
00120   /* connection is in valid state for data transmission? */
00121   if (pcb->state == ESTABLISHED ||
00122      pcb->state == CLOSE_WAIT ||
00123      pcb->state == SYN_SENT ||
00124      pcb->state == SYN_RCVD) {
00125     if (len > 0) {
00126 #if LWIP_TCP_TIMESTAMPS
00127       return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 
00128                          pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
00129 #else
00130       return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
00131 #endif
00132     }
00133     return ERR_OK;
00134   } else {
00135     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
00136     return ERR_CONN;
00137   }
00138 }
00139 
00140 /**
00141  * Enqueue data and/or TCP options for transmission
00142  *
00143  * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
00144  *
00145  * @param pcb Protocol control block for the TCP connection to enqueue data for.
00146  * @param arg Pointer to the data to be enqueued for sending.
00147  * @param len Data length in bytes
00148  * @param flags tcp header flags to set in the outgoing segment
00149  * @param apiflags combination of following flags :
00150  * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
00151  * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
00152  * @param optflags options to include in segment later on (see definition of struct tcp_seg)
00153  */
00154 err_t
00155 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
00156             u8_t flags, u8_t apiflags, u8_t optflags)
00157 {
00158   struct pbuf *p;
00159   struct tcp_seg *seg, *useg, *queue;
00160   u32_t seqno;
00161   u16_t left, seglen;
00162   void *ptr;
00163   u16_t queuelen;
00164   u8_t optlen;
00165 
00166   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
00167               ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
00168                (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
00169   LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
00170              ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
00171              return ERR_ARG;);
00172   LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)", 
00173              ((len != 0) || (arg == NULL)), return ERR_ARG;);
00174 
00175   /* fail on too much data */
00176   if (len > pcb->snd_buf) {
00177     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
00178       ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
00179     pcb->flags |= TF_NAGLEMEMERR;
00180     return ERR_MEM;
00181   }
00182   left = len;
00183   ptr = arg;
00184 
00185   optlen = LWIP_TCP_OPT_LENGTH(optflags);
00186 
00187   /* seqno will be the sequence number of the first segment enqueued
00188    * by the call to this function. */
00189   seqno = pcb->snd_lbb;
00190 
00191   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00192 
00193   /* If total number of pbufs on the unsent/unacked queues exceeds the
00194    * configured maximum, return an error */
00195   queuelen = pcb->snd_queuelen;
00196   /* check for configured max queuelen and possible overflow */
00197   if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00198     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
00199       ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00200     TCP_STATS_INC(tcp.memerr);
00201     pcb->flags |= TF_NAGLEMEMERR;
00202     return ERR_MEM;
00203   }
00204   if (queuelen != 0) {
00205     LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
00206       pcb->unacked != NULL || pcb->unsent != NULL);
00207   } else {
00208     LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
00209       pcb->unacked == NULL && pcb->unsent == NULL);
00210   }
00211 
00212   /* First, break up the data into segments and tuck them together in
00213    * the local "queue" variable. */
00214   useg = queue = seg = NULL;
00215   seglen = 0;
00216   while (queue == NULL || left > 0) {
00217     /* The segment length (including options) should be at most the MSS */
00218     seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
00219 
00220     /* Allocate memory for tcp_seg, and fill in fields. */
00221     seg = memp_malloc(MEMP_TCP_SEG);
00222     if (seg == NULL) {
00223       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
00224                   ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
00225       goto memerr;
00226     }
00227     seg->next = NULL;
00228     seg->p = NULL;
00229 
00230     /* first segment of to-be-queued data? */
00231     if (queue == NULL) {
00232       queue = seg;
00233     }
00234     /* subsequent segments of to-be-queued data */
00235     else {
00236       /* Attach the segment to the end of the queued segments */
00237       LWIP_ASSERT("useg != NULL", useg != NULL);
00238       useg->next = seg;
00239     }
00240     /* remember last segment of to-be-queued data for next iteration */
00241     useg = seg;
00242 
00243     /* If copy is set, memory should be allocated
00244      * and data copied into pbuf, otherwise data comes from
00245      * ROM or other static memory, and need not be copied.  */
00246     if (apiflags & TCP_WRITE_FLAG_COPY) {
00247       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
00248         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
00249                     ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
00250         goto memerr;
00251       }
00252       LWIP_ASSERT("check that first pbuf can hold the complete seglen",
00253                   (seg->p->len >= seglen + optlen));
00254       queuelen += pbuf_clen(seg->p);
00255       if (arg != NULL) {
00256         MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
00257       }
00258       seg->dataptr = seg->p->payload;
00259     }
00260     /* do not copy data */
00261     else {
00262       /* First, allocate a pbuf for the headers. */
00263       if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00264         LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
00265                     ("tcp_enqueue: could not allocate memory for header pbuf\n"));
00266         goto memerr;
00267       }
00268       queuelen += pbuf_clen(seg->p);
00269 
00270       /* Second, allocate a pbuf for holding the data.
00271        * since the referenced data is available at least until it is sent out on the
00272        * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
00273        * instead of PBUF_REF here.
00274        */
00275       if (left > 0) {
00276         if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
00277           /* If allocation fails, we have to deallocate the header pbuf as well. */
00278           pbuf_free(seg->p);
00279           seg->p = NULL;
00280           LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
00281                       ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
00282           goto memerr;
00283         }
00284         ++queuelen;
00285         /* reference the non-volatile payload data */
00286         p->payload = ptr;
00287         seg->dataptr = ptr;
00288 
00289         /* Concatenate the headers and data pbufs together. */
00290         pbuf_cat(seg->p/*header*/, p/*data*/);
00291         p = NULL;
00292       }
00293     }
00294 
00295     /* Now that there are more segments queued, we check again if the
00296     length of the queue exceeds the configured maximum or overflows. */
00297     if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
00298       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00299         ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
00300       goto memerr;
00301     }
00302 
00303     seg->len = seglen;
00304 
00305     /* build TCP header */
00306     if (pbuf_header(seg->p, TCP_HLEN)) {
00307       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
00308       TCP_STATS_INC(tcp.err);
00309       goto memerr;
00310     }
00311     seg->tcphdr = seg->p->payload;
00312     seg->tcphdr->src = htons(pcb->local_port);
00313     seg->tcphdr->dest = htons(pcb->remote_port);
00314     seg->tcphdr->seqno = htonl(seqno);
00315     seg->tcphdr->urgp = 0;
00316     TCPH_FLAGS_SET(seg->tcphdr, flags);
00317     /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
00318 
00319     seg->flags = optflags;
00320 
00321     /* Set the length of the header */
00322     TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
00323     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
00324       ntohl(seg->tcphdr->seqno),
00325       ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00326       (u16_t)flags));
00327 
00328     left -= seglen;
00329     seqno += seglen;
00330     ptr = (void *)((u8_t *)ptr + seglen);
00331   }
00332 
00333   /* Now that the data to be enqueued has been broken up into TCP
00334   segments in the queue variable, we add them to the end of the
00335   pcb->unsent queue. */
00336   if (pcb->unsent == NULL) {
00337     useg = NULL;
00338   }
00339   else {
00340     for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00341   }
00342   /* { useg is last segment on the unsent queue, NULL if list is empty } */
00343 
00344   /* If there is room in the last pbuf on the unsent queue,
00345   chain the first pbuf on the queue together with that. */
00346   if (useg != NULL &&
00347     TCP_TCPLEN(useg) != 0 &&
00348     !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
00349     (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
00350     /* fit within max seg size */
00351     (useg->len + queue->len <= pcb->mss) &&
00352     /* only concatenate segments with the same options */
00353     (useg->flags == queue->flags) &&
00354     /* segments are consecutive */
00355     (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
00356     /* Remove TCP header from first segment of our to-be-queued list */
00357     if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
00358       /* Can we cope with this failing?  Just assert for now */
00359       LWIP_ASSERT("pbuf_header failed\n", 0);
00360       TCP_STATS_INC(tcp.err);
00361       goto memerr;
00362     }
00363     if (queue->p->len == 0) {
00364       /* free the first (header-only) pbuf if it is now empty (contained only headers) */
00365       struct pbuf *old_q = queue->p;
00366       queue->p = queue->p->next;
00367       old_q->next = NULL;
00368       queuelen--;
00369       pbuf_free(old_q);
00370     }
00371     if (flags & TCP_FIN) {
00372       /* the new segment contains only FIN, no data -> put the FIN into the last segment */
00373       LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
00374       TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
00375     } else {
00376       LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
00377       pbuf_cat(useg->p, queue->p);
00378       useg->len += queue->len;
00379       useg->next = queue->next;
00380     }
00381 
00382     LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
00383     if (seg == queue) {
00384       seg = useg;
00385       seglen = useg->len;
00386     }
00387     memp_free(MEMP_TCP_SEG, queue);
00388   }
00389   else {
00390     /* empty list */
00391     if (useg == NULL) {
00392       /* initialize list with this segment */
00393       pcb->unsent = queue;
00394     }
00395     /* enqueue segment */
00396     else {
00397       useg->next = queue;
00398     }
00399   }
00400   if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
00401     ++len;
00402   }
00403   if (flags & TCP_FIN) {
00404     pcb->flags |= TF_FIN;
00405   }
00406   pcb->snd_lbb += len;
00407 
00408   pcb->snd_buf -= len;
00409 
00410   /* update number of segments on the queues */
00411   pcb->snd_queuelen = queuelen;
00412   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
00413   if (pcb->snd_queuelen != 0) {
00414     LWIP_ASSERT("tcp_enqueue: valid queue length",
00415       pcb->unacked != NULL || pcb->unsent != NULL);
00416   }
00417 
00418   /* Set the PSH flag in the last segment that we enqueued, but only
00419   if the segment has data (indicated by seglen > 0). */
00420   if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
00421     TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
00422   }
00423 
00424   return ERR_OK;
00425 memerr:
00426   pcb->flags |= TF_NAGLEMEMERR;
00427   TCP_STATS_INC(tcp.memerr);
00428 
00429   if (queue != NULL) {
00430     tcp_segs_free(queue);
00431   }
00432   if (pcb->snd_queuelen != 0) {
00433     LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00434       pcb->unsent != NULL);
00435   }
00436   LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
00437   return ERR_MEM;
00438 }
00439 
00440 
00441 #if LWIP_TCP_TIMESTAMPS
00442 /* Build a timestamp option (12 bytes long) at the specified options pointer)
00443  *
00444  * @param pcb tcp_pcb
00445  * @param opts option pointer where to store the timestamp option
00446  */
00447 static void
00448 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
00449 {
00450   /* Pad with two NOP options to make everything nicely aligned */
00451   opts[0] = htonl(0x0101080A);
00452   opts[1] = htonl(sys_now());
00453   opts[2] = htonl(pcb->ts_recent);
00454 }
00455 #endif
00456 
00457 /** Send an ACK without data.
00458  *
00459  * @param pcb Protocol control block for the TCP connection to send the ACK
00460  */
00461 err_t
00462 tcp_send_empty_ack(struct tcp_pcb *pcb)
00463 {
00464   struct pbuf *p;
00465   struct tcp_hdr *tcphdr;
00466   u8_t optlen = 0;
00467 
00468 #if LWIP_TCP_TIMESTAMPS
00469   if (pcb->flags & TF_TIMESTAMP) {
00470     optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
00471   }
00472 #endif
00473   p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
00474   if (p == NULL) {
00475     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00476     return ERR_BUF;
00477   }
00478   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
00479               ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
00480   /* remove ACK flags from the PCB, as we send an empty ACK now */
00481   pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00482 
00483   tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
00484 
00485   /* NB. MSS option is only sent on SYNs, so ignore it here */
00486 #if LWIP_TCP_TIMESTAMPS
00487   pcb->ts_lastacksent = pcb->rcv_nxt;
00488 
00489   if (pcb->flags & TF_TIMESTAMP) {
00490     tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
00491   }
00492 #endif 
00493 
00494 #if CHECKSUM_GEN_TCP
00495   tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
00496         IP_PROTO_TCP, p->tot_len);
00497 #endif
00498 #if LWIP_NETIF_HWADDRHINT
00499   ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00500       IP_PROTO_TCP, &(pcb->addr_hint));
00501 #else /* LWIP_NETIF_HWADDRHINT*/
00502   ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00503       IP_PROTO_TCP);
00504 #endif /* LWIP_NETIF_HWADDRHINT*/
00505   pbuf_free(p);
00506 
00507   return ERR_OK;
00508 }
00509 
00510 /**
00511  * Find out what we can send and send it
00512  *
00513  * @param pcb Protocol control block for the TCP connection to send data
00514  * @return ERR_OK if data has been sent or nothing to send
00515  *         another err_t on error
00516  */
00517 err_t
00518 tcp_output(struct tcp_pcb *pcb)
00519 {
00520   struct tcp_seg *seg, *useg;
00521   u32_t wnd, snd_nxt;
00522 #if TCP_CWND_DEBUG
00523   s16_t i = 0;
00524 #endif /* TCP_CWND_DEBUG */
00525 
00526   /* First, check if we are invoked by the TCP input processing
00527      code. If so, we do not output anything. Instead, we rely on the
00528      input processing code to call us when input processing is done
00529      with. */
00530   if (tcp_input_pcb == pcb) {
00531     return ERR_OK;
00532   }
00533 
00534   wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
00535 
00536   seg = pcb->unsent;
00537 
00538   /* If the TF_ACK_NOW flag is set and no data will be sent (either
00539    * because the ->unsent queue is empty or because the window does
00540    * not allow it), construct an empty ACK segment and send it.
00541    *
00542    * If data is to be sent, we will just piggyback the ACK (see below).
00543    */
00544   if (pcb->flags & TF_ACK_NOW &&
00545      (seg == NULL ||
00546       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00547      return tcp_send_empty_ack(pcb);
00548   }
00549 
00550   /* useg should point to last segment on unacked queue */
00551   useg = pcb->unacked;
00552   if (useg != NULL) {
00553     for (; useg->next != NULL; useg = useg->next);
00554   }
00555 
00556 #if TCP_OUTPUT_DEBUG
00557   if (seg == NULL) {
00558     LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
00559                                    (void*)pcb->unsent));
00560   }
00561 #endif /* TCP_OUTPUT_DEBUG */
00562 #if TCP_CWND_DEBUG
00563   if (seg == NULL) {
00564     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
00565                                  ", cwnd %"U16_F", wnd %"U32_F
00566                                  ", seg == NULL, ack %"U32_F"\n",
00567                                  pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
00568   } else {
00569     LWIP_DEBUGF(TCP_CWND_DEBUG, 
00570                 ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
00571                  ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
00572                  pcb->snd_wnd, pcb->cwnd, wnd,
00573                  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
00574                  ntohl(seg->tcphdr->seqno), pcb->lastack));
00575   }
00576 #endif /* TCP_CWND_DEBUG */
00577   /* data available and window allows it to be sent? */
00578   while (seg != NULL &&
00579          ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
00580     LWIP_ASSERT("RST not expected here!", 
00581                 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
00582     /* Stop sending if the nagle algorithm would prevent it
00583      * Don't stop:
00584      * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or
00585      * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
00586      *   either seg->next != NULL or pcb->unacked == NULL;
00587      *   RST is no sent using tcp_enqueue/tcp_output.
00588      */
00589     if((tcp_do_output_nagle(pcb) == 0) &&
00590       ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
00591       break;
00592     }
00593 #if TCP_CWND_DEBUG
00594     LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
00595                             pcb->snd_wnd, pcb->cwnd, wnd,
00596                             ntohl(seg->tcphdr->seqno) + seg->len -
00597                             pcb->lastack,
00598                             ntohl(seg->tcphdr->seqno), pcb->lastack, i));
00599     ++i;
00600 #endif /* TCP_CWND_DEBUG */
00601 
00602     pcb->unsent = seg->next;
00603 
00604     if (pcb->state != SYN_SENT) {
00605       TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
00606       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00607     }
00608 
00609     tcp_output_segment(seg, pcb);
00610     snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
00611     if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
00612       pcb->snd_nxt = snd_nxt;
00613     }
00614     /* put segment on unacknowledged list if length > 0 */
00615     if (TCP_TCPLEN(seg) > 0) {
00616       seg->next = NULL;
00617       /* unacked list is empty? */
00618       if (pcb->unacked == NULL) {
00619         pcb->unacked = seg;
00620         useg = seg;
00621       /* unacked list is not empty? */
00622       } else {
00623         /* In the case of fast retransmit, the packet should not go to the tail
00624          * of the unacked queue, but rather somewhere before it. We need to check for
00625          * this case. -STJ Jul 27, 2004 */
00626         if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
00627           /* add segment to before tail of unacked list, keeping the list sorted */
00628           struct tcp_seg **cur_seg = &(pcb->unacked);
00629           while (*cur_seg &&
00630             TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00631               cur_seg = &((*cur_seg)->next );
00632           }
00633           seg->next = (*cur_seg);
00634           (*cur_seg) = seg;
00635         } else {
00636           /* add segment to tail of unacked list */
00637           useg->next = seg;
00638           useg = useg->next;
00639         }
00640       }
00641     /* do not queue empty segments on the unacked list */
00642     } else {
00643       tcp_seg_free(seg);
00644     }
00645     seg = pcb->unsent;
00646   }
00647 
00648   if (seg != NULL && pcb->persist_backoff == 0 && 
00649       ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
00650     /* prepare for persist timer */
00651     pcb->persist_cnt = 0;
00652     pcb->persist_backoff = 1;
00653   }
00654 
00655   pcb->flags &= ~TF_NAGLEMEMERR;
00656   return ERR_OK;
00657 }
00658 
00659 /**
00660  * Called by tcp_output() to actually send a TCP segment over IP.
00661  *
00662  * @param seg the tcp_seg to send
00663  * @param pcb the tcp_pcb for the TCP connection used to send the segment
00664  */
00665 static void
00666 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
00667 {
00668   u16_t len;
00669   struct netif *netif;
00670   u32_t *opts;
00671 
00672   /** @bug Exclude retransmitted segments from this count. */
00673   snmp_inc_tcpoutsegs();
00674 
00675   /* The TCP header has already been constructed, but the ackno and
00676    wnd fields remain. */
00677   seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
00678 
00679   /* advertise our receive window size in this TCP segment */
00680   seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
00681 
00682   pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
00683 
00684   /* Add any requested options.  NB MSS option is only set on SYN
00685      packets, so ignore it here */
00686   opts = (u32_t *)(seg->tcphdr + 1);
00687   if (seg->flags & TF_SEG_OPTS_MSS) {
00688     TCP_BUILD_MSS_OPTION(*opts);
00689     opts += 1;
00690   }
00691 #if LWIP_TCP_TIMESTAMPS
00692   pcb->ts_lastacksent = pcb->rcv_nxt;
00693 
00694   if (seg->flags & TF_SEG_OPTS_TS) {
00695     tcp_build_timestamp_option(pcb, opts);
00696     opts += 3;
00697   }
00698 #endif
00699 
00700   /* If we don't have a local IP address, we get one by
00701      calling ip_route(). */
00702   if (ip_addr_isany(&(pcb->local_ip))) {
00703     netif = ip_route(&(pcb->remote_ip));
00704     if (netif == NULL) {
00705       return;
00706     }
00707     ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
00708   }
00709 
00710   /* Set retransmission timer running if it is not currently enabled */
00711   if(pcb->rtime == -1)
00712     pcb->rtime = 0;
00713 
00714   if (pcb->rttest == 0) {
00715     pcb->rttest = tcp_ticks;
00716     pcb->rtseq = ntohl(seg->tcphdr->seqno);
00717 
00718     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
00719   }
00720   LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
00721           htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
00722           seg->len));
00723 
00724   len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
00725 
00726   seg->p->len -= len;
00727   seg->p->tot_len -= len;
00728 
00729   seg->p->payload = seg->tcphdr;
00730 
00731   seg->tcphdr->chksum = 0;
00732 #if CHECKSUM_GEN_TCP
00733   seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
00734              &(pcb->local_ip),
00735              &(pcb->remote_ip),
00736              IP_PROTO_TCP, seg->p->tot_len);
00737 #endif
00738   TCP_STATS_INC(tcp.xmit);
00739 
00740 #if LWIP_NETIF_HWADDRHINT
00741   ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00742       IP_PROTO_TCP, &(pcb->addr_hint));
00743 #else /* LWIP_NETIF_HWADDRHINT*/
00744   ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
00745       IP_PROTO_TCP);
00746 #endif /* LWIP_NETIF_HWADDRHINT*/
00747 }
00748 
00749 /**
00750  * Send a TCP RESET packet (empty segment with RST flag set) either to
00751  * abort a connection or to show that there is no matching local connection
00752  * for a received segment.
00753  *
00754  * Called by tcp_abort() (to abort a local connection), tcp_input() (if no
00755  * matching local pcb was found), tcp_listen_input() (if incoming segment
00756  * has ACK flag set) and tcp_process() (received segment in the wrong state)
00757  *
00758  * Since a RST segment is in most cases not sent for an active connection,
00759  * tcp_rst() has a number of arguments that are taken from a tcp_pcb for
00760  * most other segment output functions.
00761  *
00762  * @param seqno the sequence number to use for the outgoing segment
00763  * @param ackno the acknowledge number to use for the outgoing segment
00764  * @param local_ip the local IP address to send the segment from
00765  * @param remote_ip the remote IP address to send the segment to
00766  * @param local_port the local TCP port to send the segment from
00767  * @param remote_port the remote TCP port to send the segment to
00768  */
00769 void
00770 tcp_rst(u32_t seqno, u32_t ackno,
00771   struct ip_addr *local_ip, struct ip_addr *remote_ip,
00772   u16_t local_port, u16_t remote_port)
00773 {
00774   struct pbuf *p;
00775   struct tcp_hdr *tcphdr;
00776   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00777   if (p == NULL) {
00778       LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
00779       return;
00780   }
00781   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00782               (p->len >= sizeof(struct tcp_hdr)));
00783 
00784   tcphdr = p->payload;
00785   tcphdr->src = htons(local_port);
00786   tcphdr->dest = htons(remote_port);
00787   tcphdr->seqno = htonl(seqno);
00788   tcphdr->ackno = htonl(ackno);
00789   TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
00790   tcphdr->wnd = htons(TCP_WND);
00791   tcphdr->urgp = 0;
00792   TCPH_HDRLEN_SET(tcphdr, 5);
00793 
00794   tcphdr->chksum = 0;
00795 #if CHECKSUM_GEN_TCP
00796   tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
00797               IP_PROTO_TCP, p->tot_len);
00798 #endif
00799   TCP_STATS_INC(tcp.xmit);
00800   snmp_inc_tcpoutrsts();
00801    /* Send output with hardcoded TTL since we have no access to the pcb */
00802   ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
00803   pbuf_free(p);
00804   LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
00805 }
00806 
00807 /**
00808  * Requeue all unacked segments for retransmission
00809  *
00810  * Called by tcp_slowtmr() for slow retransmission.
00811  *
00812  * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
00813  */
00814 void
00815 tcp_rexmit_rto(struct tcp_pcb *pcb)
00816 {
00817   struct tcp_seg *seg;
00818 
00819   if (pcb->unacked == NULL) {
00820     return;
00821   }
00822 
00823   /* Move all unacked segments to the head of the unsent queue */
00824   for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
00825   /* concatenate unsent queue after unacked queue */
00826   seg->next = pcb->unsent;
00827   /* unsent queue is the concatenated queue (of unacked, unsent) */
00828   pcb->unsent = pcb->unacked;
00829   /* unacked queue is now empty */
00830   pcb->unacked = NULL;
00831 
00832   /* increment number of retransmissions */
00833   ++pcb->nrtx;
00834 
00835   /* Don't take any RTT measurements after retransmitting. */
00836   pcb->rttest = 0;
00837 
00838   /* Do the actual retransmission */
00839   tcp_output(pcb);
00840 }
00841 
00842 /**
00843  * Requeue the first unacked segment for retransmission
00844  *
00845  * Called by tcp_receive() for fast retramsmit.
00846  *
00847  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
00848  */
00849 void
00850 tcp_rexmit(struct tcp_pcb *pcb)
00851 {
00852   struct tcp_seg *seg;
00853   struct tcp_seg **cur_seg;
00854 
00855   if (pcb->unacked == NULL) {
00856     return;
00857   }
00858 
00859   /* Move the first unacked segment to the unsent queue */
00860   /* Keep the unsent queue sorted. */
00861   seg = pcb->unacked;
00862   pcb->unacked = seg->next;
00863 
00864   cur_seg = &(pcb->unsent);
00865   while (*cur_seg &&
00866     TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
00867       cur_seg = &((*cur_seg)->next );
00868   }
00869   seg->next = *cur_seg;
00870   *cur_seg = seg;
00871 
00872   ++pcb->nrtx;
00873 
00874   /* Don't take any rtt measurements after retransmitting. */
00875   pcb->rttest = 0;
00876 
00877   /* Do the actual retransmission. */
00878   snmp_inc_tcpretranssegs();
00879   /* No need to call tcp_output: we are always called from tcp_input()
00880      and thus tcp_output directly returns. */
00881 }
00882 
00883 
00884 /**
00885  * Handle retransmission after three dupacks received
00886  *
00887  * @param pcb the tcp_pcb for which to retransmit the first unacked segment
00888  */
00889 void 
00890 tcp_rexmit_fast(struct tcp_pcb *pcb)
00891 {
00892   if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
00893     /* This is fast retransmit. Retransmit the first unacked segment. */
00894     LWIP_DEBUGF(TCP_FR_DEBUG, 
00895                 ("tcp_receive: dupacks %"U16_F" (%"U32_F
00896                  "), fast retransmit %"U32_F"\n",
00897                  (u16_t)pcb->dupacks, pcb->lastack,
00898                  ntohl(pcb->unacked->tcphdr->seqno)));
00899     tcp_rexmit(pcb);
00900 
00901     /* Set ssthresh to half of the minimum of the current
00902      * cwnd and the advertised window */
00903     if (pcb->cwnd > pcb->snd_wnd)
00904       pcb->ssthresh = pcb->snd_wnd / 2;
00905     else
00906       pcb->ssthresh = pcb->cwnd / 2;
00907     
00908     /* The minimum value for ssthresh should be 2 MSS */
00909     if (pcb->ssthresh < 2*pcb->mss) {
00910       LWIP_DEBUGF(TCP_FR_DEBUG, 
00911                   ("tcp_receive: The minimum value for ssthresh %"U16_F
00912                    " should be min 2 mss %"U16_F"...\n",
00913                    pcb->ssthresh, 2*pcb->mss));
00914       pcb->ssthresh = 2*pcb->mss;
00915     }
00916     
00917     pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
00918     pcb->flags |= TF_INFR;
00919   } 
00920 }
00921 
00922 
00923 /**
00924  * Send keepalive packets to keep a connection active although
00925  * no data is sent over it.
00926  *
00927  * Called by tcp_slowtmr()
00928  *
00929  * @param pcb the tcp_pcb for which to send a keepalive packet
00930  */
00931 void
00932 tcp_keepalive(struct tcp_pcb *pcb)
00933 {
00934   struct pbuf *p;
00935   struct tcp_hdr *tcphdr;
00936 
00937   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00938                           ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00939                           ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00940 
00941   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
00942                           tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
00943    
00944   p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00945    
00946   if(p == NULL) {
00947     LWIP_DEBUGF(TCP_DEBUG, 
00948                 ("tcp_keepalive: could not allocate memory for pbuf\n"));
00949     return;
00950   }
00951   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
00952               (p->len >= sizeof(struct tcp_hdr)));
00953 
00954   tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
00955 
00956 #if CHECKSUM_GEN_TCP
00957   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
00958                                       IP_PROTO_TCP, p->tot_len);
00959 #endif
00960   TCP_STATS_INC(tcp.xmit);
00961 
00962   /* Send output to IP */
00963 #if LWIP_NETIF_HWADDRHINT
00964   ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
00965     &(pcb->addr_hint));
00966 #else /* LWIP_NETIF_HWADDRHINT*/
00967   ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
00968 #endif /* LWIP_NETIF_HWADDRHINT*/
00969 
00970   pbuf_free(p);
00971 
00972   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
00973                           pcb->snd_nxt - 1, pcb->rcv_nxt));
00974 }
00975 
00976 
00977 /**
00978  * Send persist timer zero-window probes to keep a connection active
00979  * when a window update is lost.
00980  *
00981  * Called by tcp_slowtmr()
00982  *
00983  * @param pcb the tcp_pcb for which to send a zero-window probe packet
00984  */
00985 void
00986 tcp_zero_window_probe(struct tcp_pcb *pcb)
00987 {
00988   struct pbuf *p;
00989   struct tcp_hdr *tcphdr;
00990   struct tcp_seg *seg;
00991   u16_t len;
00992   u8_t is_fin;
00993 
00994   LWIP_DEBUGF(TCP_DEBUG, 
00995               ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
00996                U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00997                ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
00998                ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
00999 
01000   LWIP_DEBUGF(TCP_DEBUG, 
01001               ("tcp_zero_window_probe: tcp_ticks %"U32_F
01002                "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
01003                tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
01004 
01005   seg = pcb->unacked;
01006 
01007   if(seg == NULL)
01008     seg = pcb->unsent;
01009 
01010   if(seg == NULL)
01011     return;
01012 
01013   is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
01014   len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
01015 
01016   p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
01017   if(p == NULL) {
01018     LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
01019     return;
01020   }
01021   LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
01022               (p->len >= sizeof(struct tcp_hdr)));
01023 
01024   tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
01025 
01026   if (is_fin) {
01027     /* FIN segment, no data */
01028     TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
01029   } else {
01030     /* Data segment, copy in one byte from the head of the unacked queue */
01031     *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
01032   }
01033 
01034 #if CHECKSUM_GEN_TCP
01035   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
01036                                       IP_PROTO_TCP, p->tot_len);
01037 #endif
01038   TCP_STATS_INC(tcp.xmit);
01039 
01040   /* Send output to IP */
01041 #if LWIP_NETIF_HWADDRHINT
01042   ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
01043     &(pcb->addr_hint));
01044 #else /* LWIP_NETIF_HWADDRHINT*/
01045   ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
01046 #endif /* LWIP_NETIF_HWADDRHINT*/
01047 
01048   pbuf_free(p);
01049 
01050   LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
01051                           " ackno %"U32_F".\n",
01052                           pcb->snd_nxt - 1, pcb->rcv_nxt));
01053 }
01054 #endif /* LWIP_TCP */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines