3 * Transmission Control Protocol for IP
\r
5 * This file contains common functions for the TCP implementation, such as functinos
\r
6 * for manipulating the data structures and the TCP timer functions. TCP functions
\r
7 * related to input and output is found in tcp_in.c and tcp_out.c respectively.
\r
12 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
\r
13 * All rights reserved.
\r
15 * Redistribution and use in source and binary forms, with or without modification,
\r
16 * are permitted provided that the following conditions are met:
\r
18 * 1. Redistributions of source code must retain the above copyright notice,
\r
19 * this list of conditions and the following disclaimer.
\r
20 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
21 * this list of conditions and the following disclaimer in the documentation
\r
22 * and/or other materials provided with the distribution.
\r
23 * 3. The name of the author may not be used to endorse or promote products
\r
24 * derived from this software without specific prior written permission.
\r
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
\r
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
\r
29 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
\r
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
\r
31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
\r
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
\r
37 * This file is part of the lwIP TCP/IP stack.
\r
39 * Author: Adam Dunkels <adam@sics.se>
\r
43 #include "lwip/opt.h"
\r
45 #if LWIP_TCP /* don't build if not configured for use in lwipopts.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
51 #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
59 /* Times per slowtmr hits */
\r
60 const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
\r
62 /* The TCP PCB lists. */
\r
64 /** List of all TCP PCBs bound but not yet (connected || listening) */
\r
65 struct tcp_pcb *tcp_bound_pcbs;
\r
66 /** List of all TCP PCBs in LISTEN state */
\r
67 union tcp_listen_pcbs_t tcp_listen_pcbs;
\r
68 /** List of all TCP PCBs that are in a state in which
\r
69 * they accept or send data. */
\r
70 struct tcp_pcb *tcp_active_pcbs;
\r
71 /** List of all TCP PCBs in TIME-WAIT state */
\r
72 struct tcp_pcb *tcp_tw_pcbs;
\r
74 struct tcp_pcb *tcp_tmp_pcb;
\r
76 static u8_t tcp_timer;
\r
77 static u16_t tcp_new_port(void);
\r
80 * Called periodically to dispatch TCP timers.
\r
86 /* Call tcp_fasttmr() every 250 ms */
\r
89 if (++tcp_timer & 1) {
\r
90 /* Call tcp_tmr() every 500 ms, i.e., every other timer
\r
91 tcp_tmr() is called. */
\r
97 * Closes the connection held by the PCB.
\r
99 * Listening pcbs are freed and may not be referenced any more.
\r
100 * Connection pcbs are freed if not yet connected and may not be referenced
\r
101 * any more. If a connection is established (at least SYN received or in
\r
102 * a closing state), the connection is closed, and put in a closing state.
\r
103 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore
\r
104 * unsafe to reference it.
\r
106 * @param pcb the tcp_pcb to close
\r
107 * @return ERR_OK if connection has been closed
\r
108 * another err_t if closing failed and pcb is not freed
\r
111 tcp_close(struct tcp_pcb *pcb)
\r
116 LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in "));
\r
117 tcp_debug_print_state(pcb->state);
\r
118 #endif /* TCP_DEBUG */
\r
120 switch (pcb->state) {
\r
122 /* Closing a pcb in the CLOSED state might seem erroneous,
\r
123 * however, it is in this state once allocated and as yet unused
\r
124 * and the user needs some way to free it should the need arise.
\r
125 * Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
\r
126 * or for a pcb that has been used and then entered the CLOSED state
\r
127 * is erroneous, but this should never happen as the pcb has in those cases
\r
128 * been freed, and so any remaining handles are bogus. */
\r
130 TCP_RMV(&tcp_bound_pcbs, pcb);
\r
131 memp_free(MEMP_TCP_PCB, pcb);
\r
136 tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);
\r
137 memp_free(MEMP_TCP_PCB_LISTEN, pcb);
\r
142 tcp_pcb_remove(&tcp_active_pcbs, pcb);
\r
143 memp_free(MEMP_TCP_PCB, pcb);
\r
145 snmp_inc_tcpattemptfails();
\r
148 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
149 if (err == ERR_OK) {
\r
150 snmp_inc_tcpattemptfails();
\r
151 pcb->state = FIN_WAIT_1;
\r
155 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
156 if (err == ERR_OK) {
\r
157 snmp_inc_tcpestabresets();
\r
158 pcb->state = FIN_WAIT_1;
\r
162 err = tcp_send_ctrl(pcb, TCP_FIN);
\r
163 if (err == ERR_OK) {
\r
164 snmp_inc_tcpestabresets();
\r
165 pcb->state = LAST_ACK;
\r
169 /* Has already been closed, do nothing. */
\r
175 if (pcb != NULL && err == ERR_OK) {
\r
176 /* To ensure all data has been sent when tcp_close returns, we have
\r
177 to make sure tcp_output doesn't fail.
\r
178 Since we don't really have to ensure all data has been sent when tcp_close
\r
179 returns (unsent data is sent from tcp timer functions, also), we don't care
\r
180 for the return value of tcp_output for now. */
\r
181 /* @todo: When implementing SO_LINGER, this must be changed somehow:
\r
182 If SOF_LINGER is set, the data should be sent when tcp_close returns. */
\r
189 * Aborts a connection by sending a RST to the remote host and deletes
\r
190 * the local protocol control block. This is done when a connection is
\r
191 * killed because of shortage of memory.
\r
193 * @param pcb the tcp_pcb to abort
\r
196 tcp_abort(struct tcp_pcb *pcb)
\r
198 u32_t seqno, ackno;
\r
199 u16_t remote_port, local_port;
\r
200 struct ip_addr remote_ip, local_ip;
\r
201 #if LWIP_CALLBACK_API
\r
202 void (* errf)(void *arg, err_t err);
\r
203 #endif /* LWIP_CALLBACK_API */
\r
207 /* Figure out on which TCP PCB list we are, and remove us. If we
\r
208 are in an active state, call the receive function associated with
\r
209 the PCB with a NULL argument, and send an RST to the remote end. */
\r
210 if (pcb->state == TIME_WAIT) {
\r
211 tcp_pcb_remove(&tcp_tw_pcbs, pcb);
\r
212 memp_free(MEMP_TCP_PCB, pcb);
\r
214 seqno = pcb->snd_nxt;
\r
215 ackno = pcb->rcv_nxt;
\r
216 ip_addr_set(&local_ip, &(pcb->local_ip));
\r
217 ip_addr_set(&remote_ip, &(pcb->remote_ip));
\r
218 local_port = pcb->local_port;
\r
219 remote_port = pcb->remote_port;
\r
220 #if LWIP_CALLBACK_API
\r
222 #endif /* LWIP_CALLBACK_API */
\r
223 errf_arg = pcb->callback_arg;
\r
224 tcp_pcb_remove(&tcp_active_pcbs, pcb);
\r
225 if (pcb->unacked != NULL) {
\r
226 tcp_segs_free(pcb->unacked);
\r
228 if (pcb->unsent != NULL) {
\r
229 tcp_segs_free(pcb->unsent);
\r
231 #if TCP_QUEUE_OOSEQ
\r
232 if (pcb->ooseq != NULL) {
\r
233 tcp_segs_free(pcb->ooseq);
\r
235 #endif /* TCP_QUEUE_OOSEQ */
\r
236 memp_free(MEMP_TCP_PCB, pcb);
\r
237 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
\r
238 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n"));
\r
239 tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
\r
244 * Binds the connection to a local portnumber and IP address. If the
\r
245 * IP address is not given (i.e., ipaddr == NULL), the IP address of
\r
246 * the outgoing network interface is used instead.
\r
248 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is
\r
250 * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind
\r
251 * to any local address
\r
252 * @param port the local port to bind to
\r
253 * @return ERR_USE if the port is already in use
\r
257 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
\r
259 struct tcp_pcb *cpcb;
\r
261 LWIP_ERROR("tcp_connect: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
\r
264 port = tcp_new_port();
\r
266 /* Check if the address already is in use. */
\r
267 /* Check the listen pcbs. */
\r
268 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
\r
269 cpcb != NULL; cpcb = cpcb->next) {
\r
270 if (cpcb->local_port == port) {
\r
271 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
272 ip_addr_isany(ipaddr) ||
\r
273 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
278 /* Check the connected pcbs. */
\r
279 for(cpcb = tcp_active_pcbs;
\r
280 cpcb != NULL; cpcb = cpcb->next) {
\r
281 if (cpcb->local_port == port) {
\r
282 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
283 ip_addr_isany(ipaddr) ||
\r
284 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
289 /* Check the bound, not yet connected pcbs. */
\r
290 for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) {
\r
291 if (cpcb->local_port == port) {
\r
292 if (ip_addr_isany(&(cpcb->local_ip)) ||
\r
293 ip_addr_isany(ipaddr) ||
\r
294 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
299 /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah),
\r
300 * we have to check the pcbs in TIME-WAIT state, also: */
\r
301 for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
\r
302 if (cpcb->local_port == port) {
\r
303 if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
\r
309 if (!ip_addr_isany(ipaddr)) {
\r
310 pcb->local_ip = *ipaddr;
\r
312 pcb->local_port = port;
\r
313 TCP_REG(&tcp_bound_pcbs, pcb);
\r
314 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
\r
317 #if LWIP_CALLBACK_API
\r
319 * Default accept callback if no accept callback is specified by the user.
\r
322 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
\r
324 LWIP_UNUSED_ARG(arg);
\r
325 LWIP_UNUSED_ARG(pcb);
\r
326 LWIP_UNUSED_ARG(err);
\r
330 #endif /* LWIP_CALLBACK_API */
\r
333 * Set the state of the connection to be LISTEN, which means that it
\r
334 * is able to accept incoming connections. The protocol control block
\r
335 * is reallocated in order to consume less memory. Setting the
\r
336 * connection to LISTEN is an irreversible process.
\r
338 * @param pcb the original tcp_pcb
\r
339 * @param backlog the incoming connections queue limit
\r
340 * @return tcp_pcb used for listening, consumes less memory.
\r
342 * @note The original tcp_pcb is freed. This function therefore has to be
\r
343 * called like this:
\r
344 * tpcb = tcp_listen(tpcb);
\r
347 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
\r
349 struct tcp_pcb_listen *lpcb;
\r
351 LWIP_UNUSED_ARG(backlog);
\r
352 LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
\r
354 /* already listening? */
\r
355 if (pcb->state == LISTEN) {
\r
358 lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);
\r
359 if (lpcb == NULL) {
\r
362 lpcb->callback_arg = pcb->callback_arg;
\r
363 lpcb->local_port = pcb->local_port;
\r
364 lpcb->state = LISTEN;
\r
365 lpcb->so_options = pcb->so_options;
\r
366 lpcb->so_options |= SOF_ACCEPTCONN;
\r
367 lpcb->ttl = pcb->ttl;
\r
368 lpcb->tos = pcb->tos;
\r
369 ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
\r
370 TCP_RMV(&tcp_bound_pcbs, pcb);
\r
371 memp_free(MEMP_TCP_PCB, pcb);
\r
372 #if LWIP_CALLBACK_API
\r
373 lpcb->accept = tcp_accept_null;
\r
374 #endif /* LWIP_CALLBACK_API */
\r
375 #if TCP_LISTEN_BACKLOG
\r
376 lpcb->accepts_pending = 0;
\r
377 lpcb->backlog = (backlog ? backlog : 1);
\r
378 #endif /* TCP_LISTEN_BACKLOG */
\r
379 TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb);
\r
380 return (struct tcp_pcb *)lpcb;
\r
384 * This function should be called by the application when it has
\r
385 * processed the data. The purpose is to advertise a larger window
\r
386 * when the data has been processed.
\r
388 * @param pcb the tcp_pcb for which data is read
\r
389 * @param len the amount of bytes that have been read by the application
\r
392 tcp_recved(struct tcp_pcb *pcb, u16_t len)
\r
394 if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
\r
395 pcb->rcv_wnd = TCP_WND;
\r
396 pcb->rcv_ann_wnd = TCP_WND;
\r
398 pcb->rcv_wnd += len;
\r
399 if (pcb->rcv_wnd >= pcb->mss) {
\r
400 pcb->rcv_ann_wnd = pcb->rcv_wnd;
\r
404 if (!(pcb->flags & TF_ACK_DELAY) &&
\r
405 !(pcb->flags & TF_ACK_NOW)) {
\r
407 * We send an ACK here (if one is not already pending, hence
\r
408 * the above tests) as tcp_recved() implies that the application
\r
409 * has processed some data, and so we can open the receiver's
\r
410 * window to allow more to be transmitted. This could result in
\r
411 * two ACKs being sent for each received packet in some limited cases
\r
412 * (where the application is only receiving data, and is slow to
\r
413 * process it) but it is necessary to guarantee that the sender can
\r
414 * continue to transmit.
\r
418 else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) {
\r
419 /* If we can send a window update such that there is a full
\r
420 * segment available in the window, do so now. This is sort of
\r
421 * nagle-like in its goals, and tries to hit a compromise between
\r
422 * sending acks each time the window is updated, and only sending
\r
423 * window updates when a timer expires. The "threshold" used
\r
424 * above (currently TCP_WND/2) can be tuned to be more or less
\r
429 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
\r
430 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
\r
434 * A nastly hack featuring 'goto' statements that allocates a
\r
435 * new TCP local port.
\r
437 * @return a new (free) local TCP port number
\r
442 struct tcp_pcb *pcb;
\r
443 #ifndef TCP_LOCAL_PORT_RANGE_START
\r
444 #define TCP_LOCAL_PORT_RANGE_START 4096
\r
445 #define TCP_LOCAL_PORT_RANGE_END 0x7fff
\r
447 static u16_t port = TCP_LOCAL_PORT_RANGE_START;
\r
450 if (++port > TCP_LOCAL_PORT_RANGE_END) {
\r
451 port = TCP_LOCAL_PORT_RANGE_START;
\r
454 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
455 if (pcb->local_port == port) {
\r
459 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
460 if (pcb->local_port == port) {
\r
464 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
465 if (pcb->local_port == port) {
\r
473 * Connects to another host. The function given as the "connected"
\r
474 * argument will be called when the connection has been established.
\r
476 * @param pcb the tcp_pcb used to establish the connection
\r
477 * @param ipaddr the remote ip address to connect to
\r
478 * @param port the remote tcp port to connect to
\r
479 * @param connected callback function to call when connected (or on error)
\r
480 * @return ERR_VAL if invalid arguments are given
\r
481 * ERR_OK if connect request has been sent
\r
482 * other err_t values if connect request couldn't be sent
\r
485 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
\r
486 err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
\r
492 LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
\r
494 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
\r
495 if (ipaddr != NULL) {
\r
496 pcb->remote_ip = *ipaddr;
\r
500 pcb->remote_port = port;
\r
501 if (pcb->local_port == 0) {
\r
502 pcb->local_port = tcp_new_port();
\r
504 iss = tcp_next_iss();
\r
506 pcb->snd_nxt = iss;
\r
507 pcb->lastack = iss - 1;
\r
508 pcb->snd_lbb = iss - 1;
\r
509 pcb->rcv_wnd = TCP_WND;
\r
510 pcb->rcv_ann_wnd = TCP_WND;
\r
511 pcb->snd_wnd = TCP_WND;
\r
512 /* The send MSS is updated when an MSS option is received. */
\r
513 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
\r
514 #if TCP_CALCULATE_EFF_SEND_MSS
\r
515 pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
\r
516 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
\r
518 pcb->ssthresh = pcb->mss * 10;
\r
519 pcb->state = SYN_SENT;
\r
520 #if LWIP_CALLBACK_API
\r
521 pcb->connected = connected;
\r
522 #endif /* LWIP_CALLBACK_API */
\r
523 TCP_RMV(&tcp_bound_pcbs, pcb);
\r
524 TCP_REG(&tcp_active_pcbs, pcb);
\r
526 snmp_inc_tcpactiveopens();
\r
528 /* Build an MSS option */
\r
529 optdata = TCP_BUILD_MSS_OPTION();
\r
531 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
\r
532 if (ret == ERR_OK) {
\r
539 * Called every 500 ms and implements the retransmission timer and the timer that
\r
540 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
\r
541 * various timers such as the inactivity timer in each PCB.
\r
543 * Automatically called from tcp_tmr().
\r
548 struct tcp_pcb *pcb, *pcb2, *prev;
\r
550 u8_t pcb_remove; /* flag if a PCB should be removed */
\r
557 /* Steps through all of the active PCBs. */
\r
559 pcb = tcp_active_pcbs;
\r
561 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
\r
563 while (pcb != NULL) {
\r
564 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
\r
565 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
\r
566 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
\r
567 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
\r
571 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
\r
573 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
\r
575 else if (pcb->nrtx == TCP_MAXRTX) {
\r
577 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
\r
579 if (pcb->persist_backoff > 0) {
\r
580 /* If snd_wnd is zero, use persist timer to send 1 byte probes
\r
581 * instead of using the standard retransmission mechanism. */
\r
582 pcb->persist_cnt++;
\r
583 if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {
\r
584 pcb->persist_cnt = 0;
\r
585 if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
\r
586 pcb->persist_backoff++;
\r
588 tcp_zero_window_probe(pcb);
\r
591 /* Increase the retransmission timer if it is running */
\r
592 if(pcb->rtime >= 0)
\r
595 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
\r
596 /* Time for a retransmission. */
\r
597 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F
\r
598 " pcb->rto %"S16_F"\n",
\r
599 pcb->rtime, pcb->rto));
\r
601 /* Double retransmission time-out unless we are trying to
\r
602 * connect to somebody (i.e., we are in SYN_SENT). */
\r
603 if (pcb->state != SYN_SENT) {
\r
604 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
\r
607 /* Reset the retransmission timer. */
\r
610 /* Reduce congestion window and ssthresh. */
\r
611 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
\r
612 pcb->ssthresh = eff_wnd >> 1;
\r
613 if (pcb->ssthresh < pcb->mss) {
\r
614 pcb->ssthresh = pcb->mss * 2;
\r
616 pcb->cwnd = pcb->mss;
\r
617 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F
\r
618 " ssthresh %"U16_F"\n",
\r
619 pcb->cwnd, pcb->ssthresh));
\r
621 /* The following needs to be called AFTER cwnd is set to one
\r
623 tcp_rexmit_rto(pcb);
\r
627 /* Check if this PCB has stayed too long in FIN-WAIT-2 */
\r
628 if (pcb->state == FIN_WAIT_2) {
\r
629 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
630 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
632 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
\r
636 /* Check if KEEPALIVE should be sent */
\r
637 if((pcb->so_options & SOF_KEEPALIVE) &&
\r
638 ((pcb->state == ESTABLISHED) ||
\r
639 (pcb->state == CLOSE_WAIT))) {
\r
640 #if LWIP_TCP_KEEPALIVE
\r
641 if((u32_t)(tcp_ticks - pcb->tmr) >
\r
642 (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl))
\r
643 / TCP_SLOW_INTERVAL)
\r
645 if((u32_t)(tcp_ticks - pcb->tmr) >
\r
646 (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
\r
647 #endif /* LWIP_TCP_KEEPALIVE */
\r
649 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
\r
650 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
\r
651 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
\r
655 #if LWIP_TCP_KEEPALIVE
\r
656 else if((u32_t)(tcp_ticks - pcb->tmr) >
\r
657 (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl)
\r
658 / TCP_SLOW_INTERVAL)
\r
660 else if((u32_t)(tcp_ticks - pcb->tmr) >
\r
661 (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT)
\r
662 / TCP_SLOW_INTERVAL)
\r
663 #endif /* LWIP_TCP_KEEPALIVE */
\r
665 tcp_keepalive(pcb);
\r
666 pcb->keep_cnt_sent++;
\r
670 /* If this PCB has queued out of sequence data, but has been
\r
671 inactive for too long, will drop the data (it will eventually
\r
672 be retransmitted). */
\r
673 #if TCP_QUEUE_OOSEQ
\r
674 if (pcb->ooseq != NULL &&
\r
675 (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) {
\r
676 tcp_segs_free(pcb->ooseq);
\r
678 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
\r
680 #endif /* TCP_QUEUE_OOSEQ */
\r
682 /* Check if this PCB has stayed too long in SYN-RCVD */
\r
683 if (pcb->state == SYN_RCVD) {
\r
684 if ((u32_t)(tcp_ticks - pcb->tmr) >
\r
685 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
\r
687 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
\r
691 /* Check if this PCB has stayed too long in LAST-ACK */
\r
692 if (pcb->state == LAST_ACK) {
\r
693 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
695 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
\r
699 /* If the PCB should be removed, do it. */
\r
701 tcp_pcb_purge(pcb);
\r
702 /* Remove PCB from tcp_active_pcbs list. */
\r
703 if (prev != NULL) {
\r
704 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
\r
705 prev->next = pcb->next;
\r
707 /* This PCB was the first. */
\r
708 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
\r
709 tcp_active_pcbs = pcb->next;
\r
712 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
\r
715 memp_free(MEMP_TCP_PCB, pcb);
\r
719 /* We check if we should poll the connection. */
\r
721 if (pcb->polltmr >= pcb->pollinterval) {
\r
723 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
\r
724 TCP_EVENT_POLL(pcb, err);
\r
725 if (err == ERR_OK) {
\r
736 /* Steps through all of the TIME-WAIT PCBs. */
\r
739 while (pcb != NULL) {
\r
740 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
743 /* Check if this PCB has stayed long enough in TIME-WAIT */
\r
744 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
\r
750 /* If the PCB should be removed, do it. */
\r
752 tcp_pcb_purge(pcb);
\r
753 /* Remove PCB from tcp_tw_pcbs list. */
\r
754 if (prev != NULL) {
\r
755 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
\r
756 prev->next = pcb->next;
\r
758 /* This PCB was the first. */
\r
759 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
\r
760 tcp_tw_pcbs = pcb->next;
\r
763 memp_free(MEMP_TCP_PCB, pcb);
\r
773 * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously
\r
774 * "refused" by upper layer (application) and sends delayed ACKs.
\r
776 * Automatically called from tcp_tmr().
\r
781 struct tcp_pcb *pcb;
\r
783 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
784 /* If there is data which was previously "refused" by upper layer */
\r
785 if (pcb->refused_data != NULL) {
\r
786 /* Notify again application with data previously received. */
\r
788 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n"));
\r
789 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
\r
790 if (err == ERR_OK) {
\r
791 pcb->refused_data = NULL;
\r
795 /* send delayed ACKs */
\r
796 if (pcb->flags & TF_ACK_DELAY) {
\r
797 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
\r
799 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
\r
805 * Deallocates a list of TCP segments (tcp_seg structures).
\r
807 * @param seg tcp_seg list of TCP segments to free
\r
808 * @return the number of pbufs that were deallocated
\r
811 tcp_segs_free(struct tcp_seg *seg)
\r
814 struct tcp_seg *next;
\r
815 while (seg != NULL) {
\r
817 count += tcp_seg_free(seg);
\r
824 * Frees a TCP segment (tcp_seg structure).
\r
826 * @param seg single tcp_seg to free
\r
827 * @return the number of pbufs that were deallocated
\r
830 tcp_seg_free(struct tcp_seg *seg)
\r
835 if (seg->p != NULL) {
\r
836 count = pbuf_free(seg->p);
\r
839 #endif /* TCP_DEBUG */
\r
841 memp_free(MEMP_TCP_SEG, seg);
\r
847 * Sets the priority of a connection.
\r
849 * @param pcb the tcp_pcb to manipulate
\r
850 * @param prio new priority
\r
853 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
\r
857 #if TCP_QUEUE_OOSEQ
\r
860 * Returns a copy of the given TCP segment.
\r
861 * The pbuf and data are not copied, only the pointers
\r
863 * @param seg the old tcp_seg
\r
864 * @return a copy of seg
\r
867 tcp_seg_copy(struct tcp_seg *seg)
\r
869 struct tcp_seg *cseg;
\r
871 cseg = memp_malloc(MEMP_TCP_SEG);
\r
872 if (cseg == NULL) {
\r
875 SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
\r
881 #if LWIP_CALLBACK_API
\r
883 * Default receive callback that is called if the user didn't register
\r
884 * a recv callback for the pcb.
\r
887 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
\r
892 } else if (err == ERR_OK) {
\r
893 return tcp_close(pcb);
\r
897 #endif /* LWIP_CALLBACK_API */
\r
900 * Kills the oldest active connection that has lower priority than prio.
\r
902 * @param prio minimum priority
\r
905 tcp_kill_prio(u8_t prio)
\r
907 struct tcp_pcb *pcb, *inactive;
\r
912 mprio = TCP_PRIO_MAX;
\r
914 /* We kill the oldest active connection that has lower priority than prio. */
\r
917 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
918 if (pcb->prio <= prio &&
\r
919 pcb->prio <= mprio &&
\r
920 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
921 inactivity = tcp_ticks - pcb->tmr;
\r
926 if (inactive != NULL) {
\r
927 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
\r
928 (void *)inactive, inactivity));
\r
929 tcp_abort(inactive);
\r
934 * Kills the oldest connection that is in TIME_WAIT state.
\r
935 * Called from tcp_alloc() if no more connections are available.
\r
938 tcp_kill_timewait(void)
\r
940 struct tcp_pcb *pcb, *inactive;
\r
945 /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */
\r
946 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
947 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
\r
948 inactivity = tcp_ticks - pcb->tmr;
\r
952 if (inactive != NULL) {
\r
953 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
\r
954 (void *)inactive, inactivity));
\r
955 tcp_abort(inactive);
\r
960 * Allocate a new tcp_pcb structure.
\r
962 * @param prio priority for the new pcb
\r
963 * @return a new tcp_pcb that initially is in state CLOSED
\r
966 tcp_alloc(u8_t prio)
\r
968 struct tcp_pcb *pcb;
\r
971 pcb = memp_malloc(MEMP_TCP_PCB);
\r
973 /* Try killing oldest connection in TIME-WAIT. */
\r
974 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
\r
975 tcp_kill_timewait();
\r
976 /* Try to allocate a tcp_pcb again. */
\r
977 pcb = memp_malloc(MEMP_TCP_PCB);
\r
979 /* Try killing active connections with lower priority than the new one. */
\r
980 tcp_kill_prio(prio);
\r
981 /* Try to allocate a tcp_pcb again. */
\r
982 pcb = memp_malloc(MEMP_TCP_PCB);
\r
986 memset(pcb, 0, sizeof(struct tcp_pcb));
\r
987 pcb->prio = TCP_PRIO_NORMAL;
\r
988 pcb->snd_buf = TCP_SND_BUF;
\r
989 pcb->snd_queuelen = 0;
\r
990 pcb->rcv_wnd = TCP_WND;
\r
991 pcb->rcv_ann_wnd = TCP_WND;
\r
993 pcb->ttl = TCP_TTL;
\r
994 /* The send MSS is updated when an MSS option is received. */
\r
995 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
\r
996 pcb->rto = 3000 / TCP_SLOW_INTERVAL;
\r
998 pcb->sv = 3000 / TCP_SLOW_INTERVAL;
\r
1001 iss = tcp_next_iss();
\r
1002 pcb->snd_wl2 = iss;
\r
1003 pcb->snd_nxt = iss;
\r
1004 pcb->snd_max = iss;
\r
1005 pcb->lastack = iss;
\r
1006 pcb->snd_lbb = iss;
\r
1007 pcb->tmr = tcp_ticks;
\r
1011 #if LWIP_CALLBACK_API
\r
1012 pcb->recv = tcp_recv_null;
\r
1013 #endif /* LWIP_CALLBACK_API */
\r
1015 /* Init KEEPALIVE timer */
\r
1016 pcb->keep_idle = TCP_KEEPIDLE_DEFAULT;
\r
1018 #if LWIP_TCP_KEEPALIVE
\r
1019 pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
\r
1020 pcb->keep_cnt = TCP_KEEPCNT_DEFAULT;
\r
1021 #endif /* LWIP_TCP_KEEPALIVE */
\r
1023 pcb->keep_cnt_sent = 0;
\r
1029 * Creates a new TCP protocol control block but doesn't place it on
\r
1030 * any of the TCP PCB lists.
\r
1031 * The pcb is not put on any list until binding using tcp_bind().
\r
1033 * @internal: Maybe there should be a idle TCP PCB list where these
\r
1034 * PCBs are put on. Port reservation using tcp_bind() is implemented but
\r
1035 * allocated pcbs that are not bound can't be killed automatically if wanting
\r
1036 * to allocate a pcb with higher prio (@see tcp_kill_prio())
\r
1038 * @return a new tcp_pcb that initially is in state CLOSED
\r
1043 return tcp_alloc(TCP_PRIO_NORMAL);
\r
1047 * Used to specify the argument that should be passed callback
\r
1050 * @param pcb tcp_pcb to set the callback argument
\r
1051 * @param arg void pointer argument to pass to callback functions
\r
1054 tcp_arg(struct tcp_pcb *pcb, void *arg)
\r
1056 pcb->callback_arg = arg;
\r
1058 #if LWIP_CALLBACK_API
\r
1061 * Used to specify the function that should be called when a TCP
\r
1062 * connection receives data.
\r
1064 * @param pcb tcp_pcb to set the recv callback
\r
1065 * @param recv callback function to call for this pcb when data is received
\r
1068 tcp_recv(struct tcp_pcb *pcb,
\r
1069 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
\r
1075 * Used to specify the function that should be called when TCP data
\r
1076 * has been successfully delivered to the remote host.
\r
1078 * @param pcb tcp_pcb to set the sent callback
\r
1079 * @param sent callback function to call for this pcb when data is successfully sent
\r
1082 tcp_sent(struct tcp_pcb *pcb,
\r
1083 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
\r
1089 * Used to specify the function that should be called when a fatal error
\r
1090 * has occured on the connection.
\r
1092 * @param pcb tcp_pcb to set the err callback
\r
1093 * @param errf callback function to call for this pcb when a fatal error
\r
1094 * has occured on the connection
\r
1097 tcp_err(struct tcp_pcb *pcb,
\r
1098 void (* errf)(void *arg, err_t err))
\r
1104 * Used for specifying the function that should be called when a
\r
1105 * LISTENing connection has been connected to another host.
\r
1107 * @param pcb tcp_pcb to set the accept callback
\r
1108 * @param accept callback function to call for this pcb when LISTENing
\r
1109 * connection has been connected to another host
\r
1112 tcp_accept(struct tcp_pcb *pcb,
\r
1113 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
\r
1115 ((struct tcp_pcb_listen *)pcb)->accept = accept;
\r
1117 #endif /* LWIP_CALLBACK_API */
\r
1121 * Used to specify the function that should be called periodically
\r
1122 * from TCP. The interval is specified in terms of the TCP coarse
\r
1123 * timer interval, which is called twice a second.
\r
1127 tcp_poll(struct tcp_pcb *pcb,
\r
1128 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
\r
1130 #if LWIP_CALLBACK_API
\r
1132 #endif /* LWIP_CALLBACK_API */
\r
1133 pcb->pollinterval = interval;
\r
1137 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory
\r
1138 * (pcb->ooseq, pcb->unsent and pcb->unacked are freed).
\r
1140 * @param pcb tcp_pcb to purge. The pcb itself is not deallocated!
\r
1143 tcp_pcb_purge(struct tcp_pcb *pcb)
\r
1145 if (pcb->state != CLOSED &&
\r
1146 pcb->state != TIME_WAIT &&
\r
1147 pcb->state != LISTEN) {
\r
1149 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
\r
1151 if (pcb->refused_data != NULL) {
\r
1152 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
\r
1153 pbuf_free(pcb->refused_data);
\r
1154 pcb->refused_data = NULL;
\r
1156 if (pcb->unsent != NULL) {
\r
1157 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
\r
1159 if (pcb->unacked != NULL) {
\r
1160 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
\r
1162 #if TCP_QUEUE_OOSEQ /* LW */
\r
1163 if (pcb->ooseq != NULL) {
\r
1164 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
\r
1167 /* Stop the retransmission timer as it will expect data on unacked
\r
1168 queue if it fires */
\r
1171 tcp_segs_free(pcb->ooseq);
\r
1172 pcb->ooseq = NULL;
\r
1173 #endif /* TCP_QUEUE_OOSEQ */
\r
1174 tcp_segs_free(pcb->unsent);
\r
1175 tcp_segs_free(pcb->unacked);
\r
1176 pcb->unacked = pcb->unsent = NULL;
\r
1181 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
\r
1183 * @param pcblist PCB list to purge.
\r
1184 * @param pcb tcp_pcb to purge. The pcb itself is also deallocated!
\r
1187 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
\r
1189 TCP_RMV(pcblist, pcb);
\r
1191 tcp_pcb_purge(pcb);
\r
1193 /* if there is an outstanding delayed ACKs, send it */
\r
1194 if (pcb->state != TIME_WAIT &&
\r
1195 pcb->state != LISTEN &&
\r
1196 pcb->flags & TF_ACK_DELAY) {
\r
1197 pcb->flags |= TF_ACK_NOW;
\r
1201 if (pcb->state != LISTEN) {
\r
1202 LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL);
\r
1203 LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL);
\r
1204 #if TCP_QUEUE_OOSEQ
\r
1205 LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL);
\r
1206 #endif /* TCP_QUEUE_OOSEQ */
\r
1209 pcb->state = CLOSED;
\r
1211 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
\r
1215 * Calculates a new initial sequence number for new connections.
\r
1217 * @return u32_t pseudo random sequence number
\r
1220 tcp_next_iss(void)
\r
1222 static u32_t iss = 6510;
\r
1224 iss += tcp_ticks; /* XXX */
\r
1228 #if TCP_CALCULATE_EFF_SEND_MSS
\r
1230 * Calcluates the effective send mss that can be used for a specific IP address
\r
1231 * by using ip_route to determin the netif used to send to the address and
\r
1232 * calculating the minimum of TCP_MSS and that netif's mtu (if set).
\r
1235 tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)
\r
1238 struct netif *outif;
\r
1240 outif = ip_route(addr);
\r
1241 if ((outif != NULL) && (outif->mtu != 0)) {
\r
1242 mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
\r
1243 /* RFC 1122, chap 4.2.2.6:
\r
1244 * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
\r
1245 * but we only send options with SYN and that is never filled with data! */
\r
1246 sendmss = LWIP_MIN(sendmss, mss_s);
\r
1250 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
\r
1252 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
\r
1254 * Print a tcp header for debugging purposes.
\r
1256 * @param tcphdr pointer to a struct tcp_hdr
\r
1259 tcp_debug_print(struct tcp_hdr *tcphdr)
\r
1261 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
\r
1262 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1263 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
\r
1264 ntohs(tcphdr->src), ntohs(tcphdr->dest)));
\r
1265 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1266 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
\r
1267 ntohl(tcphdr->seqno)));
\r
1268 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1269 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
\r
1270 ntohl(tcphdr->ackno)));
\r
1271 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1272 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
1273 TCPH_HDRLEN(tcphdr),
\r
1274 TCPH_FLAGS(tcphdr) >> 5 & 1,
\r
1275 TCPH_FLAGS(tcphdr) >> 4 & 1,
\r
1276 TCPH_FLAGS(tcphdr) >> 3 & 1,
\r
1277 TCPH_FLAGS(tcphdr) >> 2 & 1,
\r
1278 TCPH_FLAGS(tcphdr) >> 1 & 1,
\r
1279 TCPH_FLAGS(tcphdr) & 1,
\r
1280 ntohs(tcphdr->wnd)));
\r
1281 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
\r
1282 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
\r
1283 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1284 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
\r
1285 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
\r
1286 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
\r
1290 * Print a tcp state for debugging purposes.
\r
1292 * @param s enum tcp_state to print
\r
1295 tcp_debug_print_state(enum tcp_state s)
\r
1297 LWIP_DEBUGF(TCP_DEBUG, ("State: "));
\r
1300 LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));
\r
1303 LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));
\r
1306 LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));
\r
1309 LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));
\r
1312 LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));
\r
1315 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));
\r
1318 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));
\r
1321 LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));
\r
1324 LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));
\r
1327 LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));
\r
1330 LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));
\r
1336 * Print tcp flags for debugging purposes.
\r
1338 * @param flags tcp flags, all active flags are printed
\r
1341 tcp_debug_print_flags(u8_t flags)
\r
1343 if (flags & TCP_FIN) {
\r
1344 LWIP_DEBUGF(TCP_DEBUG, ("FIN "));
\r
1346 if (flags & TCP_SYN) {
\r
1347 LWIP_DEBUGF(TCP_DEBUG, ("SYN "));
\r
1349 if (flags & TCP_RST) {
\r
1350 LWIP_DEBUGF(TCP_DEBUG, ("RST "));
\r
1352 if (flags & TCP_PSH) {
\r
1353 LWIP_DEBUGF(TCP_DEBUG, ("PSH "));
\r
1355 if (flags & TCP_ACK) {
\r
1356 LWIP_DEBUGF(TCP_DEBUG, ("ACK "));
\r
1358 if (flags & TCP_URG) {
\r
1359 LWIP_DEBUGF(TCP_DEBUG, ("URG "));
\r
1361 if (flags & TCP_ECE) {
\r
1362 LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
\r
1364 if (flags & TCP_CWR) {
\r
1365 LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
\r
1370 * Print all tcp_pcbs in every list for debugging purposes.
\r
1373 tcp_debug_print_pcbs(void)
\r
1375 struct tcp_pcb *pcb;
\r
1376 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
\r
1377 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1378 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1379 pcb->local_port, pcb->remote_port,
\r
1380 pcb->snd_nxt, pcb->rcv_nxt));
\r
1381 tcp_debug_print_state(pcb->state);
\r
1383 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
\r
1384 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
\r
1385 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1386 pcb->local_port, pcb->remote_port,
\r
1387 pcb->snd_nxt, pcb->rcv_nxt));
\r
1388 tcp_debug_print_state(pcb->state);
\r
1390 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
\r
1391 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1392 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
\r
1393 pcb->local_port, pcb->remote_port,
\r
1394 pcb->snd_nxt, pcb->rcv_nxt));
\r
1395 tcp_debug_print_state(pcb->state);
\r
1400 * Check state consistency of the tcp_pcb lists.
\r
1403 tcp_pcbs_sane(void)
\r
1405 struct tcp_pcb *pcb;
\r
1406 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1407 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
\r
1408 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
\r
1409 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
\r
1411 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
\r
1412 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
\r
1416 #endif /* TCP_DEBUG */
\r
1418 #endif /* LWIP_TCP */
\r