]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/tcp.c
First version under SVN is V4.0.1
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / tcp.c
1 /**\r
2  * @file\r
3  *\r
4  * Transmission Control Protocol for IP\r
5  *\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
9  *\r
10  */\r
11 \r
12 /*\r
13  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
14  * All rights reserved. \r
15  * \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
18  *\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
26  *\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
36  * OF SUCH DAMAGE.\r
37  *\r
38  * This file is part of the lwIP TCP/IP stack.\r
39  * \r
40  * Author: Adam Dunkels <adam@sics.se>\r
41  *\r
42  */\r
43 \r
44 #include <string.h>\r
45 \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 \r
51 #include "lwip/tcp.h"\r
52 #if LWIP_TCP\r
53 \r
54 /* Incremented every coarse grained timer shot\r
55    (typically every 500 ms, determined by TCP_COARSE_TIMEOUT). */\r
56 u32_t tcp_ticks;\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 \r
60 /* The TCP PCB lists. */\r
61 \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
69 \r
70 struct tcp_pcb *tcp_tmp_pcb;\r
71 \r
72 static u8_t tcp_timer;\r
73 static u16_t tcp_new_port(void);\r
74 \r
75 /**\r
76  * Initializes the TCP layer.\r
77  */\r
78 void\r
79 tcp_init(void)\r
80 {\r
81   /* Clear globals. */\r
82   tcp_listen_pcbs.listen_pcbs = NULL;\r
83   tcp_active_pcbs = NULL;\r
84   tcp_tw_pcbs = NULL;\r
85   tcp_tmp_pcb = NULL;\r
86   \r
87   /* initialize timer */\r
88   tcp_ticks = 0;\r
89   tcp_timer = 0;\r
90   \r
91 }\r
92 \r
93 /**\r
94  * Called periodically to dispatch TCP timers.\r
95  *\r
96  */\r
97 void\r
98 tcp_tmr(void)\r
99 {\r
100   /* Call tcp_fasttmr() every 250 ms */\r
101   tcp_fasttmr();\r
102 \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
106     tcp_slowtmr();\r
107   }\r
108 }\r
109 \r
110 /**\r
111  * Closes the connection held by the PCB.\r
112  *\r
113  */\r
114 err_t\r
115 tcp_close(struct tcp_pcb *pcb)\r
116 {\r
117   err_t err;\r
118 \r
119 #if TCP_DEBUG\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
125   case CLOSED:\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
133     err = ERR_OK;\r
134     memp_free(MEMP_TCP_PCB, pcb);\r
135     pcb = NULL;\r
136     break;\r
137   case LISTEN:\r
138     err = ERR_OK;\r
139     tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);\r
140     memp_free(MEMP_TCP_PCB_LISTEN, pcb);\r
141     pcb = NULL;\r
142     break;\r
143   case SYN_SENT:\r
144     err = ERR_OK;\r
145     tcp_pcb_remove(&tcp_active_pcbs, pcb);\r
146     memp_free(MEMP_TCP_PCB, pcb);\r
147     pcb = NULL;\r
148     break;\r
149   case SYN_RCVD:\r
150   case ESTABLISHED:\r
151     err = tcp_send_ctrl(pcb, TCP_FIN);\r
152     if (err == ERR_OK) {\r
153       pcb->state = FIN_WAIT_1;\r
154     }\r
155     break;\r
156   case CLOSE_WAIT:\r
157     err = tcp_send_ctrl(pcb, TCP_FIN);\r
158     if (err == ERR_OK) {\r
159       pcb->state = LAST_ACK;\r
160     }\r
161     break;\r
162   default:\r
163     /* Has already been closed, do nothing. */\r
164     err = ERR_OK;\r
165     pcb = NULL;\r
166     break;\r
167   }\r
168 \r
169   if (pcb != NULL && err == ERR_OK) {\r
170     err = tcp_output(pcb);\r
171   }\r
172   return err;\r
173 }\r
174 \r
175 /**\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
179  *\r
180  */\r
181 void\r
182 tcp_abort(struct tcp_pcb *pcb)\r
183 {\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
190   void *errf_arg;\r
191 \r
192   \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
199   } else {\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
207     errf = pcb->errf;\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
213     }\r
214     if (pcb->unsent != NULL) {\r
215       tcp_segs_free(pcb->unsent);\r
216     }\r
217 #if TCP_QUEUE_OOSEQ    \r
218     if (pcb->ooseq != NULL) {\r
219       tcp_segs_free(pcb->ooseq);\r
220     }\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
226   }\r
227 }\r
228 \r
229 /**\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
233  *\r
234  */\r
235 \r
236 err_t\r
237 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)\r
238 {\r
239   struct tcp_pcb *cpcb;\r
240 #if SO_REUSE\r
241   int reuse_port_all_set = 1;\r
242 #endif /* SO_REUSE */\r
243 \r
244   if (port == 0) {\r
245     port = tcp_new_port();\r
246   }\r
247 #if SO_REUSE == 0\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
255           return ERR_USE;\r
256       }\r
257     }\r
258   }\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
265   return ERR_USE;\r
266       }\r
267     }\r
268   }\r
269 #else /* SO_REUSE */\r
270   /* Search through list of PCB's in LISTEN state. \r
271      \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
276   \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
279   \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
288         }\r
289         else {\r
290           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));\r
291           return ERR_USE;\r
292         }\r
293       }\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
298           return ERR_USE;\r
299         }      \r
300         else {\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
302         }     \r
303       }\r
304     }\r
305   }\r
306 \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
315         }\r
316         else {\r
317           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));\r
318           return ERR_USE;\r
319         }\r
320       }\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
325           return ERR_USE;\r
326         }   \r
327         else {\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
329         }        \r
330       }\r
331     }\r
332   }\r
333 \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
336      \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
339      \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
347           return ERR_USE;\r
348         }\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
352         }\r
353       }\r
354     }\r
355   }\r
356 \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
361     return ERR_USE;\r
362   }\r
363 #endif /* SO_REUSE */\r
364 \r
365   if (!ip_addr_isany(ipaddr)) {\r
366     pcb->local_ip = *ipaddr;\r
367   }\r
368   pcb->local_port = port;\r
369   LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));\r
370   return ERR_OK;\r
371 }\r
372 #if LWIP_CALLBACK_API\r
373 static err_t\r
374 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)\r
375 {\r
376   (void)arg;\r
377   (void)pcb;\r
378   (void)err;\r
379 \r
380   return ERR_ABRT;\r
381 }\r
382 #endif /* LWIP_CALLBACK_API */\r
383 \r
384 /**\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
389  *\r
390  */\r
391 struct tcp_pcb *\r
392 tcp_listen(struct tcp_pcb *pcb)\r
393 {\r
394   struct tcp_pcb_listen *lpcb;\r
395 \r
396   /* already listening? */\r
397   if (pcb->state == LISTEN) {\r
398     return pcb;\r
399   }\r
400   lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);\r
401   if (lpcb == NULL) {\r
402     return NULL;\r
403   }\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
418 }\r
419 \r
420 /**\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
424  *\r
425  */\r
426 void\r
427 tcp_recved(struct tcp_pcb *pcb, u16_t len)\r
428 {\r
429   if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {\r
430     pcb->rcv_wnd = TCP_WND;\r
431   } else {\r
432     pcb->rcv_wnd += len;\r
433   }\r
434   if (!(pcb->flags & TF_ACK_DELAY) &&\r
435      !(pcb->flags & TF_ACK_NOW)) {\r
436     /*\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
445      */\r
446     tcp_ack(pcb);\r
447   } \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
455      * aggressive  */\r
456     tcp_ack_now(pcb);\r
457   }\r
458 \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
461 }\r
462 \r
463 /**\r
464  * A nastly hack featuring 'goto' statements that allocates a\r
465  * new TCP local port.\r
466  */\r
467 static u16_t\r
468 tcp_new_port(void)\r
469 {\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
474 #endif\r
475   static u16_t port = TCP_LOCAL_PORT_RANGE_START;\r
476   \r
477  again:\r
478   if (++port > TCP_LOCAL_PORT_RANGE_END) {\r
479     port = TCP_LOCAL_PORT_RANGE_START;\r
480   }\r
481   \r
482   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {\r
483     if (pcb->local_port == port) {\r
484       goto again;\r
485     }\r
486   }\r
487   for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {\r
488     if (pcb->local_port == port) {\r
489       goto again;\r
490     }\r
491   }\r
492   for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {\r
493     if (pcb->local_port == port) {\r
494       goto again;\r
495     }\r
496   }\r
497   return port;\r
498 }\r
499 \r
500 /**\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
503  *\r
504  */\r
505 err_t\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
508 {\r
509   u32_t optdata;\r
510   err_t ret;\r
511   u32_t iss;\r
512 \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
516   } else {\r
517     return ERR_VAL;\r
518   }\r
519   pcb->remote_port = port;\r
520   if (pcb->local_port == 0) {\r
521     pcb->local_port = tcp_new_port();\r
522   }\r
523   iss = tcp_next_iss();\r
524   pcb->rcv_nxt = 0;\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
531   pcb->cwnd = 1;\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
538   \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
543       (pcb->mss & 255));\r
544 \r
545   ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);\r
546   if (ret == ERR_OK) { \r
547     tcp_output(pcb);\r
548   }\r
549   return ret;\r
550\r
551 \r
552 /**\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
556  */\r
557 void\r
558 tcp_slowtmr(void)\r
559 {\r
560   struct tcp_pcb *pcb, *pcb2, *prev;\r
561   u32_t eff_wnd;\r
562   u8_t pcb_remove;      /* flag if a PCB should be removed */\r
563   err_t err;\r
564 \r
565   err = ERR_OK;\r
566 \r
567   ++tcp_ticks;\r
568 \r
569   /* Steps through all of the active PCBs. */\r
570   prev = NULL;\r
571   pcb = tcp_active_pcbs;\r
572   if (pcb == NULL) {\r
573     LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));\r
574   }\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
580 \r
581     pcb_remove = 0;\r
582 \r
583     if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {\r
584       ++pcb_remove;\r
585       LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));\r
586     }\r
587     else if (pcb->nrtx == TCP_MAXRTX) {\r
588       ++pcb_remove;\r
589       LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));\r
590     } else {\r
591       ++pcb->rtime;\r
592       if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {\r
593 \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
597 \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
602         }\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
608         }\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
612  \r
613         /* The following needs to be called AFTER cwnd is set to one mss - STJ */\r
614         tcp_rexmit_rto(pcb);\r
615      }\r
616     }\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
621         ++pcb_remove;\r
622         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));\r
623       }\r
624     }\r
625 \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
632 \r
633          tcp_abort(pcb);\r
634       }\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
637          pcb->keep_cnt++;\r
638       }\r
639    }\r
640 \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
649       pcb->ooseq = NULL;\r
650       LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));\r
651     }\r
652 #endif /* TCP_QUEUE_OOSEQ */\r
653 \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
658         ++pcb_remove;\r
659         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));\r
660       }\r
661     }\r
662 \r
663 \r
664     /* If the PCB should be removed, do it. */\r
665     if (pcb_remove) {\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
671       } else {\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
675       }\r
676 \r
677       TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);\r
678 \r
679       pcb2 = pcb->next;\r
680       memp_free(MEMP_TCP_PCB, pcb);\r
681       pcb = pcb2;\r
682     } else {\r
683 \r
684       /* We check if we should poll the connection. */\r
685       ++pcb->polltmr;\r
686       if (pcb->polltmr >= pcb->pollinterval) {\r
687         pcb->polltmr = 0;\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
691           tcp_output(pcb);\r
692         }\r
693       }\r
694       \r
695       prev = pcb;\r
696       pcb = pcb->next;\r
697     }\r
698   }\r
699 \r
700   \r
701   /* Steps through all of the TIME-WAIT PCBs. */\r
702   prev = NULL;    \r
703   pcb = tcp_tw_pcbs;\r
704   while (pcb != NULL) {\r
705     LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);\r
706     pcb_remove = 0;\r
707 \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
710       ++pcb_remove;\r
711     }\r
712     \r
713 \r
714 \r
715     /* If the PCB should be removed, do it. */\r
716     if (pcb_remove) {\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
722       } else {\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
726       }\r
727       pcb2 = pcb->next;\r
728       memp_free(MEMP_TCP_PCB, pcb);\r
729       pcb = pcb2;\r
730     } else {\r
731       prev = pcb;\r
732       pcb = pcb->next;\r
733     }\r
734   }\r
735 }\r
736 \r
737 /**\r
738  * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.\r
739  */\r
740 void\r
741 tcp_fasttmr(void)\r
742 {\r
743   struct tcp_pcb *pcb;\r
744 \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
749       tcp_ack_now(pcb);\r
750       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);\r
751     }\r
752   }\r
753 }\r
754 \r
755 /**\r
756  * Deallocates a list of TCP segments (tcp_seg structures).\r
757  *\r
758  */\r
759 u8_t\r
760 tcp_segs_free(struct tcp_seg *seg)\r
761 {\r
762   u8_t count = 0;\r
763   struct tcp_seg *next;\r
764   while (seg != NULL) {\r
765     next = seg->next;\r
766     count += tcp_seg_free(seg);\r
767     seg = next;\r
768   }\r
769   return count;\r
770 }\r
771 \r
772 /**\r
773  * Frees a TCP segment.\r
774  *\r
775  */\r
776 u8_t\r
777 tcp_seg_free(struct tcp_seg *seg)\r
778 {\r
779   u8_t count = 0;\r
780   \r
781   if (seg != NULL) {\r
782     if (seg->p != NULL) {\r
783       count = pbuf_free(seg->p);\r
784 #if TCP_DEBUG\r
785       seg->p = NULL;\r
786 #endif /* TCP_DEBUG */\r
787     }\r
788     memp_free(MEMP_TCP_SEG, seg);\r
789   }\r
790   return count;\r
791 }\r
792 \r
793 /**\r
794  * Sets the priority of a connection.\r
795  *\r
796  */\r
797 void\r
798 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)\r
799 {\r
800   pcb->prio = prio;\r
801 }\r
802 #if TCP_QUEUE_OOSEQ\r
803 \r
804 /**\r
805  * Returns a copy of the given TCP segment.\r
806  *\r
807  */ \r
808 struct tcp_seg *\r
809 tcp_seg_copy(struct tcp_seg *seg)\r
810 {\r
811   struct tcp_seg *cseg;\r
812 \r
813   cseg = memp_malloc(MEMP_TCP_SEG);\r
814   if (cseg == NULL) {\r
815     return NULL;\r
816   }\r
817   memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg)); \r
818   pbuf_ref(cseg->p);\r
819   return cseg;\r
820 }\r
821 #endif\r
822 \r
823 #if LWIP_CALLBACK_API\r
824 static err_t\r
825 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)\r
826 {\r
827   arg = arg;\r
828   if (p != NULL) {\r
829     pbuf_free(p);\r
830   } else if (err == ERR_OK) {\r
831     return tcp_close(pcb);\r
832   }\r
833   return ERR_OK;\r
834 }\r
835 #endif /* LWIP_CALLBACK_API */\r
836 \r
837 static void\r
838 tcp_kill_prio(u8_t prio)\r
839 {\r
840   struct tcp_pcb *pcb, *inactive;\r
841   u32_t inactivity;\r
842   u8_t mprio;\r
843 \r
844 \r
845   mprio = TCP_PRIO_MAX;\r
846   \r
847   /* We kill the oldest active connection that has lower priority than\r
848      prio. */\r
849   inactivity = 0;\r
850   inactive = NULL;\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
856       inactive = pcb;\r
857       mprio = pcb->prio;\r
858     }\r
859   }\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
864   }      \r
865 }\r
866 \r
867 \r
868 static void\r
869 tcp_kill_timewait(void)\r
870 {\r
871   struct tcp_pcb *pcb, *inactive;\r
872   u32_t inactivity;\r
873 \r
874   inactivity = 0;\r
875   inactive = NULL;\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
879       inactive = pcb;\r
880     }\r
881   }\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
886   }      \r
887 }\r
888 \r
889 \r
890 \r
891 struct tcp_pcb *\r
892 tcp_alloc(u8_t prio)\r
893 {\r
894   struct tcp_pcb *pcb;\r
895   u32_t iss;\r
896   \r
897   pcb = memp_malloc(MEMP_TCP_PCB);\r
898   if (pcb == NULL) {\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
903     if (pcb == NULL) {\r
904       tcp_kill_prio(prio);    \r
905       pcb = memp_malloc(MEMP_TCP_PCB);\r
906     }\r
907   }\r
908   if (pcb != NULL) {\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
914     pcb->tos = 0;\r
915     pcb->ttl = TCP_TTL;\r
916     pcb->mss = TCP_MSS;\r
917     pcb->rto = 3000 / TCP_SLOW_INTERVAL;\r
918     pcb->sa = 0;\r
919     pcb->sv = 3000 / TCP_SLOW_INTERVAL;\r
920     pcb->rtime = 0;\r
921     pcb->cwnd = 1;\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
929 \r
930     pcb->polltmr = 0;\r
931 \r
932 #if LWIP_CALLBACK_API\r
933     pcb->recv = tcp_recv_null;\r
934 #endif /* LWIP_CALLBACK_API */  \r
935     \r
936     /* Init KEEPALIVE timer */\r
937     pcb->keepalive = TCP_KEEPDEFAULT;\r
938     pcb->keep_cnt = 0;\r
939   }\r
940   return pcb;\r
941 }\r
942 \r
943 /**\r
944  * Creates a new TCP protocol control block but doesn't place it on\r
945  * any of the TCP PCB lists.\r
946  *\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
950  */\r
951 \r
952 struct tcp_pcb *\r
953 tcp_new(void)\r
954 {\r
955   return tcp_alloc(TCP_PRIO_NORMAL);\r
956 }\r
957 \r
958 /*\r
959  * tcp_arg():\r
960  *\r
961  * Used to specify the argument that should be passed callback\r
962  * functions.\r
963  *\r
964  */ \r
965 \r
966 void\r
967 tcp_arg(struct tcp_pcb *pcb, void *arg)\r
968 {  \r
969   pcb->callback_arg = arg;\r
970 }\r
971 #if LWIP_CALLBACK_API\r
972 \r
973 /**\r
974  * Used to specify the function that should be called when a TCP\r
975  * connection receives data.\r
976  *\r
977  */ \r
978 void\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
981 {\r
982   pcb->recv = recv;\r
983 }\r
984 \r
985 /**\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
988  *\r
989  */ \r
990 \r
991 void\r
992 tcp_sent(struct tcp_pcb *pcb,\r
993    err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))\r
994 {\r
995   pcb->sent = sent;\r
996 }\r
997 \r
998 /**\r
999  * Used to specify the function that should be called when a fatal error\r
1000  * has occured on the connection.\r
1001  *\r
1002  */ \r
1003 void\r
1004 tcp_err(struct tcp_pcb *pcb,\r
1005    void (* errf)(void *arg, err_t err))\r
1006 {\r
1007   pcb->errf = errf;\r
1008 }\r
1009 \r
1010 /**\r
1011  * Used for specifying the function that should be called when a\r
1012  * LISTENing connection has been connected to another host.\r
1013  *\r
1014  */ \r
1015 void\r
1016 tcp_accept(struct tcp_pcb *pcb,\r
1017      err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))\r
1018 {\r
1019   ((struct tcp_pcb_listen *)pcb)->accept = accept;\r
1020 }\r
1021 #endif /* LWIP_CALLBACK_API */\r
1022 \r
1023 \r
1024 /**\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
1028  *\r
1029  */ \r
1030 void\r
1031 tcp_poll(struct tcp_pcb *pcb,\r
1032    err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)\r
1033 {\r
1034 #if LWIP_CALLBACK_API\r
1035   pcb->poll = poll;\r
1036 #endif /* LWIP_CALLBACK_API */  \r
1037   pcb->pollinterval = interval;\r
1038 }\r
1039 \r
1040 /**\r
1041  * Purges a TCP PCB. Removes any buffered data and frees the buffer memory.\r
1042  *\r
1043  */\r
1044 void\r
1045 tcp_pcb_purge(struct tcp_pcb *pcb)\r
1046 {\r
1047   if (pcb->state != CLOSED &&\r
1048      pcb->state != TIME_WAIT &&\r
1049      pcb->state != LISTEN) {\r
1050 \r
1051     LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));\r
1052     \r
1053     if (pcb->unsent != NULL) {    \r
1054       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));\r
1055     }\r
1056     if (pcb->unacked != NULL) {    \r
1057       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));\r
1058     }\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
1062     }\r
1063     \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
1070   }\r
1071 }\r
1072 \r
1073 /**\r
1074  * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.\r
1075  *\r
1076  */\r
1077 void\r
1078 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)\r
1079 {\r
1080   TCP_RMV(pcblist, pcb);\r
1081 \r
1082   tcp_pcb_purge(pcb);\r
1083   \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
1089     tcp_output(pcb);\r
1090   }  \r
1091   pcb->state = CLOSED;\r
1092 \r
1093   LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());\r
1094 }\r
1095 \r
1096 /**\r
1097  * Calculates a new initial sequence number for new connections.\r
1098  *\r
1099  */\r
1100 u32_t\r
1101 tcp_next_iss(void)\r
1102 {\r
1103   static u32_t iss = 6510;\r
1104   \r
1105   iss += tcp_ticks;       /* XXX */\r
1106   return iss;\r
1107 }\r
1108 \r
1109 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG\r
1110 void\r
1111 tcp_debug_print(struct tcp_hdr *tcphdr)\r
1112 {\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
1139 }\r
1140 \r
1141 void\r
1142 tcp_debug_print_state(enum tcp_state s)\r
1143 {\r
1144   LWIP_DEBUGF(TCP_DEBUG, ("State: "));\r
1145   switch (s) {\r
1146   case CLOSED:\r
1147     LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));\r
1148     break;\r
1149  case LISTEN:\r
1150    LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));\r
1151    break;\r
1152   case SYN_SENT:\r
1153     LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));\r
1154     break;\r
1155   case SYN_RCVD:\r
1156     LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));\r
1157     break;\r
1158   case ESTABLISHED:\r
1159     LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));\r
1160     break;\r
1161   case FIN_WAIT_1:\r
1162     LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));\r
1163     break;\r
1164   case FIN_WAIT_2:\r
1165     LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));\r
1166     break;\r
1167   case CLOSE_WAIT:\r
1168     LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));\r
1169     break;\r
1170   case CLOSING:\r
1171     LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));\r
1172     break;\r
1173   case LAST_ACK:\r
1174     LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));\r
1175     break;\r
1176   case TIME_WAIT:\r
1177     LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));\r
1178    break;\r
1179   }\r
1180 }\r
1181 \r
1182 void\r
1183 tcp_debug_print_flags(u8_t flags)\r
1184 {\r
1185   if (flags & TCP_FIN) {\r
1186     LWIP_DEBUGF(TCP_DEBUG, ("FIN "));\r
1187   }\r
1188   if (flags & TCP_SYN) {\r
1189     LWIP_DEBUGF(TCP_DEBUG, ("SYN "));\r
1190   }\r
1191   if (flags & TCP_RST) {\r
1192     LWIP_DEBUGF(TCP_DEBUG, ("RST "));\r
1193   }\r
1194   if (flags & TCP_PSH) {\r
1195     LWIP_DEBUGF(TCP_DEBUG, ("PSH "));\r
1196   }\r
1197   if (flags & TCP_ACK) {\r
1198     LWIP_DEBUGF(TCP_DEBUG, ("ACK "));\r
1199   }\r
1200   if (flags & TCP_URG) {\r
1201     LWIP_DEBUGF(TCP_DEBUG, ("URG "));\r
1202   }\r
1203   if (flags & TCP_ECE) {\r
1204     LWIP_DEBUGF(TCP_DEBUG, ("ECE "));\r
1205   }\r
1206   if (flags & TCP_CWR) {\r
1207     LWIP_DEBUGF(TCP_DEBUG, ("CWR "));\r
1208   }\r
1209 }\r
1210 \r
1211 void\r
1212 tcp_debug_print_pcbs(void)\r
1213 {\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
1221   }    \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
1228   }    \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
1235   }    \r
1236 }\r
1237 \r
1238 int\r
1239 tcp_pcbs_sane(void)\r
1240 {\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
1246   }\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
1249   }\r
1250   return 1;\r
1251 }\r
1252 #endif /* TCP_DEBUG */\r
1253 #endif /* LWIP_TCP */\r
1254 \r
1255 \r
1256 \r
1257 \r
1258 \r
1259 \r
1260 \r
1261 \r
1262 \r
1263 \r