4 * Transmission Control Protocol for IP
\r
6 * This file contains common functions for the TCP implementation, such as functinos
\r
7 * for manipulating the data structures and the TCP timer functions. TCP functions
\r
8 * related to input and output is found in tcp_in.c and tcp_out.c respectively.
\r
13 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
\r
14 * All rights reserved.
\r
16 * Redistribution and use in source and binary forms, with or without modification,
\r
17 * are permitted provided that the following conditions are met:
\r
19 * 1. Redistributions of source code must retain the above copyright notice,
\r
20 * this list of conditions and the following disclaimer.
\r
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
22 * this list of conditions and the following disclaimer in the documentation
\r
23 * and/or other materials provided with the distribution.
\r
24 * 3. The name of the author may not be used to endorse or promote products
\r
25 * derived from this software without specific prior written permission.
\r
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
\r
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
\r
30 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
\r
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
\r
32 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
\r
35 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
\r
38 * This file is part of the lwIP TCP/IP stack.
\r
40 * Author: Adam Dunkels <adam@sics.se>
\r
46 #include "lwip/opt.h"
\r
47 #include "lwip/def.h"
\r
48 #include "lwip/mem.h"
\r
49 #include "lwip/memp.h"
\r
51 #include "lwip/tcp.h"
\r
54 /* Incremented every coarse grained timer shot
\r
55 (typically every 500 ms, determined by TCP_COARSE_TIMEOUT). */
\r
57 const u8_t tcp_backoff[13] =
\r
58 { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
\r
60 /* The TCP PCB lists. */
\r
62 /** List of all TCP PCBs in LISTEN state */
\r
63 union tcp_listen_pcbs_t tcp_listen_pcbs;
\r
64 /** List of all TCP PCBs that are in a state in which
\r
65 * they accept or send data. */
\r
66 struct tcp_pcb *tcp_active_pcbs;
\r
67 /** List of all TCP PCBs in TIME-WAIT state */
\r
68 struct tcp_pcb *tcp_tw_pcbs;
\r
70 struct tcp_pcb *tcp_tmp_pcb;
\r
72 static u8_t tcp_timer;
\r
73 static u16_t tcp_new_port(void);
\r
76 * Initializes the TCP layer.
\r
81 /* Clear globals. */
\r
82 tcp_listen_pcbs.listen_pcbs = NULL;
\r
83 tcp_active_pcbs = NULL;
\r
87 /* initialize timer */
\r
94 * Called periodically to dispatch TCP timers.
\r
100 /* Call tcp_fasttmr() every 250 ms */
\r
103 if (++tcp_timer & 1) {
\r
104 /* Call tcp_tmr() every 500 ms, i.e., every other timer
\r
105 tcp_tmr() is called. */
\r
111 * Closes the connection held by the PCB.
\r
115 tcp_close(struct tcp_pcb *pcb)
\r
120 LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in state "));
\r
121 tcp_debug_print_state(pcb->state);
\r
122 LWIP_DEBUGF(TCP_DEBUG, ("\n"));
\r
123 #endif /* TCP_DEBUG */
\r
124 switch (pcb->state) {
\r
126 /* Closing a pcb in the CLOSED state might seem erroneous,
\r
127 * however, it is in this state once allocated and as yet unused
\r
128 * and the user needs some way to free it should the need arise.
\r
129 * Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
\r
130 * or for a pcb that has been used and then entered the CLOSED state
\r
131 * is erroneous, but this should never happen as the pcb has in those cases
\r
132 * been freed, and so any remaining handles are bogus. */
\r
134 memp_free(MEMP_TCP_PCB, pcb);
\r
139 tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
\r
140 memp_free(MEMP_TCP_PCB_LISTEN, pcb);
\r
145 tcp_pcb_remove(&tcp_active_pcbs, pcb);
\r
146 memp_free(MEMP_TCP_PCB, pcb);
\r
151 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
152 if (err == ERR_OK) {
\r
153 pcb->state = FIN_WAIT_1;
\r
157 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
158 if (err == ERR_OK) {
\r
159 pcb->state = LAST_ACK;
\r
163 /* Has already been closed, do nothing. */
\r
169 if (pcb != NULL && err == ERR_OK) {
\r
170 err = tcp_output(pcb);
\r
176 * Aborts a connection by sending a RST to the remote host and deletes
\r
177 * the local protocol control block. This is done when a connection is
\r
178 * killed because of shortage of memory.
\r
182 tcp_abort(struct tcp_pcb *pcb)
\r
184 u32_t seqno, ackno;
\r
185 u16_t remote_port, local_port;
\r
186 struct ip_addr remote_ip, local_ip;
\r
187 #if LWIP_CALLBACK_API
\r
188 void (* errf)(void *arg, err_t err);
\r
189 #endif /* LWIP_CALLBACK_API */
\r
193 /* Figure out on which TCP PCB list we are, and remove us. If we
\r
194 are in an active state, call the receive function associated with
\r
195 the PCB with a NULL argument, and send an RST to the remote end. */
\r
196 if (pcb->state == TIME_WAIT) {
\r
197 tcp_pcb_remove(&tcp_tw_pcbs, pcb);
\r
198 memp_free(MEMP_TCP_PCB, pcb);
\r
200 seqno = pcb->snd_nxt;
\r
201 ackno = pcb->rcv_nxt;
\r
202 ip_addr_set(&local_ip, &(pcb->local_ip));
\r
203 ip_addr_set(&remote_ip, &(pcb->remote_ip));
\r
204 local_port = pcb->local_port;
\r
205 remote_port = pcb->remote_port;
\r
206 #if LWIP_CALLBACK_API
\r
208 #endif /* LWIP_CALLBACK_API */
\r
209 errf_arg = pcb->callback_arg;
\r
210 tcp_pcb_remove(&tcp_active_pcbs, pcb);
\r
211 if (pcb->unacked != NULL) {
\r
212 tcp_segs_free(pcb->unacked);
\r
214 if (pcb->unsent != NULL) {
\r
215 tcp_segs_free(pcb->unsent);
\r
217 #if TCP_QUEUE_OOSEQ
\r
218 if (pcb->ooseq != NULL) {
\r
219 tcp_segs_free(pcb->ooseq);
\r
221 #endif /* TCP_QUEUE_OOSEQ */
\r
222 memp_free(MEMP_TCP_PCB, pcb);
\r
223 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
\r
224 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n"));
\r
225 tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
\r
230 * Binds the connection to a local portnumber and IP address. If the
\r
231 * IP address is not given (i.e., ipaddr == NULL), the IP address of
\r
232 * the outgoing network interface is used instead.
\r
237 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
\r
239 struct tcp_pcb *cpcb;
\r
242 port = tcp_new_port();
\r
244 /* Check if the address already is in use. */
\r
245 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
\r
246 cpcb != NULL; cpcb = cpcb->next) {
\r
247 if (cpcb->local_port == port) {
\r
248 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
249 ip_addr_isany(ipaddr) ||
\r
250 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
255 for(cpcb = tcp_active_pcbs;
\r
256 cpcb != NULL; cpcb = cpcb->next) {
\r
257 if (cpcb->local_port == port) {
\r
258 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
259 ip_addr_isany(ipaddr) ||
\r
260 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
266 if (!ip_addr_isany(ipaddr)) {
\r
267 pcb->local_ip = *ipaddr;
\r
269 pcb->local_port = port;
\r
270 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
\r
273 #if LWIP_CALLBACK_API
\r
275 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
\r
283 #endif /* LWIP_CALLBACK_API */
\r
286 * Set the state of the connection to be LISTEN, which means that it
\r
287 * is able to accept incoming connections. The protocol control block
\r
288 * is reallocated in order to consume less memory. Setting the
\r
289 * connection to LISTEN is an irreversible process.
\r
293 tcp_listen(struct tcp_pcb *pcb)
\r
295 struct tcp_pcb_listen *lpcb;
\r
297 /* already listening? */
\r
298 if (pcb->state == LISTEN) {
\r
301 lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
\r
302 if (lpcb == NULL) {
\r
305 lpcb->callback_arg = pcb->callback_arg;
\r
306 lpcb->local_port = pcb->local_port;
\r
307 lpcb->state = LISTEN;
\r
308 lpcb->so_options = pcb->so_options;
\r
309 lpcb->so_options |= SOF_ACCEPTCONN;
\r
310 lpcb->ttl = pcb->ttl;
\r
311 lpcb->tos = pcb->tos;
\r
312 ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
\r
313 memp_free(MEMP_TCP_PCB, pcb);
\r
314 #if LWIP_CALLBACK_API
\r
315 lpcb->accept = tcp_accept_null;
\r
316 #endif /* LWIP_CALLBACK_API */
\r
317 TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
\r
318 return (struct tcp_pcb *)lpcb;
\r
322 * This function should be called by the application when it has
\r
323 * processed the data. The purpose is to advertise a larger window
\r
324 * when the data has been processed.
\r
328 tcp_recved(struct tcp_pcb *pcb, u16_t len)
\r
330 if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
\r
331 pcb->rcv_wnd = TCP_WND;
\r
333 pcb->rcv_wnd += len;
\r
335 if (!(pcb->flags & TF_ACK_DELAY) &&
\r
336 !(pcb->flags & TF_ACK_NOW)) {
\r
338 * We send an ACK here (if one is not already pending, hence
\r
339 * the above tests) as tcp_recved() implies that the application
\r
340 * has processed some data, and so we can open the receiver's
\r
341 * window to allow more to be transmitted. This could result in
\r
342 * two ACKs being sent for each received packet in some limited cases
\r
343 * (where the application is only receiving data, and is slow to
\r
344 * process it) but it is necessary to guarantee that the sender can
\r
345 * continue to transmit.
\r
349 else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
\r
350 /* If we can send a window update such that there is a full
\r
351 * segment available in the window, do so now. This is sort of
\r
352 * nagle-like in its goals, and tries to hit a compromise between
\r
353 * sending acks each time the window is updated, and only sending
\r
354 * window updates when a timer expires. The "threshold" used
\r
355 * above (currently TCP_WND/2) can be tuned to be more or less
\r
360 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
\r
361 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
\r
365 * A nastly hack featuring 'goto' statements that allocates a
\r
366 * new TCP local port.
\r
371 struct tcp_pcb *pcb;
\r
372 #ifndef TCP_LOCAL_PORT_RANGE_START
\r
373 #define TCP_LOCAL_PORT_RANGE_START 4096
\r
374 #define TCP_LOCAL_PORT_RANGE_END 0x7fff
\r
376 static u16_t port = TCP_LOCAL_PORT_RANGE_START;
\r
379 if (++port > TCP_LOCAL_PORT_RANGE_END) {
\r
380 port = TCP_LOCAL_PORT_RANGE_START;
\r
383 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
384 if (pcb->local_port == port) {
\r
388 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
389 if (pcb->local_port == port) {
\r
393 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
394 if (pcb->local_port == port) {
\r
402 * Connects to another host. The function given as the "connected"
\r
403 * argument will be called when the connection has been established.
\r
407 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
\r
408 err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
\r
414 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
\r
415 if (ipaddr != NULL) {
\r
416 pcb->remote_ip = *ipaddr;
\r
420 pcb->remote_port = port;
\r
421 if (pcb->local_port == 0) {
\r
422 pcb->local_port = tcp_new_port();
\r
424 iss = tcp_next_iss();
\r
426 pcb->snd_nxt = iss;
\r
427 pcb->lastack = iss - 1;
\r
428 pcb->snd_lbb = iss - 1;
\r
429 pcb->rcv_wnd = TCP_WND;
\r
430 pcb->snd_wnd = TCP_WND;
\r
431 pcb->mss = TCP_MSS;
\r
433 pcb->ssthresh = pcb->mss * 10;
\r
434 pcb->state = SYN_SENT;
\r
435 #if LWIP_CALLBACK_API
\r
436 pcb->connected = connected;
\r
437 #endif /* LWIP_CALLBACK_API */
\r
438 TCP_REG(&tcp_active_pcbs, pcb);
\r
440 /* Build an MSS option */
\r
441 optdata = htonl(((u32_t)2 << 24) |
\r
442 ((u32_t)4 << 16) |
\r
443 (((u32_t)pcb->mss / 256) << 8) |
\r
446 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
\r
447 if (ret == ERR_OK) {
\r
454 * Called every 500 ms and implements the retransmission timer and the timer that
\r
455 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
\r
456 * various timers such as the inactivity timer in each PCB.
\r
461 struct tcp_pcb *pcb, *pcb2, *prev;
\r
463 u8_t pcb_remove; /* flag if a PCB should be removed */
\r
470 /* Steps through all of the active PCBs. */
\r
472 pcb = tcp_active_pcbs;
\r
474 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
\r
476 while (pcb != NULL) {
\r
477 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
\r
478 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
\r
479 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
\r
480 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
\r
484 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
\r
486 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
\r
488 else if (pcb->nrtx == TCP_MAXRTX) {
\r
490 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
\r
493 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
\r
495 /* Time for a retransmission. */
\r
496 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
\r
497 pcb->rtime, pcb->rto));
\r
499 /* Double retransmission time-out unless we are trying to
\r
500 * connect to somebody (i.e., we are in SYN_SENT). */
\r
501 if (pcb->state != SYN_SENT) {
\r
502 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
\r
504 /* Reduce congestion window and ssthresh. */
\r
505 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
\r
506 pcb->ssthresh = eff_wnd >> 1;
\r
507 if (pcb->ssthresh < pcb->mss) {
\r
508 pcb->ssthresh = pcb->mss * 2;
\r
510 pcb->cwnd = pcb->mss;
\r
511 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
\r
512 pcb->cwnd, pcb->ssthresh));
\r
514 /* The following needs to be called AFTER cwnd is set to one mss - STJ */
\r
515 tcp_rexmit_rto(pcb);
\r
518 /* Check if this PCB has stayed too long in FIN-WAIT-2 */
\r
519 if (pcb->state == FIN_WAIT_2) {
\r
520 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
521 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
523 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
\r
527 /* Check if KEEPALIVE should be sent */
\r
528 if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
\r
529 if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
\r
530 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
\r
531 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
\r
532 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
\r
536 else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
\r
537 tcp_keepalive(pcb);
\r
542 /* If this PCB has queued out of sequence data, but has been
\r
543 inactive for too long, will drop the data (it will eventually
\r
544 be retransmitted). */
\r
545 #if TCP_QUEUE_OOSEQ
\r
546 if (pcb->ooseq != NULL &&
\r
547 (u32_t)tcp_ticks - pcb->tmr >=
\r
548 pcb->rto * TCP_OOSEQ_TIMEOUT) {
\r
549 tcp_segs_free(pcb->ooseq);
\r
551 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
\r
553 #endif /* TCP_QUEUE_OOSEQ */
\r
555 /* Check if this PCB has stayed too long in SYN-RCVD */
\r
556 if (pcb->state == SYN_RCVD) {
\r
557 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
558 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
560 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
\r
564 /* Check if this PCB has stayed too long in LAST-ACK */
\r
565 if (pcb->state == LAST_ACK) {
\r
566 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
568 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
\r
572 /* If the PCB should be removed, do it. */
\r
574 tcp_pcb_purge(pcb);
\r
575 /* Remove PCB from tcp_active_pcbs list. */
\r
576 if (prev != NULL) {
\r
577 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
\r
578 prev->next = pcb->next;
\r
580 /* This PCB was the first. */
\r
581 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
\r
582 tcp_active_pcbs = pcb->next;
\r
585 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
\r
588 memp_free(MEMP_TCP_PCB, pcb);
\r
592 /* We check if we should poll the connection. */
\r
594 if (pcb->polltmr >= pcb->pollinterval) {
\r
596 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
\r
597 TCP_EVENT_POLL(pcb, err);
\r
598 if (err == ERR_OK) {
\r
609 /* Steps through all of the TIME-WAIT PCBs. */
\r
612 while (pcb != NULL) {
\r
613 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
616 /* Check if this PCB has stayed long enough in TIME-WAIT */
\r
617 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
623 /* If the PCB should be removed, do it. */
\r
625 tcp_pcb_purge(pcb);
\r
626 /* Remove PCB from tcp_tw_pcbs list. */
\r
627 if (prev != NULL) {
\r
628 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
\r
629 prev->next = pcb->next;
\r
631 /* This PCB was the first. */
\r
632 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
\r
633 tcp_tw_pcbs = pcb->next;
\r
636 memp_free(MEMP_TCP_PCB, pcb);
\r
646 * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
\r
651 struct tcp_pcb *pcb;
\r
653 /* send delayed ACKs */
\r
654 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
655 if (pcb->flags & TF_ACK_DELAY) {
\r
656 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
\r
658 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
664 * Deallocates a list of TCP segments (tcp_seg structures).
\r
668 tcp_segs_free(struct tcp_seg *seg)
\r
671 struct tcp_seg *next;
\r
672 while (seg != NULL) {
\r
674 count += tcp_seg_free(seg);
\r
681 * Frees a TCP segment.
\r
685 tcp_seg_free(struct tcp_seg *seg)
\r
690 if (seg->p != NULL) {
\r
691 count = pbuf_free(seg->p);
\r
694 #endif /* TCP_DEBUG */
\r
696 memp_free(MEMP_TCP_SEG, seg);
\r
702 * Sets the priority of a connection.
\r
706 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
\r
710 #if TCP_QUEUE_OOSEQ
\r
713 * Returns a copy of the given TCP segment.
\r
717 tcp_seg_copy(struct tcp_seg *seg)
\r
719 struct tcp_seg *cseg;
\r
721 cseg = memp_malloc(MEMP_TCP_SEG);
\r
722 if (cseg == NULL) {
\r
725 memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
\r
731 #if LWIP_CALLBACK_API
\r
733 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
\r
738 } else if (err == ERR_OK) {
\r
739 return tcp_close(pcb);
\r
743 #endif /* LWIP_CALLBACK_API */
\r
746 tcp_kill_prio(u8_t prio)
\r
748 struct tcp_pcb *pcb, *inactive;
\r
753 mprio = TCP_PRIO_MAX;
\r
755 /* We kill the oldest active connection that has lower priority than
\r
759 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
760 if (pcb->prio <= prio &&
\r
761 pcb->prio <= mprio &&
\r
762 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
763 inactivity = tcp_ticks - pcb->tmr;
\r
768 if (inactive != NULL) {
\r
769 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
\r
770 (void *)inactive, inactivity));
\r
771 tcp_abort(inactive);
\r
777 tcp_kill_timewait(void)
\r
779 struct tcp_pcb *pcb, *inactive;
\r
784 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
785 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
786 inactivity = tcp_ticks - pcb->tmr;
\r
790 if (inactive != NULL) {
\r
791 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
\r
792 (void *)inactive, inactivity));
\r
793 tcp_abort(inactive);
\r
800 tcp_alloc(u8_t prio)
\r
802 struct tcp_pcb *pcb;
\r
805 pcb = memp_malloc(MEMP_TCP_PCB);
\r
807 /* Try killing oldest connection in TIME-WAIT. */
\r
808 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
\r
809 tcp_kill_timewait();
\r
810 pcb = memp_malloc(MEMP_TCP_PCB);
\r
812 tcp_kill_prio(prio);
\r
813 pcb = memp_malloc(MEMP_TCP_PCB);
\r
817 memset(pcb, 0, sizeof(struct tcp_pcb));
\r
818 pcb->prio = TCP_PRIO_NORMAL;
\r
819 pcb->snd_buf = TCP_SND_BUF;
\r
820 pcb->snd_queuelen = 0;
\r
821 pcb->rcv_wnd = TCP_WND;
\r
823 pcb->ttl = TCP_TTL;
\r
824 pcb->mss = TCP_MSS;
\r
825 pcb->rto = 3000 / TCP_SLOW_INTERVAL;
\r
827 pcb->sv = 3000 / TCP_SLOW_INTERVAL;
\r
830 iss = tcp_next_iss();
\r
831 pcb->snd_wl2 = iss;
\r
832 pcb->snd_nxt = iss;
\r
833 pcb->snd_max = iss;
\r
834 pcb->lastack = iss;
\r
835 pcb->snd_lbb = iss;
\r
836 pcb->tmr = tcp_ticks;
\r
840 #if LWIP_CALLBACK_API
\r
841 pcb->recv = tcp_recv_null;
\r
842 #endif /* LWIP_CALLBACK_API */
\r
844 /* Init KEEPALIVE timer */
\r
845 pcb->keepalive = TCP_KEEPDEFAULT;
\r
852 * Creates a new TCP protocol control block but doesn't place it on
\r
853 * any of the TCP PCB lists.
\r
855 * @internal: Maybe there should be a idle TCP PCB list where these
\r
856 * PCBs are put on. We can then implement port reservation using
\r
857 * tcp_bind(). Currently, we lack this (BSD socket type of) feature.
\r
863 return tcp_alloc(TCP_PRIO_NORMAL);
\r
869 * Used to specify the argument that should be passed callback
\r
875 tcp_arg(struct tcp_pcb *pcb, void *arg)
\r
877 pcb->callback_arg = arg;
\r
879 #if LWIP_CALLBACK_API
\r
882 * Used to specify the function that should be called when a TCP
\r
883 * connection receives data.
\r
887 tcp_recv(struct tcp_pcb *pcb,
\r
888 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
\r
894 * Used to specify the function that should be called when TCP data
\r
895 * has been successfully delivered to the remote host.
\r
900 tcp_sent(struct tcp_pcb *pcb,
\r
901 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
\r
907 * Used to specify the function that should be called when a fatal error
\r
908 * has occured on the connection.
\r
912 tcp_err(struct tcp_pcb *pcb,
\r
913 void (* errf)(void *arg, err_t err))
\r
919 * Used for specifying the function that should be called when a
\r
920 * LISTENing connection has been connected to another host.
\r
924 tcp_accept(struct tcp_pcb *pcb,
\r
925 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
\r
927 ((struct tcp_pcb_listen *)pcb)->accept = accept;
\r
929 #endif /* LWIP_CALLBACK_API */
\r
933 * Used to specify the function that should be called periodically
\r
934 * from TCP. The interval is specified in terms of the TCP coarse
\r
935 * timer interval, which is called twice a second.
\r
939 tcp_poll(struct tcp_pcb *pcb,
\r
940 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
\r
942 #if LWIP_CALLBACK_API
\r
944 #endif /* LWIP_CALLBACK_API */
\r
945 pcb->pollinterval = interval;
\r
949 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
\r
953 tcp_pcb_purge(struct tcp_pcb *pcb)
\r
955 if (pcb->state != CLOSED &&
\r
956 pcb->state != TIME_WAIT &&
\r
957 pcb->state != LISTEN) {
\r
959 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
\r
961 if (pcb->unsent != NULL) {
\r
962 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
\r
964 if (pcb->unacked != NULL) {
\r
965 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
\r
967 #if TCP_QUEUE_OOSEQ /* LW */
\r
968 if (pcb->ooseq != NULL) {
\r
969 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
\r
972 tcp_segs_free(pcb->ooseq);
\r
974 #endif /* TCP_QUEUE_OOSEQ */
\r
975 tcp_segs_free(pcb->unsent);
\r
976 tcp_segs_free(pcb->unacked);
\r
977 pcb->unacked = pcb->unsent = NULL;
\r
982 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
\r
986 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
\r
988 TCP_RMV(pcblist, pcb);
\r
990 tcp_pcb_purge(pcb);
\r
992 /* if there is an outstanding delayed ACKs, send it */
\r
993 if (pcb->state != TIME_WAIT &&
\r
994 pcb->state != LISTEN &&
\r
995 pcb->flags & TF_ACK_DELAY) {
\r
996 pcb->flags |= TF_ACK_NOW;
\r
999 pcb->state = CLOSED;
\r
1001 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
\r
1005 * Calculates a new initial sequence number for new connections.
\r
1009 tcp_next_iss(void)
\r
1011 static u32_t iss = 6510;
\r
1013 iss += tcp_ticks; /* XXX */
\r
1017 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
\r
1019 tcp_debug_print(struct tcp_hdr *tcphdr)
\r
1021 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
\r
1022 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1023 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
\r
1024 ntohs(tcphdr->src), ntohs(tcphdr->dest)));
\r
1025 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1026 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
\r
1027 ntohl(tcphdr->seqno)));
\r
1028 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1029 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
\r
1030 ntohl(tcphdr->ackno)));
\r
1031 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1032 LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
\r
1033 TCPH_HDRLEN(tcphdr),
\r
1034 TCPH_FLAGS(tcphdr) >> 5 & 1,
\r
1035 TCPH_FLAGS(tcphdr) >> 4 & 1,
\r
1036 TCPH_FLAGS(tcphdr) >> 3 & 1,
\r
1037 TCPH_FLAGS(tcphdr) >> 2 & 1,
\r
1038 TCPH_FLAGS(tcphdr) >> 1 & 1,
\r
1039 TCPH_FLAGS(tcphdr) & 1,
\r
1040 ntohs(tcphdr->wnd)));
\r
1041 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
\r
1042 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
\r
1043 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1044 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
\r
1045 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
\r
1046 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1050 tcp_debug_print_state(enum tcp_state s)
\r
1052 LWIP_DEBUGF(TCP_DEBUG, ("State: "));
\r
1055 LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
\r
1058 LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
\r
1061 LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
\r
1064 LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
\r
1067 LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
\r
1070 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
\r
1073 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
\r
1076 LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
\r
1079 LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
\r
1082 LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
\r
1085 LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
\r
1091 tcp_debug_print_flags(u8_t flags)
\r
1093 if (flags & TCP_FIN) {
\r
1094 LWIP_DEBUGF(TCP_DEBUG, ("FIN "));
\r
1096 if (flags & TCP_SYN) {
\r
1097 LWIP_DEBUGF(TCP_DEBUG, ("SYN "));
\r
1099 if (flags & TCP_RST) {
\r
1100 LWIP_DEBUGF(TCP_DEBUG, ("RST "));
\r
1102 if (flags & TCP_PSH) {
\r
1103 LWIP_DEBUGF(TCP_DEBUG, ("PSH "));
\r
1105 if (flags & TCP_ACK) {
\r
1106 LWIP_DEBUGF(TCP_DEBUG, ("ACK "));
\r
1108 if (flags & TCP_URG) {
\r
1109 LWIP_DEBUGF(TCP_DEBUG, ("URG "));
\r
1111 if (flags & TCP_ECE) {
\r
1112 LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
\r
1114 if (flags & TCP_CWR) {
\r
1115 LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
\r
1120 tcp_debug_print_pcbs(void)
\r
1122 struct tcp_pcb *pcb;
\r
1123 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
\r
1124 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1125 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1126 pcb->local_port, pcb->remote_port,
\r
1127 pcb->snd_nxt, pcb->rcv_nxt));
\r
1128 tcp_debug_print_state(pcb->state);
\r
1130 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
\r
1131 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
1132 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1133 pcb->local_port, pcb->remote_port,
\r
1134 pcb->snd_nxt, pcb->rcv_nxt));
\r
1135 tcp_debug_print_state(pcb->state);
\r
1137 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
\r
1138 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1139 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1140 pcb->local_port, pcb->remote_port,
\r
1141 pcb->snd_nxt, pcb->rcv_nxt));
\r
1142 tcp_debug_print_state(pcb->state);
\r
1147 tcp_pcbs_sane(void)
\r
1149 struct tcp_pcb *pcb;
\r
1150 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1151 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
\r
1152 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
\r
1153 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
\r
1155 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1156 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
1160 #endif /* TCP_DEBUG */
\r
1161 #endif /* LWIP_TCP */
\r