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
241 int reuse_port_all_set = 1;
\r
242 #endif /* SO_REUSE */
\r
245 port = tcp_new_port();
\r
248 /* Check if the address already is in use. */
\r
249 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
\r
250 cpcb != NULL; cpcb = cpcb->next) {
\r
251 if (cpcb->local_port == port) {
\r
252 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
253 ip_addr_isany(ipaddr) ||
\r
254 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
259 for(cpcb = tcp_active_pcbs;
\r
260 cpcb != NULL; cpcb = cpcb->next) {
\r
261 if (cpcb->local_port == port) {
\r
262 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
263 ip_addr_isany(ipaddr) ||
\r
264 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
269 #else /* SO_REUSE */
\r
270 /* Search through list of PCB's in LISTEN state.
\r
272 If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
\r
273 or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
\r
274 the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
\r
275 But no two PCB's bound to same local port and same local address is valid.
\r
277 If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
\r
278 all PCB's must have the SOF_REUSEPORT option set.
\r
280 When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
\r
281 address is already in use. */
\r
282 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) {
\r
283 if(cpcb->local_port == port) {
\r
284 if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
285 if(pcb->so_options & SOF_REUSEPORT) {
\r
286 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
\r
287 reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
\r
290 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
\r
294 else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
\r
295 (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
\r
296 if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
\r
297 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
\r
301 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
\r
307 /* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
\r
308 PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
\r
309 for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
\r
310 if(cpcb->local_port == port) {
\r
311 if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
312 if(pcb->so_options & SOF_REUSEPORT) {
\r
313 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
\r
314 reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
\r
317 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
\r
321 else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
\r
322 (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
\r
323 if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
\r
324 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
\r
328 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
\r
334 /* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
\r
335 can be rebound. The same applies when SOF_REUSEPORT is set.
\r
337 If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
\r
338 all PCB's must have the SOF_REUSEPORT option set.
\r
340 When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
\r
341 address is already in use. */
\r
342 for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
\r
343 if(cpcb->local_port == port) {
\r
344 if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
345 if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
\r
346 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
\r
349 else if(pcb->so_options & SOF_REUSEPORT) {
\r
350 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
\r
351 reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
\r
357 /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
\r
358 {IP, port} can't be reused. */
\r
359 if(!reuse_port_all_set) {
\r
360 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
\r
363 #endif /* SO_REUSE */
\r
365 if (!ip_addr_isany(ipaddr)) {
\r
366 pcb->local_ip = *ipaddr;
\r
368 pcb->local_port = port;
\r
369 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));
\r
372 #if LWIP_CALLBACK_API
\r
374 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
\r
382 #endif /* LWIP_CALLBACK_API */
\r
385 * Set the state of the connection to be LISTEN, which means that it
\r
386 * is able to accept incoming connections. The protocol control block
\r
387 * is reallocated in order to consume less memory. Setting the
\r
388 * connection to LISTEN is an irreversible process.
\r
392 tcp_listen(struct tcp_pcb *pcb)
\r
394 struct tcp_pcb_listen *lpcb;
\r
396 /* already listening? */
\r
397 if (pcb->state == LISTEN) {
\r
400 lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
\r
401 if (lpcb == NULL) {
\r
404 lpcb->callback_arg = pcb->callback_arg;
\r
405 lpcb->local_port = pcb->local_port;
\r
406 lpcb->state = LISTEN;
\r
407 lpcb->so_options = pcb->so_options;
\r
408 lpcb->so_options |= SOF_ACCEPTCONN;
\r
409 lpcb->ttl = pcb->ttl;
\r
410 lpcb->tos = pcb->tos;
\r
411 ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
\r
412 memp_free(MEMP_TCP_PCB, pcb);
\r
413 #if LWIP_CALLBACK_API
\r
414 lpcb->accept = tcp_accept_null;
\r
415 #endif /* LWIP_CALLBACK_API */
\r
416 TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
\r
417 return (struct tcp_pcb *)lpcb;
\r
421 * This function should be called by the application when it has
\r
422 * processed the data. The purpose is to advertise a larger window
\r
423 * when the data has been processed.
\r
427 tcp_recved(struct tcp_pcb *pcb, u16_t len)
\r
429 if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
\r
430 pcb->rcv_wnd = TCP_WND;
\r
432 pcb->rcv_wnd += len;
\r
434 if (!(pcb->flags & TF_ACK_DELAY) &&
\r
435 !(pcb->flags & TF_ACK_NOW)) {
\r
437 * We send an ACK here (if one is not already pending, hence
\r
438 * the above tests) as tcp_recved() implies that the application
\r
439 * has processed some data, and so we can open the receiver's
\r
440 * window to allow more to be transmitted. This could result in
\r
441 * two ACKs being sent for each received packet in some limited cases
\r
442 * (where the application is only receiving data, and is slow to
\r
443 * process it) but it is necessary to guarantee that the sender can
\r
444 * continue to transmit.
\r
448 else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
\r
449 /* If we can send a window update such that there is a full
\r
450 * segment available in the window, do so now. This is sort of
\r
451 * nagle-like in its goals, and tries to hit a compromise between
\r
452 * sending acks each time the window is updated, and only sending
\r
453 * window updates when a timer expires. The "threshold" used
\r
454 * above (currently TCP_WND/2) can be tuned to be more or less
\r
459 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
\r
460 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
\r
464 * A nastly hack featuring 'goto' statements that allocates a
\r
465 * new TCP local port.
\r
470 struct tcp_pcb *pcb;
\r
471 #ifndef TCP_LOCAL_PORT_RANGE_START
\r
472 #define TCP_LOCAL_PORT_RANGE_START 4096
\r
473 #define TCP_LOCAL_PORT_RANGE_END 0x7fff
\r
475 static u16_t port = TCP_LOCAL_PORT_RANGE_START;
\r
478 if (++port > TCP_LOCAL_PORT_RANGE_END) {
\r
479 port = TCP_LOCAL_PORT_RANGE_START;
\r
482 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
483 if (pcb->local_port == port) {
\r
487 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
488 if (pcb->local_port == port) {
\r
492 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
493 if (pcb->local_port == port) {
\r
501 * Connects to another host. The function given as the "connected"
\r
502 * argument will be called when the connection has been established.
\r
506 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
\r
507 err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
\r
513 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port));
\r
514 if (ipaddr != NULL) {
\r
515 pcb->remote_ip = *ipaddr;
\r
519 pcb->remote_port = port;
\r
520 if (pcb->local_port == 0) {
\r
521 pcb->local_port = tcp_new_port();
\r
523 iss = tcp_next_iss();
\r
525 pcb->snd_nxt = iss;
\r
526 pcb->lastack = iss - 1;
\r
527 pcb->snd_lbb = iss - 1;
\r
528 pcb->rcv_wnd = TCP_WND;
\r
529 pcb->snd_wnd = TCP_WND;
\r
530 pcb->mss = TCP_MSS;
\r
532 pcb->ssthresh = pcb->mss * 10;
\r
533 pcb->state = SYN_SENT;
\r
534 #if LWIP_CALLBACK_API
\r
535 pcb->connected = connected;
\r
536 #endif /* LWIP_CALLBACK_API */
\r
537 TCP_REG(&tcp_active_pcbs, pcb);
\r
539 /* Build an MSS option */
\r
540 optdata = htonl(((u32_t)2 << 24) |
\r
541 ((u32_t)4 << 16) |
\r
542 (((u32_t)pcb->mss / 256) << 8) |
\r
545 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
\r
546 if (ret == ERR_OK) {
\r
553 * Called every 500 ms and implements the retransmission timer and the timer that
\r
554 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
\r
555 * various timers such as the inactivity timer in each PCB.
\r
560 struct tcp_pcb *pcb, *pcb2, *prev;
\r
562 u8_t pcb_remove; /* flag if a PCB should be removed */
\r
569 /* Steps through all of the active PCBs. */
\r
571 pcb = tcp_active_pcbs;
\r
573 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
\r
575 while (pcb != NULL) {
\r
576 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
\r
577 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
\r
578 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
\r
579 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
\r
583 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
\r
585 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
\r
587 else if (pcb->nrtx == TCP_MAXRTX) {
\r
589 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
\r
592 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
\r
594 /* Time for a retransmission. */
\r
595 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n",
\r
596 pcb->rtime, pcb->rto));
\r
598 /* Double retransmission time-out unless we are trying to
\r
599 * connect to somebody (i.e., we are in SYN_SENT). */
\r
600 if (pcb->state != SYN_SENT) {
\r
601 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
\r
603 /* Reduce congestion window and ssthresh. */
\r
604 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
\r
605 pcb->ssthresh = eff_wnd >> 1;
\r
606 if (pcb->ssthresh < pcb->mss) {
\r
607 pcb->ssthresh = pcb->mss * 2;
\r
609 pcb->cwnd = pcb->mss;
\r
610 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",
\r
611 pcb->cwnd, pcb->ssthresh));
\r
613 /* The following needs to be called AFTER cwnd is set to one mss - STJ */
\r
614 tcp_rexmit_rto(pcb);
\r
617 /* Check if this PCB has stayed too long in FIN-WAIT-2 */
\r
618 if (pcb->state == FIN_WAIT_2) {
\r
619 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
620 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
622 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
\r
626 /* Check if KEEPALIVE should be sent */
\r
627 if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
\r
628 if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
\r
629 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
\r
630 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
\r
631 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
\r
635 else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
\r
636 tcp_keepalive(pcb);
\r
641 /* If this PCB has queued out of sequence data, but has been
\r
642 inactive for too long, will drop the data (it will eventually
\r
643 be retransmitted). */
\r
644 #if TCP_QUEUE_OOSEQ
\r
645 if (pcb->ooseq != NULL &&
\r
646 (u32_t)tcp_ticks - pcb->tmr >=
\r
647 pcb->rto * (u32_t)TCP_OOSEQ_TIMEOUT) {
\r
648 tcp_segs_free(pcb->ooseq);
\r
650 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
\r
652 #endif /* TCP_QUEUE_OOSEQ */
\r
654 /* Check if this PCB has stayed too long in SYN-RCVD */
\r
655 if (pcb->state == SYN_RCVD) {
\r
656 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
657 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
659 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
\r
664 /* If the PCB should be removed, do it. */
\r
666 tcp_pcb_purge(pcb);
\r
667 /* Remove PCB from tcp_active_pcbs list. */
\r
668 if (prev != NULL) {
\r
669 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
\r
670 prev->next = pcb->next;
\r
672 /* This PCB was the first. */
\r
673 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
\r
674 tcp_active_pcbs = pcb->next;
\r
677 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
\r
680 memp_free(MEMP_TCP_PCB, pcb);
\r
684 /* We check if we should poll the connection. */
\r
686 if (pcb->polltmr >= pcb->pollinterval) {
\r
688 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
\r
689 TCP_EVENT_POLL(pcb, err);
\r
690 if (err == ERR_OK) {
\r
701 /* Steps through all of the TIME-WAIT PCBs. */
\r
704 while (pcb != NULL) {
\r
705 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
708 /* Check if this PCB has stayed long enough in TIME-WAIT */
\r
709 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
715 /* If the PCB should be removed, do it. */
\r
717 tcp_pcb_purge(pcb);
\r
718 /* Remove PCB from tcp_tw_pcbs list. */
\r
719 if (prev != NULL) {
\r
720 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
\r
721 prev->next = pcb->next;
\r
723 /* This PCB was the first. */
\r
724 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
\r
725 tcp_tw_pcbs = pcb->next;
\r
728 memp_free(MEMP_TCP_PCB, pcb);
\r
738 * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
\r
743 struct tcp_pcb *pcb;
\r
745 /* send delayed ACKs */
\r
746 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
747 if (pcb->flags & TF_ACK_DELAY) {
\r
748 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
\r
750 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
756 * Deallocates a list of TCP segments (tcp_seg structures).
\r
760 tcp_segs_free(struct tcp_seg *seg)
\r
763 struct tcp_seg *next;
\r
764 while (seg != NULL) {
\r
766 count += tcp_seg_free(seg);
\r
773 * Frees a TCP segment.
\r
777 tcp_seg_free(struct tcp_seg *seg)
\r
782 if (seg->p != NULL) {
\r
783 count = pbuf_free(seg->p);
\r
786 #endif /* TCP_DEBUG */
\r
788 memp_free(MEMP_TCP_SEG, seg);
\r
794 * Sets the priority of a connection.
\r
798 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
\r
802 #if TCP_QUEUE_OOSEQ
\r
805 * Returns a copy of the given TCP segment.
\r
809 tcp_seg_copy(struct tcp_seg *seg)
\r
811 struct tcp_seg *cseg;
\r
813 cseg = memp_malloc(MEMP_TCP_SEG);
\r
814 if (cseg == NULL) {
\r
817 memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg));
\r
823 #if LWIP_CALLBACK_API
\r
825 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
\r
830 } else if (err == ERR_OK) {
\r
831 return tcp_close(pcb);
\r
835 #endif /* LWIP_CALLBACK_API */
\r
838 tcp_kill_prio(u8_t prio)
\r
840 struct tcp_pcb *pcb, *inactive;
\r
845 mprio = TCP_PRIO_MAX;
\r
847 /* We kill the oldest active connection that has lower priority than
\r
851 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
852 if (pcb->prio <= prio &&
\r
853 pcb->prio <= mprio &&
\r
854 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
855 inactivity = tcp_ticks - pcb->tmr;
\r
860 if (inactive != NULL) {
\r
861 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%ld)\n",
\r
862 (void *)inactive, inactivity));
\r
863 tcp_abort(inactive);
\r
869 tcp_kill_timewait(void)
\r
871 struct tcp_pcb *pcb, *inactive;
\r
876 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
877 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
878 inactivity = tcp_ticks - pcb->tmr;
\r
882 if (inactive != NULL) {
\r
883 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%ld)\n",
\r
884 (void *)inactive, inactivity));
\r
885 tcp_abort(inactive);
\r
892 tcp_alloc(u8_t prio)
\r
894 struct tcp_pcb *pcb;
\r
897 pcb = memp_malloc(MEMP_TCP_PCB);
\r
899 /* Try killing oldest connection in TIME-WAIT. */
\r
900 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
\r
901 tcp_kill_timewait();
\r
902 pcb = memp_malloc(MEMP_TCP_PCB);
\r
904 tcp_kill_prio(prio);
\r
905 pcb = memp_malloc(MEMP_TCP_PCB);
\r
909 memset(pcb, 0, sizeof(struct tcp_pcb));
\r
910 pcb->prio = TCP_PRIO_NORMAL;
\r
911 pcb->snd_buf = TCP_SND_BUF;
\r
912 pcb->snd_queuelen = 0;
\r
913 pcb->rcv_wnd = TCP_WND;
\r
915 pcb->ttl = TCP_TTL;
\r
916 pcb->mss = TCP_MSS;
\r
917 pcb->rto = 3000 / TCP_SLOW_INTERVAL;
\r
919 pcb->sv = 3000 / TCP_SLOW_INTERVAL;
\r
922 iss = tcp_next_iss();
\r
923 pcb->snd_wl2 = iss;
\r
924 pcb->snd_nxt = iss;
\r
925 pcb->snd_max = iss;
\r
926 pcb->lastack = iss;
\r
927 pcb->snd_lbb = iss;
\r
928 pcb->tmr = tcp_ticks;
\r
932 #if LWIP_CALLBACK_API
\r
933 pcb->recv = tcp_recv_null;
\r
934 #endif /* LWIP_CALLBACK_API */
\r
936 /* Init KEEPALIVE timer */
\r
937 pcb->keepalive = TCP_KEEPDEFAULT;
\r
944 * Creates a new TCP protocol control block but doesn't place it on
\r
945 * any of the TCP PCB lists.
\r
947 * @internal: Maybe there should be a idle TCP PCB list where these
\r
948 * PCBs are put on. We can then implement port reservation using
\r
949 * tcp_bind(). Currently, we lack this (BSD socket type of) feature.
\r
955 return tcp_alloc(TCP_PRIO_NORMAL);
\r
961 * Used to specify the argument that should be passed callback
\r
967 tcp_arg(struct tcp_pcb *pcb, void *arg)
\r
969 pcb->callback_arg = arg;
\r
971 #if LWIP_CALLBACK_API
\r
974 * Used to specify the function that should be called when a TCP
\r
975 * connection receives data.
\r
979 tcp_recv(struct tcp_pcb *pcb,
\r
980 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
\r
986 * Used to specify the function that should be called when TCP data
\r
987 * has been successfully delivered to the remote host.
\r
992 tcp_sent(struct tcp_pcb *pcb,
\r
993 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
\r
999 * Used to specify the function that should be called when a fatal error
\r
1000 * has occured on the connection.
\r
1004 tcp_err(struct tcp_pcb *pcb,
\r
1005 void (* errf)(void *arg, err_t err))
\r
1011 * Used for specifying the function that should be called when a
\r
1012 * LISTENing connection has been connected to another host.
\r
1016 tcp_accept(struct tcp_pcb *pcb,
\r
1017 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
\r
1019 ((struct tcp_pcb_listen *)pcb)->accept = accept;
\r
1021 #endif /* LWIP_CALLBACK_API */
\r
1025 * Used to specify the function that should be called periodically
\r
1026 * from TCP. The interval is specified in terms of the TCP coarse
\r
1027 * timer interval, which is called twice a second.
\r
1031 tcp_poll(struct tcp_pcb *pcb,
\r
1032 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
\r
1034 #if LWIP_CALLBACK_API
\r
1036 #endif /* LWIP_CALLBACK_API */
\r
1037 pcb->pollinterval = interval;
\r
1041 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
\r
1045 tcp_pcb_purge(struct tcp_pcb *pcb)
\r
1047 if (pcb->state != CLOSED &&
\r
1048 pcb->state != TIME_WAIT &&
\r
1049 pcb->state != LISTEN) {
\r
1051 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
\r
1053 if (pcb->unsent != NULL) {
\r
1054 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
\r
1056 if (pcb->unacked != NULL) {
\r
1057 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
\r
1059 #if TCP_QUEUE_OOSEQ /* LW */
\r
1060 if (pcb->ooseq != NULL) {
\r
1061 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
\r
1064 tcp_segs_free(pcb->ooseq);
\r
1065 pcb->ooseq = NULL;
\r
1066 #endif /* TCP_QUEUE_OOSEQ */
\r
1067 tcp_segs_free(pcb->unsent);
\r
1068 tcp_segs_free(pcb->unacked);
\r
1069 pcb->unacked = pcb->unsent = NULL;
\r
1074 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
\r
1078 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
\r
1080 TCP_RMV(pcblist, pcb);
\r
1082 tcp_pcb_purge(pcb);
\r
1084 /* if there is an outstanding delayed ACKs, send it */
\r
1085 if (pcb->state != TIME_WAIT &&
\r
1086 pcb->state != LISTEN &&
\r
1087 pcb->flags & TF_ACK_DELAY) {
\r
1088 pcb->flags |= TF_ACK_NOW;
\r
1091 pcb->state = CLOSED;
\r
1093 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
\r
1097 * Calculates a new initial sequence number for new connections.
\r
1101 tcp_next_iss(void)
\r
1103 static u32_t iss = 6510;
\r
1105 iss += tcp_ticks; /* XXX */
\r
1109 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
\r
1111 tcp_debug_print(struct tcp_hdr *tcphdr)
\r
1113 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
\r
1114 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1115 LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
\r
1116 ntohs(tcphdr->src), ntohs(tcphdr->dest)));
\r
1117 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1118 LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
\r
1119 ntohl(tcphdr->seqno)));
\r
1120 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1121 LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
\r
1122 ntohl(tcphdr->ackno)));
\r
1123 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1124 LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
\r
1125 TCPH_HDRLEN(tcphdr),
\r
1126 TCPH_FLAGS(tcphdr) >> 5 & 1,
\r
1127 TCPH_FLAGS(tcphdr) >> 4 & 1,
\r
1128 TCPH_FLAGS(tcphdr) >> 3 & 1,
\r
1129 TCPH_FLAGS(tcphdr) >> 2 & 1,
\r
1130 TCPH_FLAGS(tcphdr) >> 1 & 1,
\r
1131 TCPH_FLAGS(tcphdr) & 1,
\r
1132 ntohs(tcphdr->wnd)));
\r
1133 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
\r
1134 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
\r
1135 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1136 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04x | %5u | (chksum, urgp)\n",
\r
1137 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
\r
1138 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1142 tcp_debug_print_state(enum tcp_state s)
\r
1144 LWIP_DEBUGF(TCP_DEBUG, ("State: "));
\r
1147 LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
\r
1150 LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
\r
1153 LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
\r
1156 LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
\r
1159 LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
\r
1162 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
\r
1165 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
\r
1168 LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
\r
1171 LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
\r
1174 LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
\r
1177 LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
\r
1183 tcp_debug_print_flags(u8_t flags)
\r
1185 if (flags & TCP_FIN) {
\r
1186 LWIP_DEBUGF(TCP_DEBUG, ("FIN "));
\r
1188 if (flags & TCP_SYN) {
\r
1189 LWIP_DEBUGF(TCP_DEBUG, ("SYN "));
\r
1191 if (flags & TCP_RST) {
\r
1192 LWIP_DEBUGF(TCP_DEBUG, ("RST "));
\r
1194 if (flags & TCP_PSH) {
\r
1195 LWIP_DEBUGF(TCP_DEBUG, ("PSH "));
\r
1197 if (flags & TCP_ACK) {
\r
1198 LWIP_DEBUGF(TCP_DEBUG, ("ACK "));
\r
1200 if (flags & TCP_URG) {
\r
1201 LWIP_DEBUGF(TCP_DEBUG, ("URG "));
\r
1203 if (flags & TCP_ECE) {
\r
1204 LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
\r
1206 if (flags & TCP_CWR) {
\r
1207 LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
\r
1212 tcp_debug_print_pcbs(void)
\r
1214 struct tcp_pcb *pcb;
\r
1215 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
\r
1216 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1217 LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
\r
1218 pcb->local_port, pcb->remote_port,
\r
1219 pcb->snd_nxt, pcb->rcv_nxt));
\r
1220 tcp_debug_print_state(pcb->state);
\r
1222 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
\r
1223 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
1224 LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
\r
1225 pcb->local_port, pcb->remote_port,
\r
1226 pcb->snd_nxt, pcb->rcv_nxt));
\r
1227 tcp_debug_print_state(pcb->state);
\r
1229 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
\r
1230 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1231 LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",
\r
1232 pcb->local_port, pcb->remote_port,
\r
1233 pcb->snd_nxt, pcb->rcv_nxt));
\r
1234 tcp_debug_print_state(pcb->state);
\r
1239 tcp_pcbs_sane(void)
\r
1241 struct tcp_pcb *pcb;
\r
1242 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1243 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
\r
1244 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
\r
1245 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
\r
1247 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1248 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
1252 #endif /* TCP_DEBUG */
\r
1253 #endif /* LWIP_TCP */
\r