source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/libraries/WiFi/extras/wifiHD/src/SOFTWARE_FRAMEWORK/SERVICES/LWIP/lwip-1.3.2/src/core/tcp_out.c @ 46

Last change on this file since 46 was 46, checked in by jrpelegrina, 4 years ago

First release to Xenial

File size: 35.0 KB
Line 
1/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3/**
4 * @file
5 * Transmission Control Protocol, outgoing traffic
6 *
7 * The output functions of TCP.
8 *
9 */
10
11/*
12 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without modification,
16 * are permitted provided that the following conditions are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright notice,
19 *    this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright notice,
21 *    this list of conditions and the following disclaimer in the documentation
22 *    and/or other materials provided with the distribution.
23 * 3. The name of the author may not be used to endorse or promote products
24 *    derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
29 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 *
37 * This file is part of the lwIP TCP/IP stack.
38 *
39 * Author: Adam Dunkels <adam@sics.se>
40 *
41 */
42
43#include "lwip/opt.h"
44
45#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
46
47#include "lwip/tcp.h"
48#include "lwip/def.h"
49#include "lwip/mem.h"
50#include "lwip/memp.h"
51#include "lwip/sys.h"
52#include "lwip/ip_addr.h"
53#include "lwip/netif.h"
54#include "lwip/inet.h"
55#include "lwip/inet_chksum.h"
56#include "lwip/stats.h"
57#include "lwip/snmp.h"
58
59#include <string.h>
60#define _TEST_HD_
61/* Forward declarations.*/
62static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
63
64static struct tcp_hdr *
65tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen,
66                      u32_t seqno_be /* already in network byte order */)
67{
68  struct tcp_hdr *tcphdr = p->payload;
69  tcphdr->src = htons(pcb->local_port);
70  tcphdr->dest = htons(pcb->remote_port);
71  tcphdr->seqno = seqno_be;
72  tcphdr->ackno = htonl(pcb->rcv_nxt);
73  TCPH_FLAGS_SET(tcphdr, TCP_ACK);
74  tcphdr->wnd = htons(pcb->rcv_ann_wnd);
75  tcphdr->urgp = 0;
76  TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4));
77  tcphdr->chksum = 0;
78
79  /* If we're sending a packet, update the announced right window edge */
80  pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
81
82  return tcphdr;
83}
84
85/**
86 * Called by tcp_close() to send a segment including flags but not data.
87 *
88 * @param pcb the tcp_pcb over which to send a segment
89 * @param flags the flags to set in the segment header
90 * @return ERR_OK if sent, another err_t otherwise
91 */
92err_t
93tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
94{
95  /* no data, no length, flags, copy=1, no optdata */
96  return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
97}
98
99/**
100 * Write data for sending (but does not send it immediately).
101 *
102 * It waits in the expectation of more data being sent soon (as
103 * it can send them more efficiently by combining them together).
104 * To prompt the system to send data now, call tcp_output() after
105 * calling tcp_write().
106 *
107 * @param pcb Protocol control block of the TCP connection to enqueue data for.
108 * @param data pointer to the data to send
109 * @param len length (in bytes) of the data to send
110 * @param apiflags combination of following flags :
111 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
112 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
113 * @return ERR_OK if enqueued, another err_t on error
114 *
115 * @see tcp_write()
116 */
117err_t
118tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
119{
120  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
121    data, len, (u16_t)apiflags));
122  /* connection is in valid state for data transmission? */
123  if (pcb->state == ESTABLISHED ||
124     pcb->state == CLOSE_WAIT ||
125     pcb->state == SYN_SENT ||
126     pcb->state == SYN_RCVD) {
127    if (len > 0) {
128#if LWIP_TCP_TIMESTAMPS
129      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 
130                         pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
131#else
132      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
133#endif
134    }
135    return ERR_OK;
136  } else {
137    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
138    return ERR_CONN;
139  }
140}
141
142/**
143 * Enqueue data and/or TCP options for transmission
144 *
145 * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write().
146 *
147 * @param pcb Protocol control block for the TCP connection to enqueue data for.
148 * @param arg Pointer to the data to be enqueued for sending.
149 * @param len Data length in bytes
150 * @param flags tcp header flags to set in the outgoing segment
151 * @param apiflags combination of following flags :
152 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
153 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
154 * @param optflags options to include in segment later on (see definition of struct tcp_seg)
155 */
156err_t
157tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
158            u8_t flags, u8_t apiflags, u8_t optflags)
159{
160  struct pbuf *p;
161  struct tcp_seg *seg, *useg, *queue;
162  u32_t seqno;
163  u16_t left, seglen;
164  void *ptr;
165  u16_t queuelen;
166  u8_t optlen;
167
168  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
169              ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n",
170               (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags));
171  LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)",
172             ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)),
173             return ERR_ARG;);
174  LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)", 
175             ((len != 0) || (arg == NULL)), return ERR_ARG;);
176
177  /* fail on too much data */
178  if (len > pcb->snd_buf) {
179    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
180      ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
181    pcb->flags |= TF_NAGLEMEMERR;
182    return ERR_MEM;
183  }
184  left = len;
185  ptr = arg;
186
187  optlen = LWIP_TCP_OPT_LENGTH(optflags);
188
189  /* seqno will be the sequence number of the first segment enqueued
190   * by the call to this function. */
191  seqno = pcb->snd_lbb;
192
193  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
194
195  /* If total number of pbufs on the unsent/unacked queues exceeds the
196   * configured maximum, return an error */
197  queuelen = pcb->snd_queuelen;
198  /* check for configured max queuelen and possible overflow */
199  if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
200    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING,
201      ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
202    TCP_STATS_INC(tcp.memerr);
203    pcb->flags |= TF_NAGLEMEMERR;
204    return ERR_MEM;
205  }
206  if (queuelen != 0) {
207    LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
208      pcb->unacked != NULL || pcb->unsent != NULL);
209  } else {
210    LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
211      pcb->unacked == NULL && pcb->unsent == NULL);
212  }
213
214  /* First, break up the data into segments and tuck them together in
215   * the local "queue" variable. */
216  useg = queue = seg = NULL;
217  seglen = 0;
218  while (queue == NULL || left > 0) {
219    /* The segment length (including options) should be at most the MSS */
220    seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left;
221
222    /* Allocate memory for tcp_seg, and fill in fields. */
223    seg = memp_malloc(MEMP_TCP_SEG);
224    if (seg == NULL) {
225      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
226                  ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
227      goto memerr;
228    }
229    seg->next = NULL;
230    seg->p = NULL;
231
232    /* first segment of to-be-queued data? */
233    if (queue == NULL) {
234      queue = seg;
235    }
236    /* subsequent segments of to-be-queued data */
237    else {
238      /* Attach the segment to the end of the queued segments */
239      LWIP_ASSERT("useg != NULL", useg != NULL);
240      useg->next = seg;
241    }
242    /* remember last segment of to-be-queued data for next iteration */
243    useg = seg;
244
245    /* If copy is set, memory should be allocated
246     * and data copied into pbuf, otherwise data comes from
247     * ROM or other static memory, and need not be copied.  */
248    if (apiflags & TCP_WRITE_FLAG_COPY) {
249      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) {
250        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
251                    ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
252        goto memerr;
253      }
254      LWIP_ASSERT("check that first pbuf can hold the complete seglen",
255                  (seg->p->len >= seglen + optlen));
256      queuelen += pbuf_clen(seg->p);
257      if (arg != NULL) {
258        MEMCPY((char *)seg->p->payload + optlen, ptr, seglen);
259      }
260      seg->dataptr = seg->p->payload;
261    }
262    /* do not copy data */
263    else {
264      /* First, allocate a pbuf for the headers. */
265      if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
266        LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
267                    ("tcp_enqueue: could not allocate memory for header pbuf\n"));
268        goto memerr;
269      }
270      queuelen += pbuf_clen(seg->p);
271
272      /* Second, allocate a pbuf for holding the data.
273       * since the referenced data is available at least until it is sent out on the
274       * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
275       * instead of PBUF_REF here.
276       */
277      if (left > 0) {
278        if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
279          /* If allocation fails, we have to deallocate the header pbuf as well. */
280          pbuf_free(seg->p);
281          seg->p = NULL;
282          LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 
283                      ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
284          goto memerr;
285        }
286        ++queuelen;
287        /* reference the non-volatile payload data */
288        p->payload = ptr;
289        seg->dataptr = ptr;
290
291        /* Concatenate the headers and data pbufs together. */
292        pbuf_cat(seg->p/*header*/, p/*data*/);
293        p = NULL;
294      }
295    }
296
297    /* Now that there are more segments queued, we check again if the
298    length of the queue exceeds the configured maximum or overflows. */
299    if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
300      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
301        ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
302      goto memerr;
303    }
304
305    seg->len = seglen;
306
307    /* build TCP header */
308    if (pbuf_header(seg->p, TCP_HLEN)) {
309      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
310      TCP_STATS_INC(tcp.err);
311      goto memerr;
312    }
313    seg->tcphdr = seg->p->payload;
314    seg->tcphdr->src = htons(pcb->local_port);
315    seg->tcphdr->dest = htons(pcb->remote_port);
316    seg->tcphdr->seqno = htonl(seqno);
317    seg->tcphdr->urgp = 0;
318    TCPH_FLAGS_SET(seg->tcphdr, flags);
319    /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
320
321    seg->flags = optflags;
322
323    /* Set the length of the header */
324    TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
325    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
326      ntohl(seg->tcphdr->seqno),
327      ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
328      (u16_t)flags));
329
330    left -= seglen;
331    seqno += seglen;
332    ptr = (void *)((u8_t *)ptr + seglen);
333  }
334
335  /* Now that the data to be enqueued has been broken up into TCP
336  segments in the queue variable, we add them to the end of the
337  pcb->unsent queue. */
338  if (pcb->unsent == NULL) {
339    useg = NULL;
340  }
341  else {
342    for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
343  }
344  /* { useg is last segment on the unsent queue, NULL if list is empty } */
345
346  /* If there is room in the last pbuf on the unsent queue,
347  chain the first pbuf on the queue together with that. */
348  if (useg != NULL &&
349    TCP_TCPLEN(useg) != 0 &&
350    !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
351    (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) &&
352    /* fit within max seg size */
353    (useg->len + queue->len <= pcb->mss) &&
354    /* only concatenate segments with the same options */
355    (useg->flags == queue->flags) &&
356    /* segments are consecutive */
357    (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) {
358    /* Remove TCP header from first segment of our to-be-queued list */
359    if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) {
360      /* Can we cope with this failing?  Just assert for now */
361      LWIP_ASSERT("pbuf_header failed\n", 0);
362      TCP_STATS_INC(tcp.err);
363      goto memerr;
364    }
365    if (queue->p->len == 0) {
366      /* free the first (header-only) pbuf if it is now empty (contained only headers) */
367      struct pbuf *old_q = queue->p;
368      queue->p = queue->p->next;
369      old_q->next = NULL;
370      queuelen--;
371      pbuf_free(old_q);
372    }
373    if (flags & TCP_FIN) {
374      /* the new segment contains only FIN, no data -> put the FIN into the last segment */
375      LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0);
376      TCPH_SET_FLAG(useg->tcphdr, TCP_FIN);
377    } else {
378      LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0));
379      pbuf_cat(useg->p, queue->p);
380      useg->len += queue->len;
381      useg->next = queue->next;
382    }
383
384    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
385    if (seg == queue) {
386      seg = useg;
387      seglen = useg->len;
388    }
389    memp_free(MEMP_TCP_SEG, queue);
390  }
391  else {
392    /* empty list */
393    if (useg == NULL) {
394      /* initialize list with this segment */
395      pcb->unsent = queue;
396    }
397    /* enqueue segment */
398    else {
399      useg->next = queue;
400    }
401  }
402  if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
403    ++len;
404  }
405  if (flags & TCP_FIN) {
406    pcb->flags |= TF_FIN;
407  }
408  pcb->snd_lbb += len;
409
410  pcb->snd_buf -= len;
411
412  /* update number of segments on the queues */
413  pcb->snd_queuelen = queuelen;
414  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
415  if (pcb->snd_queuelen != 0) {
416    LWIP_ASSERT("tcp_enqueue: valid queue length",
417      pcb->unacked != NULL || pcb->unsent != NULL);
418  }
419
420  /* Set the PSH flag in the last segment that we enqueued, but only
421  if the segment has data (indicated by seglen > 0). */
422  if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {
423    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
424  }
425
426  return ERR_OK;
427memerr:
428  pcb->flags |= TF_NAGLEMEMERR;
429  TCP_STATS_INC(tcp.memerr);
430
431  if (queue != NULL) {
432    tcp_segs_free(queue);
433  }
434  if (pcb->snd_queuelen != 0) {
435    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
436      pcb->unsent != NULL);
437  }
438  LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
439  return ERR_MEM;
440}
441
442
443#if LWIP_TCP_TIMESTAMPS
444/* Build a timestamp option (12 bytes long) at the specified options pointer)
445 *
446 * @param pcb tcp_pcb
447 * @param opts option pointer where to store the timestamp option
448 */
449static void
450tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
451{
452  /* Pad with two NOP options to make everything nicely aligned */
453  opts[0] = htonl(0x0101080A);
454  opts[1] = htonl(sys_now());
455  opts[2] = htonl(pcb->ts_recent);
456}
457#endif
458
459/** Send an ACK without data.
460 *
461 * @param pcb Protocol control block for the TCP connection to send the ACK
462 */
463err_t
464tcp_send_empty_ack(struct tcp_pcb *pcb)
465{
466  struct pbuf *p;
467  struct tcp_hdr *tcphdr;
468  u8_t optlen = 0;
469
470#if LWIP_TCP_TIMESTAMPS
471  if (pcb->flags & TF_TIMESTAMP) {
472    optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS);
473  }
474#endif
475  p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM);
476  if (p == NULL) {
477    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
478    return ERR_BUF;
479  }
480  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, 
481              ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
482  /* remove ACK flags from the PCB, as we send an empty ACK now */
483  pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
484
485  tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt));
486
487  /* NB. MSS option is only sent on SYNs, so ignore it here */
488#if LWIP_TCP_TIMESTAMPS
489  pcb->ts_lastacksent = pcb->rcv_nxt;
490
491  if (pcb->flags & TF_TIMESTAMP) {
492    tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
493  }
494#endif
495
496#if CHECKSUM_GEN_TCP
497  tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
498        IP_PROTO_TCP, p->tot_len);
499#endif
500#if LWIP_NETIF_HWADDRHINT
501  ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
502      IP_PROTO_TCP, &(pcb->addr_hint));
503#else /* LWIP_NETIF_HWADDRHINT*/
504  ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
505      IP_PROTO_TCP);
506#endif /* LWIP_NETIF_HWADDRHINT*/
507  pbuf_free(p);
508
509  return ERR_OK;
510}
511
512/**
513 * Find out what we can send and send it
514 *
515 * @param pcb Protocol control block for the TCP connection to send data
516 * @return ERR_OK if data has been sent or nothing to send
517 *         another err_t on error
518 */
519err_t
520tcp_output(struct tcp_pcb *pcb)
521{
522  struct tcp_seg *seg, *useg;
523  u32_t wnd, snd_nxt;
524#if TCP_CWND_DEBUG
525  s16_t i = 0;
526#endif /* TCP_CWND_DEBUG */
527
528  /* First, check if we are invoked by the TCP input processing
529     code. If so, we do not output anything. Instead, we rely on the
530     input processing code to call us when input processing is done
531     with. */
532  if (tcp_input_pcb == pcb) {
533    return ERR_OK;
534  }
535
536  wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
537
538  seg = pcb->unsent;
539
540  /* If the TF_ACK_NOW flag is set and no data will be sent (either
541   * because the ->unsent queue is empty or because the window does
542   * not allow it), construct an empty ACK segment and send it.
543   *
544   * If data is to be sent, we will just piggyback the ACK (see below).
545   */
546  if (pcb->flags & TF_ACK_NOW &&
547     (seg == NULL ||
548      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
549     return tcp_send_empty_ack(pcb);
550  }
551
552  /* useg should point to last segment on unacked queue */
553  useg = pcb->unacked;
554  if (useg != NULL) {
555    for (; useg->next != NULL; useg = useg->next);
556  }
557
558#if TCP_OUTPUT_DEBUG
559  if (seg == NULL) {
560    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n",
561                                   (void*)pcb->unsent));
562  }
563#endif /* TCP_OUTPUT_DEBUG */
564#if TCP_CWND_DEBUG
565  if (seg == NULL) {
566    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F
567                                 ", cwnd %"U16_F", wnd %"U32_F
568                                 ", seg == NULL, ack %"U32_F"\n",
569                                 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
570  } else {
571    LWIP_DEBUGF(TCP_CWND_DEBUG, 
572                ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F
573                 ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
574                 pcb->snd_wnd, pcb->cwnd, wnd,
575                 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
576                 ntohl(seg->tcphdr->seqno), pcb->lastack));
577  }
578#endif /* TCP_CWND_DEBUG */
579  /* data available and window allows it to be sent? */
580  while (seg != NULL &&
581         ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
582    LWIP_ASSERT("RST not expected here!", 
583                (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
584    /* Stop sending if the nagle algorithm would prevent it
585     * Don't stop:
586     * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or
587     * - if FIN was already enqueued for this PCB (SYN is always alone in a segment -
588     *   either seg->next != NULL or pcb->unacked == NULL;
589     *   RST is no sent using tcp_enqueue/tcp_output.
590     */
591    if((tcp_do_output_nagle(pcb) == 0) &&
592      ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
593      break;
594    }
595#if TCP_CWND_DEBUG
596    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",
597                            pcb->snd_wnd, pcb->cwnd, wnd,
598                            ntohl(seg->tcphdr->seqno) + seg->len -
599                            pcb->lastack,
600                            ntohl(seg->tcphdr->seqno), pcb->lastack, i));
601    ++i;
602#endif /* TCP_CWND_DEBUG */
603
604    pcb->unsent = seg->next;
605
606    if (pcb->state != SYN_SENT) {
607      TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
608      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
609    }
610
611    tcp_output_segment(seg, pcb);
612    snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
613    if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
614      pcb->snd_nxt = snd_nxt;
615    }
616    /* put segment on unacknowledged list if length > 0 */
617    if (TCP_TCPLEN(seg) > 0) {
618      seg->next = NULL;
619      /* unacked list is empty? */
620      if (pcb->unacked == NULL) {
621        pcb->unacked = seg;
622        useg = seg;
623      /* unacked list is not empty? */
624      } else {
625        /* In the case of fast retransmit, the packet should not go to the tail
626         * of the unacked queue, but rather somewhere before it. We need to check for
627         * this case. -STJ Jul 27, 2004 */
628        if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
629          /* add segment to before tail of unacked list, keeping the list sorted */
630          struct tcp_seg **cur_seg = &(pcb->unacked);
631          while (*cur_seg &&
632            TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
633              cur_seg = &((*cur_seg)->next );
634          }
635          seg->next = (*cur_seg);
636          (*cur_seg) = seg;
637        } else {
638          /* add segment to tail of unacked list */
639          useg->next = seg;
640          useg = useg->next;
641        }
642      }
643    /* do not queue empty segments on the unacked list */
644    } else {
645      tcp_seg_free(seg);
646    }
647    seg = pcb->unsent;
648  }
649
650  if (seg != NULL && pcb->persist_backoff == 0 && 
651      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
652    /* prepare for persist timer */
653    pcb->persist_cnt = 0;
654    pcb->persist_backoff = 1;
655  }
656
657  pcb->flags &= ~TF_NAGLEMEMERR;
658  return ERR_OK;
659}
660
661/**
662 * Called by tcp_output() to actually send a TCP segment over IP.
663 *
664 * @param seg the tcp_seg to send
665 * @param pcb the tcp_pcb for the TCP connection used to send the segment
666 */
667static void
668tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
669{
670  u16_t len;
671  struct netif *netif;
672  u32_t *opts;
673
674  /** @bug Exclude retransmitted segments from this count. */
675  snmp_inc_tcpoutsegs();
676
677  /* The TCP header has already been constructed, but the ackno and
678   wnd fields remain. */
679  seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
680
681  /* advertise our receive window size in this TCP segment */
682  seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
683
684  pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
685
686  /* Add any requested options.  NB MSS option is only set on SYN
687     packets, so ignore it here */
688  opts = (u32_t *)(seg->tcphdr + 1);
689  if (seg->flags & TF_SEG_OPTS_MSS) {
690    TCP_BUILD_MSS_OPTION(*opts);
691    opts += 1;
692  }
693#if LWIP_TCP_TIMESTAMPS
694  pcb->ts_lastacksent = pcb->rcv_nxt;
695
696  if (seg->flags & TF_SEG_OPTS_TS) {
697    tcp_build_timestamp_option(pcb, opts);
698    opts += 3;
699  }
700#endif
701
702#ifdef _TEST_HD_
703  /* ANGR: set rtime this _before_ checking ip_route(). Otherwise TCP_SYN will
704   * not be retransmitted in case the interface was down and tcp_connect()
705   * will not return any error. Since we still want the err_cb() (or maybe
706   * the wifi link comes up), make sure that we fulfill the retransmissions in
707   * tcp_slowtmr()
708   */
709
710  /* Set retransmission timer running if it is not currently enabled */
711  if(pcb->rtime == -1)
712    pcb->rtime = 0;
713#endif
714
715  /* If we don't have a local IP address, we get one by
716     calling ip_route(). */
717  if (ip_addr_isany(&(pcb->local_ip))) {
718    netif = ip_route(&(pcb->remote_ip));
719    if (netif == NULL) {
720      return;
721    }
722    ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
723  }
724
725#ifndef _TEST_HD_
726  //Set retransmission timer running if it is not currently enabled
727  if(pcb->rtime == -1)
728    pcb->rtime = 0;
729#endif
730
731  if (pcb->rttest == 0) {
732    pcb->rttest = tcp_ticks;
733    pcb->rtseq = ntohl(seg->tcphdr->seqno);
734
735    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
736  }
737  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
738          htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
739          seg->len));
740
741  len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
742
743  seg->p->len -= len;
744  seg->p->tot_len -= len;
745
746  seg->p->payload = seg->tcphdr;
747
748  seg->tcphdr->chksum = 0;
749#if CHECKSUM_GEN_TCP
750  seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
751             &(pcb->local_ip),
752             &(pcb->remote_ip),
753             IP_PROTO_TCP, seg->p->tot_len);
754#endif
755  TCP_STATS_INC(tcp.xmit);
756
757#if LWIP_NETIF_HWADDRHINT
758  ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
759      IP_PROTO_TCP, &(pcb->addr_hint));
760#else /* LWIP_NETIF_HWADDRHINT*/
761  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
762      IP_PROTO_TCP);
763#endif /* LWIP_NETIF_HWADDRHINT*/
764}
765
766/**
767 * Send a TCP RESET packet (empty segment with RST flag set) either to
768 * abort a connection or to show that there is no matching local connection
769 * for a received segment.
770 *
771 * Called by tcp_abort() (to abort a local connection), tcp_input() (if no
772 * matching local pcb was found), tcp_listen_input() (if incoming segment
773 * has ACK flag set) and tcp_process() (received segment in the wrong state)
774 *
775 * Since a RST segment is in most cases not sent for an active connection,
776 * tcp_rst() has a number of arguments that are taken from a tcp_pcb for
777 * most other segment output functions.
778 *
779 * @param seqno the sequence number to use for the outgoing segment
780 * @param ackno the acknowledge number to use for the outgoing segment
781 * @param local_ip the local IP address to send the segment from
782 * @param remote_ip the remote IP address to send the segment to
783 * @param local_port the local TCP port to send the segment from
784 * @param remote_port the remote TCP port to send the segment to
785 */
786void
787tcp_rst(u32_t seqno, u32_t ackno,
788  struct ip_addr *local_ip, struct ip_addr *remote_ip,
789  u16_t local_port, u16_t remote_port)
790{
791  struct pbuf *p;
792  struct tcp_hdr *tcphdr;
793  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
794  if (p == NULL) {
795      LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
796      return;
797  }
798  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
799              (p->len >= sizeof(struct tcp_hdr)));
800
801  tcphdr = p->payload;
802  tcphdr->src = htons(local_port);
803  tcphdr->dest = htons(remote_port);
804  tcphdr->seqno = htonl(seqno);
805  tcphdr->ackno = htonl(ackno);
806  TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
807  tcphdr->wnd = htons(TCP_WND);
808  tcphdr->urgp = 0;
809  TCPH_HDRLEN_SET(tcphdr, 5);
810
811  tcphdr->chksum = 0;
812#if CHECKSUM_GEN_TCP
813  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
814              IP_PROTO_TCP, p->tot_len);
815#endif
816  TCP_STATS_INC(tcp.xmit);
817  snmp_inc_tcpoutrsts();
818   /* Send output with hardcoded TTL since we have no access to the pcb */
819  ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
820  pbuf_free(p);
821  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
822}
823
824/**
825 * Requeue all unacked segments for retransmission
826 *
827 * Called by tcp_slowtmr() for slow retransmission.
828 *
829 * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
830 */
831void
832tcp_rexmit_rto(struct tcp_pcb *pcb)
833{
834  struct tcp_seg *seg;
835
836  if (pcb->unacked == NULL) {
837    return;
838  }
839
840  /* Move all unacked segments to the head of the unsent queue */
841  for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
842  /* concatenate unsent queue after unacked queue */
843  seg->next = pcb->unsent;
844  /* unsent queue is the concatenated queue (of unacked, unsent) */
845  pcb->unsent = pcb->unacked;
846  /* unacked queue is now empty */
847  pcb->unacked = NULL;
848
849  /* increment number of retransmissions */
850  ++pcb->nrtx;
851
852  /* Don't take any RTT measurements after retransmitting. */
853  pcb->rttest = 0;
854
855  /* Do the actual retransmission */
856  tcp_output(pcb);
857}
858
859/**
860 * Requeue the first unacked segment for retransmission
861 *
862 * Called by tcp_receive() for fast retramsmit.
863 *
864 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
865 */
866void
867tcp_rexmit(struct tcp_pcb *pcb)
868{
869  struct tcp_seg *seg;
870  struct tcp_seg **cur_seg;
871
872  if (pcb->unacked == NULL) {
873    return;
874  }
875
876  /* Move the first unacked segment to the unsent queue */
877  /* Keep the unsent queue sorted. */
878  seg = pcb->unacked;
879  pcb->unacked = seg->next;
880
881  cur_seg = &(pcb->unsent);
882  while (*cur_seg &&
883    TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
884      cur_seg = &((*cur_seg)->next );
885  }
886  seg->next = *cur_seg;
887  *cur_seg = seg;
888
889  ++pcb->nrtx;
890
891  /* Don't take any rtt measurements after retransmitting. */
892  pcb->rttest = 0;
893
894  /* Do the actual retransmission. */
895  snmp_inc_tcpretranssegs();
896  /* No need to call tcp_output: we are always called from tcp_input()
897     and thus tcp_output directly returns. */
898}
899
900
901/**
902 * Handle retransmission after three dupacks received
903 *
904 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
905 */
906void 
907tcp_rexmit_fast(struct tcp_pcb *pcb)
908{
909  if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
910    /* This is fast retransmit. Retransmit the first unacked segment. */
911    LWIP_DEBUGF(TCP_FR_DEBUG, 
912                ("tcp_receive: dupacks %"U16_F" (%"U32_F
913                 "), fast retransmit %"U32_F"\n",
914                 (u16_t)pcb->dupacks, pcb->lastack,
915                 ntohl(pcb->unacked->tcphdr->seqno)));
916    tcp_rexmit(pcb);
917
918    /* Set ssthresh to half of the minimum of the current
919     * cwnd and the advertised window */
920    if (pcb->cwnd > pcb->snd_wnd)
921      pcb->ssthresh = pcb->snd_wnd / 2;
922    else
923      pcb->ssthresh = pcb->cwnd / 2;
924   
925    /* The minimum value for ssthresh should be 2 MSS */
926    if (pcb->ssthresh < 2*pcb->mss) {
927      LWIP_DEBUGF(TCP_FR_DEBUG, 
928                  ("tcp_receive: The minimum value for ssthresh %"U16_F
929                   " should be min 2 mss %"U16_F"...\n",
930                   pcb->ssthresh, 2*pcb->mss));
931      pcb->ssthresh = 2*pcb->mss;
932    }
933   
934    pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
935    pcb->flags |= TF_INFR;
936  } 
937}
938
939
940/**
941 * Send keepalive packets to keep a connection active although
942 * no data is sent over it.
943 *
944 * Called by tcp_slowtmr()
945 *
946 * @param pcb the tcp_pcb for which to send a keepalive packet
947 */
948void
949tcp_keepalive(struct tcp_pcb *pcb)
950{
951  struct pbuf *p;
952  struct tcp_hdr *tcphdr;
953
954  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
955                          ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
956                          ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
957
958  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
959                          tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
960   
961  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
962   
963  if(p == NULL) {
964    LWIP_DEBUGF(TCP_DEBUG, 
965                ("tcp_keepalive: could not allocate memory for pbuf\n"));
966    return;
967  }
968  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
969              (p->len >= sizeof(struct tcp_hdr)));
970
971  tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1));
972
973#if CHECKSUM_GEN_TCP
974  tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
975                                      IP_PROTO_TCP, p->tot_len);
976#endif
977  TCP_STATS_INC(tcp.xmit);
978
979  /* Send output to IP */
980#if LWIP_NETIF_HWADDRHINT
981  ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
982    &(pcb->addr_hint));
983#else /* LWIP_NETIF_HWADDRHINT*/
984  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
985#endif /* LWIP_NETIF_HWADDRHINT*/
986
987  pbuf_free(p);
988
989  LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n",
990                          pcb->snd_nxt - 1, pcb->rcv_nxt));
991}
992
993
994/**
995 * Send persist timer zero-window probes to keep a connection active
996 * when a window update is lost.
997 *
998 * Called by tcp_slowtmr()
999 *
1000 * @param pcb the tcp_pcb for which to send a zero-window probe packet
1001 */
1002void
1003tcp_zero_window_probe(struct tcp_pcb *pcb)
1004{
1005  struct pbuf *p;
1006  struct tcp_hdr *tcphdr;
1007  struct tcp_seg *seg;
1008  u16_t len;
1009  u8_t is_fin;
1010
1011  LWIP_DEBUGF(TCP_DEBUG, 
1012              ("tcp_zero_window_probe: sending ZERO WINDOW probe to %"
1013               U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
1014               ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
1015               ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
1016
1017  LWIP_DEBUGF(TCP_DEBUG, 
1018              ("tcp_zero_window_probe: tcp_ticks %"U32_F
1019               "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", 
1020               tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1021
1022  seg = pcb->unacked;
1023
1024  if(seg == NULL)
1025    seg = pcb->unsent;
1026
1027  if(seg == NULL)
1028    return;
1029
1030  is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
1031  len = is_fin ? TCP_HLEN : TCP_HLEN + 1;
1032
1033  p = pbuf_alloc(PBUF_IP, len, PBUF_RAM);
1034  if(p == NULL) {
1035    LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
1036    return;
1037  }
1038  LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
1039              (p->len >= sizeof(struct tcp_hdr)));
1040
1041  tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno);
1042
1043  if (is_fin) {
1044    /* FIN segment, no data */
1045    TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
1046  } else {
1047    /* Data segment, copy in one byte from the head of the unacked queue */
1048    *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr;
1049  }
1050
1051#if CHECKSUM_GEN_TCP
1052  tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
1053                                      IP_PROTO_TCP, p->tot_len);
1054#endif
1055  TCP_STATS_INC(tcp.xmit);
1056
1057  /* Send output to IP */
1058#if LWIP_NETIF_HWADDRHINT
1059  ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
1060    &(pcb->addr_hint));
1061#else /* LWIP_NETIF_HWADDRHINT*/
1062  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
1063#endif /* LWIP_NETIF_HWADDRHINT*/
1064
1065  pbuf_free(p);
1066
1067  LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
1068                          " ackno %"U32_F".\n",
1069                          pcb->snd_nxt - 1, pcb->rcv_nxt));
1070}
1071#endif /* LWIP_TCP */
Note: See TracBrowser for help on using the repository browser.