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
50 #include "lwip/snmp.h"
\r
52 #include "lwip/tcp.h"
\r
55 /* Incremented every coarse grained timer shot (typically every 500 ms). */
\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 "));
\r
121 tcp_debug_print_state(pcb->state);
\r
122 #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
148 snmp_inc_tcpattemptfails();
\r
151 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
152 if (err == ERR_OK) {
\r
153 snmp_inc_tcpattemptfails();
\r
154 pcb->state = FIN_WAIT_1;
\r
158 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
159 if (err == ERR_OK) {
\r
160 snmp_inc_tcpestabresets();
\r
161 pcb->state = FIN_WAIT_1;
\r
165 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
166 if (err == ERR_OK) {
\r
167 snmp_inc_tcpestabresets();
\r
168 pcb->state = LAST_ACK;
\r
172 /* Has already been closed, do nothing. */
\r
178 if (pcb != NULL && err == ERR_OK) {
\r
179 err = tcp_output(pcb);
\r
185 * Aborts a connection by sending a RST to the remote host and deletes
\r
186 * the local protocol control block. This is done when a connection is
\r
187 * killed because of shortage of memory.
\r
191 tcp_abort(struct tcp_pcb *pcb)
\r
193 u32_t seqno, ackno;
\r
194 u16_t remote_port, local_port;
\r
195 struct ip_addr remote_ip, local_ip;
\r
196 #if LWIP_CALLBACK_API
\r
197 void (* errf)(void *arg, err_t err);
\r
198 #endif /* LWIP_CALLBACK_API */
\r
202 /* Figure out on which TCP PCB list we are, and remove us. If we
\r
203 are in an active state, call the receive function associated with
\r
204 the PCB with a NULL argument, and send an RST to the remote end. */
\r
205 if (pcb->state == TIME_WAIT) {
\r
206 tcp_pcb_remove(&tcp_tw_pcbs, pcb);
\r
207 memp_free(MEMP_TCP_PCB, pcb);
\r
209 seqno = pcb->snd_nxt;
\r
210 ackno = pcb->rcv_nxt;
\r
211 ip_addr_set(&local_ip, &(pcb->local_ip));
\r
212 ip_addr_set(&remote_ip, &(pcb->remote_ip));
\r
213 local_port = pcb->local_port;
\r
214 remote_port = pcb->remote_port;
\r
215 #if LWIP_CALLBACK_API
\r
217 #endif /* LWIP_CALLBACK_API */
\r
218 errf_arg = pcb->callback_arg;
\r
219 tcp_pcb_remove(&tcp_active_pcbs, pcb);
\r
220 if (pcb->unacked != NULL) {
\r
221 tcp_segs_free(pcb->unacked);
\r
223 if (pcb->unsent != NULL) {
\r
224 tcp_segs_free(pcb->unsent);
\r
226 #if TCP_QUEUE_OOSEQ
\r
227 if (pcb->ooseq != NULL) {
\r
228 tcp_segs_free(pcb->ooseq);
\r
230 #endif /* TCP_QUEUE_OOSEQ */
\r
231 memp_free(MEMP_TCP_PCB, pcb);
\r
232 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
\r
233 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n"));
\r
234 tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
\r
239 * Binds the connection to a local portnumber and IP address. If the
\r
240 * IP address is not given (i.e., ipaddr == NULL), the IP address of
\r
241 * the outgoing network interface is used instead.
\r
246 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
\r
248 struct tcp_pcb *cpcb;
\r
251 port = tcp_new_port();
\r
253 /* Check if the address already is in use. */
\r
254 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
\r
255 cpcb != NULL; cpcb = cpcb->next) {
\r
256 if (cpcb->local_port == port) {
\r
257 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
258 ip_addr_isany(ipaddr) ||
\r
259 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
264 for(cpcb = tcp_active_pcbs;
\r
265 cpcb != NULL; cpcb = cpcb->next) {
\r
266 if (cpcb->local_port == port) {
\r
267 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
268 ip_addr_isany(ipaddr) ||
\r
269 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
275 if (!ip_addr_isany(ipaddr)) {
\r
276 pcb->local_ip = *ipaddr;
\r
278 pcb->local_port = port;
\r
279 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
\r
282 #if LWIP_CALLBACK_API
\r
284 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
\r
292 #endif /* LWIP_CALLBACK_API */
\r
295 * Set the state of the connection to be LISTEN, which means that it
\r
296 * is able to accept incoming connections. The protocol control block
\r
297 * is reallocated in order to consume less memory. Setting the
\r
298 * connection to LISTEN is an irreversible process.
\r
302 tcp_listen(struct tcp_pcb *pcb)
\r
304 struct tcp_pcb_listen *lpcb;
\r
306 /* already listening? */
\r
307 if (pcb->state == LISTEN) {
\r
310 lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
\r
311 if (lpcb == NULL) {
\r
314 lpcb->callback_arg = pcb->callback_arg;
\r
315 lpcb->local_port = pcb->local_port;
\r
316 lpcb->state = LISTEN;
\r
317 lpcb->so_options = pcb->so_options;
\r
318 lpcb->so_options |= SOF_ACCEPTCONN;
\r
319 lpcb->ttl = pcb->ttl;
\r
320 lpcb->tos = pcb->tos;
\r
321 ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
\r
322 memp_free(MEMP_TCP_PCB, pcb);
\r
323 #if LWIP_CALLBACK_API
\r
324 lpcb->accept = tcp_accept_null;
\r
325 #endif /* LWIP_CALLBACK_API */
\r
326 TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
\r
327 return (struct tcp_pcb *)lpcb;
\r
331 * This function should be called by the application when it has
\r
332 * processed the data. The purpose is to advertise a larger window
\r
333 * when the data has been processed.
\r
337 tcp_recved(struct tcp_pcb *pcb, u16_t len)
\r
339 if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
\r
340 pcb->rcv_wnd = TCP_WND;
\r
342 pcb->rcv_wnd += len;
\r
344 if (!(pcb->flags & TF_ACK_DELAY) &&
\r
345 !(pcb->flags & TF_ACK_NOW)) {
\r
347 * We send an ACK here (if one is not already pending, hence
\r
348 * the above tests) as tcp_recved() implies that the application
\r
349 * has processed some data, and so we can open the receiver's
\r
350 * window to allow more to be transmitted. This could result in
\r
351 * two ACKs being sent for each received packet in some limited cases
\r
352 * (where the application is only receiving data, and is slow to
\r
353 * process it) but it is necessary to guarantee that the sender can
\r
354 * continue to transmit.
\r
358 else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
\r
359 /* If we can send a window update such that there is a full
\r
360 * segment available in the window, do so now. This is sort of
\r
361 * nagle-like in its goals, and tries to hit a compromise between
\r
362 * sending acks each time the window is updated, and only sending
\r
363 * window updates when a timer expires. The "threshold" used
\r
364 * above (currently TCP_WND/2) can be tuned to be more or less
\r
369 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
\r
370 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
\r
374 * A nastly hack featuring 'goto' statements that allocates a
\r
375 * new TCP local port.
\r
380 struct tcp_pcb *pcb;
\r
381 #ifndef TCP_LOCAL_PORT_RANGE_START
\r
382 #define TCP_LOCAL_PORT_RANGE_START 4096
\r
383 #define TCP_LOCAL_PORT_RANGE_END 0x7fff
\r
385 static u16_t port = TCP_LOCAL_PORT_RANGE_START;
\r
388 if (++port > TCP_LOCAL_PORT_RANGE_END) {
\r
389 port = TCP_LOCAL_PORT_RANGE_START;
\r
392 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
393 if (pcb->local_port == port) {
\r
397 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
398 if (pcb->local_port == port) {
\r
402 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
403 if (pcb->local_port == port) {
\r
411 * Connects to another host. The function given as the "connected"
\r
412 * argument will be called when the connection has been established.
\r
416 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
\r
417 err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
\r
423 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
\r
424 if (ipaddr != NULL) {
\r
425 pcb->remote_ip = *ipaddr;
\r
429 pcb->remote_port = port;
\r
430 if (pcb->local_port == 0) {
\r
431 pcb->local_port = tcp_new_port();
\r
433 iss = tcp_next_iss();
\r
435 pcb->snd_nxt = iss;
\r
436 pcb->lastack = iss - 1;
\r
437 pcb->snd_lbb = iss - 1;
\r
438 pcb->rcv_wnd = TCP_WND;
\r
439 pcb->snd_wnd = TCP_WND;
\r
440 pcb->mss = TCP_MSS;
\r
442 pcb->ssthresh = pcb->mss * 10;
\r
443 pcb->state = SYN_SENT;
\r
444 #if LWIP_CALLBACK_API
\r
445 pcb->connected = connected;
\r
446 #endif /* LWIP_CALLBACK_API */
\r
447 TCP_REG(&tcp_active_pcbs, pcb);
\r
449 snmp_inc_tcpactiveopens();
\r
451 /* Build an MSS option */
\r
452 optdata = htonl(((u32_t)2 << 24) |
\r
453 ((u32_t)4 << 16) |
\r
454 (((u32_t)pcb->mss / 256) << 8) |
\r
457 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
\r
458 if (ret == ERR_OK) {
\r
465 * Called every 500 ms and implements the retransmission timer and the timer that
\r
466 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
\r
467 * various timers such as the inactivity timer in each PCB.
\r
472 struct tcp_pcb *pcb, *pcb2, *prev;
\r
474 u8_t pcb_remove; /* flag if a PCB should be removed */
\r
481 /* Steps through all of the active PCBs. */
\r
483 pcb = tcp_active_pcbs;
\r
485 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
\r
487 while (pcb != NULL) {
\r
488 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
\r
489 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
\r
490 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
\r
491 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
\r
495 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
\r
497 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
\r
499 else if (pcb->nrtx == TCP_MAXRTX) {
\r
501 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
\r
504 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
\r
506 /* Time for a retransmission. */
\r
507 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
\r
508 pcb->rtime, pcb->rto));
\r
510 /* Double retransmission time-out unless we are trying to
\r
511 * connect to somebody (i.e., we are in SYN_SENT). */
\r
512 if (pcb->state != SYN_SENT) {
\r
513 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
\r
515 /* Reduce congestion window and ssthresh. */
\r
516 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
\r
517 pcb->ssthresh = eff_wnd >> 1;
\r
518 if (pcb->ssthresh < pcb->mss) {
\r
519 pcb->ssthresh = pcb->mss * 2;
\r
521 pcb->cwnd = pcb->mss;
\r
522 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
\r
523 pcb->cwnd, pcb->ssthresh));
\r
525 /* The following needs to be called AFTER cwnd is set to one mss - STJ */
\r
526 tcp_rexmit_rto(pcb);
\r
529 /* Check if this PCB has stayed too long in FIN-WAIT-2 */
\r
530 if (pcb->state == FIN_WAIT_2) {
\r
531 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
532 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
534 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
\r
538 /* Check if KEEPALIVE should be sent */
\r
539 if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
\r
540 if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
\r
541 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
\r
542 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
\r
543 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
\r
547 else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
\r
548 tcp_keepalive(pcb);
\r
553 /* If this PCB has queued out of sequence data, but has been
\r
554 inactive for too long, will drop the data (it will eventually
\r
555 be retransmitted). */
\r
556 #if TCP_QUEUE_OOSEQ
\r
557 if (pcb->ooseq != NULL &&
\r
558 (u32_t)tcp_ticks - pcb->tmr >=
\r
559 pcb->rto * TCP_OOSEQ_TIMEOUT) {
\r
560 tcp_segs_free(pcb->ooseq);
\r
562 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
\r
564 #endif /* TCP_QUEUE_OOSEQ */
\r
566 /* Check if this PCB has stayed too long in SYN-RCVD */
\r
567 if (pcb->state == SYN_RCVD) {
\r
568 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
569 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
571 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
\r
575 /* Check if this PCB has stayed too long in LAST-ACK */
\r
576 if (pcb->state == LAST_ACK) {
\r
577 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
579 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
\r
583 /* If the PCB should be removed, do it. */
\r
585 tcp_pcb_purge(pcb);
\r
586 /* Remove PCB from tcp_active_pcbs list. */
\r
587 if (prev != NULL) {
\r
588 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
\r
589 prev->next = pcb->next;
\r
591 /* This PCB was the first. */
\r
592 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
\r
593 tcp_active_pcbs = pcb->next;
\r
596 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
\r
599 memp_free(MEMP_TCP_PCB, pcb);
\r
603 /* We check if we should poll the connection. */
\r
605 if (pcb->polltmr >= pcb->pollinterval) {
\r
607 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
\r
608 TCP_EVENT_POLL(pcb, err);
\r
609 if (err == ERR_OK) {
\r
620 /* Steps through all of the TIME-WAIT PCBs. */
\r
623 while (pcb != NULL) {
\r
624 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
627 /* Check if this PCB has stayed long enough in TIME-WAIT */
\r
628 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
634 /* If the PCB should be removed, do it. */
\r
636 tcp_pcb_purge(pcb);
\r
637 /* Remove PCB from tcp_tw_pcbs list. */
\r
638 if (prev != NULL) {
\r
639 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
\r
640 prev->next = pcb->next;
\r
642 /* This PCB was the first. */
\r
643 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
\r
644 tcp_tw_pcbs = pcb->next;
\r
647 memp_free(MEMP_TCP_PCB, pcb);
\r
657 * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
\r
662 struct tcp_pcb *pcb;
\r
664 /* send delayed ACKs */
\r
665 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
666 if (pcb->flags & TF_ACK_DELAY) {
\r
667 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
\r
669 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
675 * Deallocates a list of TCP segments (tcp_seg structures).
\r
679 tcp_segs_free(struct tcp_seg *seg)
\r
682 struct tcp_seg *next;
\r
683 while (seg != NULL) {
\r
685 count += tcp_seg_free(seg);
\r
692 * Frees a TCP segment.
\r
696 tcp_seg_free(struct tcp_seg *seg)
\r
701 if (seg->p != NULL) {
\r
702 count = pbuf_free(seg->p);
\r
705 #endif /* TCP_DEBUG */
\r
707 memp_free(MEMP_TCP_SEG, seg);
\r
713 * Sets the priority of a connection.
\r
717 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
\r
721 #if TCP_QUEUE_OOSEQ
\r
724 * Returns a copy of the given TCP segment.
\r
728 tcp_seg_copy(struct tcp_seg *seg)
\r
730 struct tcp_seg *cseg;
\r
732 cseg = memp_malloc(MEMP_TCP_SEG);
\r
733 if (cseg == NULL) {
\r
736 memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
\r
742 #if LWIP_CALLBACK_API
\r
744 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
\r
749 } else if (err == ERR_OK) {
\r
750 return tcp_close(pcb);
\r
754 #endif /* LWIP_CALLBACK_API */
\r
757 tcp_kill_prio(u8_t prio)
\r
759 struct tcp_pcb *pcb, *inactive;
\r
764 mprio = TCP_PRIO_MAX;
\r
766 /* We kill the oldest active connection that has lower priority than
\r
770 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
771 if (pcb->prio <= prio &&
\r
772 pcb->prio <= mprio &&
\r
773 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
774 inactivity = tcp_ticks - pcb->tmr;
\r
779 if (inactive != NULL) {
\r
780 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
\r
781 (void *)inactive, inactivity));
\r
782 tcp_abort(inactive);
\r
788 tcp_kill_timewait(void)
\r
790 struct tcp_pcb *pcb, *inactive;
\r
795 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
796 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
797 inactivity = tcp_ticks - pcb->tmr;
\r
801 if (inactive != NULL) {
\r
802 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
\r
803 (void *)inactive, inactivity));
\r
804 tcp_abort(inactive);
\r
811 tcp_alloc(u8_t prio)
\r
813 struct tcp_pcb *pcb;
\r
816 pcb = memp_malloc(MEMP_TCP_PCB);
\r
818 /* Try killing oldest connection in TIME-WAIT. */
\r
819 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
\r
820 tcp_kill_timewait();
\r
821 pcb = memp_malloc(MEMP_TCP_PCB);
\r
823 tcp_kill_prio(prio);
\r
824 pcb = memp_malloc(MEMP_TCP_PCB);
\r
828 memset(pcb, 0, sizeof(struct tcp_pcb));
\r
829 pcb->prio = TCP_PRIO_NORMAL;
\r
830 pcb->snd_buf = TCP_SND_BUF;
\r
831 pcb->snd_queuelen = 0;
\r
832 pcb->rcv_wnd = TCP_WND;
\r
834 pcb->ttl = TCP_TTL;
\r
835 pcb->mss = TCP_MSS;
\r
836 pcb->rto = 3000 / TCP_SLOW_INTERVAL;
\r
838 pcb->sv = 3000 / TCP_SLOW_INTERVAL;
\r
841 iss = tcp_next_iss();
\r
842 pcb->snd_wl2 = iss;
\r
843 pcb->snd_nxt = iss;
\r
844 pcb->snd_max = iss;
\r
845 pcb->lastack = iss;
\r
846 pcb->snd_lbb = iss;
\r
847 pcb->tmr = tcp_ticks;
\r
851 #if LWIP_CALLBACK_API
\r
852 pcb->recv = tcp_recv_null;
\r
853 #endif /* LWIP_CALLBACK_API */
\r
855 /* Init KEEPALIVE timer */
\r
856 pcb->keepalive = TCP_KEEPDEFAULT;
\r
863 * Creates a new TCP protocol control block but doesn't place it on
\r
864 * any of the TCP PCB lists.
\r
866 * @internal: Maybe there should be a idle TCP PCB list where these
\r
867 * PCBs are put on. We can then implement port reservation using
\r
868 * tcp_bind(). Currently, we lack this (BSD socket type of) feature.
\r
874 return tcp_alloc(TCP_PRIO_NORMAL);
\r
880 * Used to specify the argument that should be passed callback
\r
886 tcp_arg(struct tcp_pcb *pcb, void *arg)
\r
888 pcb->callback_arg = arg;
\r
890 #if LWIP_CALLBACK_API
\r
893 * Used to specify the function that should be called when a TCP
\r
894 * connection receives data.
\r
898 tcp_recv(struct tcp_pcb *pcb,
\r
899 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
\r
905 * Used to specify the function that should be called when TCP data
\r
906 * has been successfully delivered to the remote host.
\r
911 tcp_sent(struct tcp_pcb *pcb,
\r
912 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
\r
918 * Used to specify the function that should be called when a fatal error
\r
919 * has occured on the connection.
\r
923 tcp_err(struct tcp_pcb *pcb,
\r
924 void (* errf)(void *arg, err_t err))
\r
930 * Used for specifying the function that should be called when a
\r
931 * LISTENing connection has been connected to another host.
\r
935 tcp_accept(struct tcp_pcb *pcb,
\r
936 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
\r
938 ((struct tcp_pcb_listen *)pcb)->accept = accept;
\r
940 #endif /* LWIP_CALLBACK_API */
\r
944 * Used to specify the function that should be called periodically
\r
945 * from TCP. The interval is specified in terms of the TCP coarse
\r
946 * timer interval, which is called twice a second.
\r
950 tcp_poll(struct tcp_pcb *pcb,
\r
951 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
\r
953 #if LWIP_CALLBACK_API
\r
955 #endif /* LWIP_CALLBACK_API */
\r
956 pcb->pollinterval = interval;
\r
960 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
\r
964 tcp_pcb_purge(struct tcp_pcb *pcb)
\r
966 if (pcb->state != CLOSED &&
\r
967 pcb->state != TIME_WAIT &&
\r
968 pcb->state != LISTEN) {
\r
970 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
\r
972 if (pcb->unsent != NULL) {
\r
973 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
\r
975 if (pcb->unacked != NULL) {
\r
976 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
\r
978 #if TCP_QUEUE_OOSEQ /* LW */
\r
979 if (pcb->ooseq != NULL) {
\r
980 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
\r
983 tcp_segs_free(pcb->ooseq);
\r
985 #endif /* TCP_QUEUE_OOSEQ */
\r
986 tcp_segs_free(pcb->unsent);
\r
987 tcp_segs_free(pcb->unacked);
\r
988 pcb->unacked = pcb->unsent = NULL;
\r
993 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
\r
997 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
\r
999 TCP_RMV(pcblist, pcb);
\r
1001 tcp_pcb_purge(pcb);
\r
1003 /* if there is an outstanding delayed ACKs, send it */
\r
1004 if (pcb->state != TIME_WAIT &&
\r
1005 pcb->state != LISTEN &&
\r
1006 pcb->flags & TF_ACK_DELAY) {
\r
1007 pcb->flags |= TF_ACK_NOW;
\r
1010 pcb->state = CLOSED;
\r
1012 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
\r
1016 * Calculates a new initial sequence number for new connections.
\r
1020 tcp_next_iss(void)
\r
1022 static u32_t iss = 6510;
\r
1024 iss += tcp_ticks; /* XXX */
\r
1028 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
\r
1030 tcp_debug_print(struct tcp_hdr *tcphdr)
\r
1032 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
\r
1033 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1034 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
\r
1035 ntohs(tcphdr->src), ntohs(tcphdr->dest)));
\r
1036 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1037 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
\r
1038 ntohl(tcphdr->seqno)));
\r
1039 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1040 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
\r
1041 ntohl(tcphdr->ackno)));
\r
1042 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1043 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
1044 TCPH_HDRLEN(tcphdr),
\r
1045 TCPH_FLAGS(tcphdr) >> 5 & 1,
\r
1046 TCPH_FLAGS(tcphdr) >> 4 & 1,
\r
1047 TCPH_FLAGS(tcphdr) >> 3 & 1,
\r
1048 TCPH_FLAGS(tcphdr) >> 2 & 1,
\r
1049 TCPH_FLAGS(tcphdr) >> 1 & 1,
\r
1050 TCPH_FLAGS(tcphdr) & 1,
\r
1051 ntohs(tcphdr->wnd)));
\r
1052 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
\r
1053 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
\r
1054 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1055 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
\r
1056 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
\r
1057 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1061 tcp_debug_print_state(enum tcp_state s)
\r
1063 LWIP_DEBUGF(TCP_DEBUG, ("State: "));
\r
1066 LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
\r
1069 LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
\r
1072 LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
\r
1075 LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
\r
1078 LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
\r
1081 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
\r
1084 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
\r
1087 LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
\r
1090 LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
\r
1093 LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
\r
1096 LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
\r
1102 tcp_debug_print_flags(u8_t flags)
\r
1104 if (flags & TCP_FIN) {
\r
1105 LWIP_DEBUGF(TCP_DEBUG, ("FIN "));
\r
1107 if (flags & TCP_SYN) {
\r
1108 LWIP_DEBUGF(TCP_DEBUG, ("SYN "));
\r
1110 if (flags & TCP_RST) {
\r
1111 LWIP_DEBUGF(TCP_DEBUG, ("RST "));
\r
1113 if (flags & TCP_PSH) {
\r
1114 LWIP_DEBUGF(TCP_DEBUG, ("PSH "));
\r
1116 if (flags & TCP_ACK) {
\r
1117 LWIP_DEBUGF(TCP_DEBUG, ("ACK "));
\r
1119 if (flags & TCP_URG) {
\r
1120 LWIP_DEBUGF(TCP_DEBUG, ("URG "));
\r
1122 if (flags & TCP_ECE) {
\r
1123 LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
\r
1125 if (flags & TCP_CWR) {
\r
1126 LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
\r
1131 tcp_debug_print_pcbs(void)
\r
1133 struct tcp_pcb *pcb;
\r
1134 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
\r
1135 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1136 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1137 pcb->local_port, pcb->remote_port,
\r
1138 pcb->snd_nxt, pcb->rcv_nxt));
\r
1139 tcp_debug_print_state(pcb->state);
\r
1141 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
\r
1142 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
1143 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1144 pcb->local_port, pcb->remote_port,
\r
1145 pcb->snd_nxt, pcb->rcv_nxt));
\r
1146 tcp_debug_print_state(pcb->state);
\r
1148 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
\r
1149 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1150 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1151 pcb->local_port, pcb->remote_port,
\r
1152 pcb->snd_nxt, pcb->rcv_nxt));
\r
1153 tcp_debug_print_state(pcb->state);
\r
1158 tcp_pcbs_sane(void)
\r
1160 struct tcp_pcb *pcb;
\r
1161 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1162 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
\r
1163 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
\r
1164 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
\r
1166 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1167 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
1171 #endif /* TCP_DEBUG */
\r
1172 #endif /* LWIP_TCP */
\r