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