]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ethernet/lwIP_130/src/core/tcp.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / ethernet / lwIP_130 / src / core / tcp.c
1 /**\r
2  * @file\r
3  * Transmission Control Protocol for IP\r
4  *\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
8  *\r
9  */\r
10 \r
11 /*\r
12  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
13  * All rights reserved.\r
14  *\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
17  *\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
25  *\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
35  * OF SUCH DAMAGE.\r
36  *\r
37  * This file is part of the lwIP TCP/IP stack.\r
38  *\r
39  * Author: Adam Dunkels <adam@sics.se>\r
40  *\r
41  */\r
42 \r
43 #include "lwip/opt.h"\r
44 \r
45 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */\r
46 \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
52 \r
53 #include <string.h>\r
54 \r
55 /* Incremented every coarse grained timer shot (typically every 500 ms). */\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  /* Times per slowtmr hits */\r
60 const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };\r
61 \r
62 /* The TCP PCB lists. */\r
63 \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
73 \r
74 struct tcp_pcb *tcp_tmp_pcb;\r
75 \r
76 static u8_t tcp_timer;\r
77 static u16_t tcp_new_port(void);\r
78 \r
79 /**\r
80  * Called periodically to dispatch TCP timers.\r
81  *\r
82  */\r
83 void\r
84 tcp_tmr(void)\r
85 {\r
86   /* Call tcp_fasttmr() every 250 ms */\r
87   tcp_fasttmr();\r
88 \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
92     tcp_slowtmr();\r
93   }\r
94 }\r
95 \r
96 /**\r
97  * Closes the connection held by the PCB.\r
98  *\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
105  *\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
109  */\r
110 err_t\r
111 tcp_close(struct tcp_pcb *pcb)\r
112 {\r
113   err_t err;\r
114 \r
115 #if TCP_DEBUG\r
116   LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in "));\r
117   tcp_debug_print_state(pcb->state);\r
118 #endif /* TCP_DEBUG */\r
119 \r
120   switch (pcb->state) {\r
121   case CLOSED:\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
129     err = ERR_OK;\r
130     TCP_RMV(&tcp_bound_pcbs, pcb);\r
131     memp_free(MEMP_TCP_PCB, pcb);\r
132     pcb = NULL;\r
133     break;\r
134   case LISTEN:\r
135     err = ERR_OK;\r
136     tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb);\r
137     memp_free(MEMP_TCP_PCB_LISTEN, pcb);\r
138     pcb = NULL;\r
139     break;\r
140   case SYN_SENT:\r
141     err = ERR_OK;\r
142     tcp_pcb_remove(&tcp_active_pcbs, pcb);\r
143     memp_free(MEMP_TCP_PCB, pcb);\r
144     pcb = NULL;\r
145     snmp_inc_tcpattemptfails();\r
146     break;\r
147   case SYN_RCVD:\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
152     }\r
153     break;\r
154   case ESTABLISHED:\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
159     }\r
160     break;\r
161   case CLOSE_WAIT:\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
166     }\r
167     break;\r
168   default:\r
169     /* Has already been closed, do nothing. */\r
170     err = ERR_OK;\r
171     pcb = NULL;\r
172     break;\r
173   }\r
174 \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
183     tcp_output(pcb);\r
184   }\r
185   return err;\r
186 }\r
187 \r
188 /**\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
192  *\r
193  * @param pcb the tcp_pcb to abort\r
194  */\r
195 void\r
196 tcp_abort(struct tcp_pcb *pcb)\r
197 {\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
204   void *errf_arg;\r
205 \r
206 \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
213   } else {\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
221     errf = pcb->errf;\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
227     }\r
228     if (pcb->unsent != NULL) {\r
229       tcp_segs_free(pcb->unsent);\r
230     }\r
231 #if TCP_QUEUE_OOSEQ\r
232     if (pcb->ooseq != NULL) {\r
233       tcp_segs_free(pcb->ooseq);\r
234     }\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
240   }\r
241 }\r
242 \r
243 /**\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
247  *\r
248  * @param pcb the tcp_pcb to bind (no check is done whether this pcb is\r
249  *        already bound!)\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
254  *         ERR_OK if bound\r
255  */\r
256 err_t\r
257 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)\r
258 {\r
259   struct tcp_pcb *cpcb;\r
260 \r
261   LWIP_ERROR("tcp_connect: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);\r
262 \r
263   if (port == 0) {\r
264     port = tcp_new_port();\r
265   }\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
274         return ERR_USE;\r
275       }\r
276     }\r
277   }\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
285         return ERR_USE;\r
286       }\r
287     }\r
288   }\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
295         return ERR_USE;\r
296       }\r
297     }\r
298   }\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
304         return ERR_USE;\r
305       }\r
306     }\r
307   }\r
308 \r
309   if (!ip_addr_isany(ipaddr)) {\r
310     pcb->local_ip = *ipaddr;\r
311   }\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
315   return ERR_OK;\r
316 }\r
317 #if LWIP_CALLBACK_API\r
318 /**\r
319  * Default accept callback if no accept callback is specified by the user.\r
320  */\r
321 static err_t\r
322 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)\r
323 {\r
324   LWIP_UNUSED_ARG(arg);\r
325   LWIP_UNUSED_ARG(pcb);\r
326   LWIP_UNUSED_ARG(err);\r
327 \r
328   return ERR_ABRT;\r
329 }\r
330 #endif /* LWIP_CALLBACK_API */\r
331 \r
332 /**\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
337  *\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
341  *\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
345  */\r
346 struct tcp_pcb *\r
347 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)\r
348 {\r
349   struct tcp_pcb_listen *lpcb;\r
350 \r
351   LWIP_UNUSED_ARG(backlog);\r
352   LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);\r
353 \r
354   /* already listening? */\r
355   if (pcb->state == LISTEN) {\r
356     return pcb;\r
357   }\r
358   lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN);\r
359   if (lpcb == NULL) {\r
360     return NULL;\r
361   }\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
381 }\r
382 \r
383 /**\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
387  *\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
390  */\r
391 void\r
392 tcp_recved(struct tcp_pcb *pcb, u16_t len)\r
393 {\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
397   } else {\r
398     pcb->rcv_wnd += len;\r
399     if (pcb->rcv_wnd >= pcb->mss) {\r
400       pcb->rcv_ann_wnd = pcb->rcv_wnd;\r
401     }\r
402   }\r
403 \r
404   if (!(pcb->flags & TF_ACK_DELAY) &&\r
405      !(pcb->flags & TF_ACK_NOW)) {\r
406     /*\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
415      */\r
416     tcp_ack(pcb);\r
417   }\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
425      * aggressive  */\r
426     tcp_ack_now(pcb);\r
427   }\r
428 \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
431 }\r
432 \r
433 /**\r
434  * A nastly hack featuring 'goto' statements that allocates a\r
435  * new TCP local port.\r
436  *\r
437  * @return a new (free) local TCP port number\r
438  */\r
439 static u16_t\r
440 tcp_new_port(void)\r
441 {\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
446 #endif\r
447   static u16_t port = TCP_LOCAL_PORT_RANGE_START;\r
448 \r
449  again:\r
450   if (++port > TCP_LOCAL_PORT_RANGE_END) {\r
451     port = TCP_LOCAL_PORT_RANGE_START;\r
452   }\r
453 \r
454   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {\r
455     if (pcb->local_port == port) {\r
456       goto again;\r
457     }\r
458   }\r
459   for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {\r
460     if (pcb->local_port == port) {\r
461       goto again;\r
462     }\r
463   }\r
464   for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {\r
465     if (pcb->local_port == port) {\r
466       goto again;\r
467     }\r
468   }\r
469   return port;\r
470 }\r
471 \r
472 /**\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
475  *\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
483  */\r
484 err_t\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
487 {\r
488   u32_t optdata;\r
489   err_t ret;\r
490   u32_t iss;\r
491 \r
492   LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);\r
493 \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
497   } else {\r
498     return ERR_VAL;\r
499   }\r
500   pcb->remote_port = port;\r
501   if (pcb->local_port == 0) {\r
502     pcb->local_port = tcp_new_port();\r
503   }\r
504   iss = tcp_next_iss();\r
505   pcb->rcv_nxt = 0;\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
517   pcb->cwnd = 1;\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
525 \r
526   snmp_inc_tcpactiveopens();\r
527 \r
528   /* Build an MSS option */\r
529   optdata = TCP_BUILD_MSS_OPTION();\r
530 \r
531   ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);\r
532   if (ret == ERR_OK) {\r
533     tcp_output(pcb);\r
534   }\r
535   return ret;\r
536 }\r
537 \r
538 /**\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
542  *\r
543  * Automatically called from tcp_tmr().\r
544  */\r
545 void\r
546 tcp_slowtmr(void)\r
547 {\r
548   struct tcp_pcb *pcb, *pcb2, *prev;\r
549   u16_t eff_wnd;\r
550   u8_t pcb_remove;      /* flag if a PCB should be removed */\r
551   err_t err;\r
552 \r
553   err = ERR_OK;\r
554 \r
555   ++tcp_ticks;\r
556 \r
557   /* Steps through all of the active PCBs. */\r
558   prev = NULL;\r
559   pcb = tcp_active_pcbs;\r
560   if (pcb == NULL) {\r
561     LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));\r
562   }\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
568 \r
569     pcb_remove = 0;\r
570 \r
571     if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {\r
572       ++pcb_remove;\r
573       LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));\r
574     }\r
575     else if (pcb->nrtx == TCP_MAXRTX) {\r
576       ++pcb_remove;\r
577       LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));\r
578     } else {\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
587           }\r
588           tcp_zero_window_probe(pcb);\r
589         }\r
590       } else {\r
591         /* Increase the retransmission timer if it is running */\r
592         if(pcb->rtime >= 0)\r
593           ++pcb->rtime;\r
594 \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
600 \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
605           }\r
606 \r
607           /* Reset the retransmission timer. */\r
608           pcb->rtime = 0;\r
609 \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
615           }\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
620 \r
621           /* The following needs to be called AFTER cwnd is set to one\r
622              mss - STJ */\r
623           tcp_rexmit_rto(pcb);\r
624         }\r
625       }\r
626     }\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
631         ++pcb_remove;\r
632         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));\r
633       }\r
634     }\r
635 \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
644 #else\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
648       {\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
652 \r
653         tcp_abort(pcb);\r
654       }\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
659 #else\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
664       {\r
665         tcp_keepalive(pcb);\r
666         pcb->keep_cnt_sent++;\r
667       }\r
668     }\r
669 \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
677       pcb->ooseq = NULL;\r
678       LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));\r
679     }\r
680 #endif /* TCP_QUEUE_OOSEQ */\r
681 \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
686         ++pcb_remove;\r
687         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));\r
688       }\r
689     }\r
690 \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
694         ++pcb_remove;\r
695         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));\r
696       }\r
697     }\r
698 \r
699     /* If the PCB should be removed, do it. */\r
700     if (pcb_remove) {\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
706       } else {\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
710       }\r
711 \r
712       TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);\r
713 \r
714       pcb2 = pcb->next;\r
715       memp_free(MEMP_TCP_PCB, pcb);\r
716       pcb = pcb2;\r
717     } else {\r
718 \r
719       /* We check if we should poll the connection. */\r
720       ++pcb->polltmr;\r
721       if (pcb->polltmr >= pcb->pollinterval) {\r
722         pcb->polltmr = 0;\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
726           tcp_output(pcb);\r
727         }\r
728       }\r
729 \r
730       prev = pcb;\r
731       pcb = pcb->next;\r
732     }\r
733   }\r
734 \r
735 \r
736   /* Steps through all of the TIME-WAIT PCBs. */\r
737   prev = NULL;\r
738   pcb = tcp_tw_pcbs;\r
739   while (pcb != NULL) {\r
740     LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);\r
741     pcb_remove = 0;\r
742 \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
745       ++pcb_remove;\r
746     }\r
747 \r
748 \r
749 \r
750     /* If the PCB should be removed, do it. */\r
751     if (pcb_remove) {\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
757       } else {\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
761       }\r
762       pcb2 = pcb->next;\r
763       memp_free(MEMP_TCP_PCB, pcb);\r
764       pcb = pcb2;\r
765     } else {\r
766       prev = pcb;\r
767       pcb = pcb->next;\r
768     }\r
769   }\r
770 }\r
771 \r
772 /**\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
775  *\r
776  * Automatically called from tcp_tmr().\r
777  */\r
778 void\r
779 tcp_fasttmr(void)\r
780 {\r
781   struct tcp_pcb *pcb;\r
782 \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
787       err_t err;\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
792       }\r
793     }\r
794 \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
798       tcp_ack_now(pcb);\r
799       pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);\r
800     }\r
801   }\r
802 }\r
803 \r
804 /**\r
805  * Deallocates a list of TCP segments (tcp_seg structures).\r
806  *\r
807  * @param seg tcp_seg list of TCP segments to free\r
808  * @return the number of pbufs that were deallocated\r
809  */\r
810 u8_t\r
811 tcp_segs_free(struct tcp_seg *seg)\r
812 {\r
813   u8_t count = 0;\r
814   struct tcp_seg *next;\r
815   while (seg != NULL) {\r
816     next = seg->next;\r
817     count += tcp_seg_free(seg);\r
818     seg = next;\r
819   }\r
820   return count;\r
821 }\r
822 \r
823 /**\r
824  * Frees a TCP segment (tcp_seg structure).\r
825  *\r
826  * @param seg single tcp_seg to free\r
827  * @return the number of pbufs that were deallocated\r
828  */\r
829 u8_t\r
830 tcp_seg_free(struct tcp_seg *seg)\r
831 {\r
832   u8_t count = 0;\r
833 \r
834   if (seg != NULL) {\r
835     if (seg->p != NULL) {\r
836       count = pbuf_free(seg->p);\r
837 #if TCP_DEBUG\r
838       seg->p = NULL;\r
839 #endif /* TCP_DEBUG */\r
840     }\r
841     memp_free(MEMP_TCP_SEG, seg);\r
842   }\r
843   return count;\r
844 }\r
845 \r
846 /**\r
847  * Sets the priority of a connection.\r
848  *\r
849  * @param pcb the tcp_pcb to manipulate\r
850  * @param prio new priority\r
851  */\r
852 void\r
853 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)\r
854 {\r
855   pcb->prio = prio;\r
856 }\r
857 #if TCP_QUEUE_OOSEQ\r
858 \r
859 /**\r
860  * Returns a copy of the given TCP segment.\r
861  * The pbuf and data are not copied, only the pointers\r
862  *\r
863  * @param seg the old tcp_seg\r
864  * @return a copy of seg\r
865  */\r
866 struct tcp_seg *\r
867 tcp_seg_copy(struct tcp_seg *seg)\r
868 {\r
869   struct tcp_seg *cseg;\r
870 \r
871   cseg = memp_malloc(MEMP_TCP_SEG);\r
872   if (cseg == NULL) {\r
873     return NULL;\r
874   }\r
875   SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));\r
876   pbuf_ref(cseg->p);\r
877   return cseg;\r
878 }\r
879 #endif\r
880 \r
881 #if LWIP_CALLBACK_API\r
882 /**\r
883  * Default receive callback that is called if the user didn't register\r
884  * a recv callback for the pcb.\r
885  */\r
886 static err_t\r
887 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)\r
888 {\r
889   arg = arg;\r
890   if (p != NULL) {\r
891     pbuf_free(p);\r
892   } else if (err == ERR_OK) {\r
893     return tcp_close(pcb);\r
894   }\r
895   return ERR_OK;\r
896 }\r
897 #endif /* LWIP_CALLBACK_API */\r
898 \r
899 /**\r
900  * Kills the oldest active connection that has lower priority than prio.\r
901  *\r
902  * @param prio minimum priority\r
903  */\r
904 static void\r
905 tcp_kill_prio(u8_t prio)\r
906 {\r
907   struct tcp_pcb *pcb, *inactive;\r
908   u32_t inactivity;\r
909   u8_t mprio;\r
910 \r
911 \r
912   mprio = TCP_PRIO_MAX;\r
913 \r
914   /* We kill the oldest active connection that has lower priority than prio. */\r
915   inactivity = 0;\r
916   inactive = NULL;\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
922       inactive = pcb;\r
923       mprio = pcb->prio;\r
924     }\r
925   }\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
930   }\r
931 }\r
932 \r
933 /**\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
936  */\r
937 static void\r
938 tcp_kill_timewait(void)\r
939 {\r
940   struct tcp_pcb *pcb, *inactive;\r
941   u32_t inactivity;\r
942 \r
943   inactivity = 0;\r
944   inactive = NULL;\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
949       inactive = pcb;\r
950     }\r
951   }\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
956   }\r
957 }\r
958 \r
959 /**\r
960  * Allocate a new tcp_pcb structure.\r
961  *\r
962  * @param prio priority for the new pcb\r
963  * @return a new tcp_pcb that initially is in state CLOSED\r
964  */\r
965 struct tcp_pcb *\r
966 tcp_alloc(u8_t prio)\r
967 {\r
968   struct tcp_pcb *pcb;\r
969   u32_t iss;\r
970 \r
971   pcb = memp_malloc(MEMP_TCP_PCB);\r
972   if (pcb == NULL) {\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
978     if (pcb == NULL) {\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
983     }\r
984   }\r
985   if (pcb != NULL) {\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
992     pcb->tos = 0;\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
997     pcb->sa = 0;\r
998     pcb->sv = 3000 / TCP_SLOW_INTERVAL;\r
999     pcb->rtime = -1;\r
1000     pcb->cwnd = 1;\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
1008 \r
1009     pcb->polltmr = 0;\r
1010 \r
1011 #if LWIP_CALLBACK_API\r
1012     pcb->recv = tcp_recv_null;\r
1013 #endif /* LWIP_CALLBACK_API */\r
1014 \r
1015     /* Init KEEPALIVE timer */\r
1016     pcb->keep_idle  = TCP_KEEPIDLE_DEFAULT;\r
1017 \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
1022 \r
1023     pcb->keep_cnt_sent = 0;\r
1024   }\r
1025   return pcb;\r
1026 }\r
1027 \r
1028 /**\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
1032  *\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
1037  *\r
1038  * @return a new tcp_pcb that initially is in state CLOSED\r
1039  */\r
1040 struct tcp_pcb *\r
1041 tcp_new(void)\r
1042 {\r
1043   return tcp_alloc(TCP_PRIO_NORMAL);\r
1044 }\r
1045 \r
1046 /**\r
1047  * Used to specify the argument that should be passed callback\r
1048  * functions.\r
1049  *\r
1050  * @param pcb tcp_pcb to set the callback argument\r
1051  * @param arg void pointer argument to pass to callback functions\r
1052  */\r
1053 void\r
1054 tcp_arg(struct tcp_pcb *pcb, void *arg)\r
1055 {\r
1056   pcb->callback_arg = arg;\r
1057 }\r
1058 #if LWIP_CALLBACK_API\r
1059 \r
1060 /**\r
1061  * Used to specify the function that should be called when a TCP\r
1062  * connection receives data.\r
1063  *\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
1066  */\r
1067 void\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
1070 {\r
1071   pcb->recv = recv;\r
1072 }\r
1073 \r
1074 /**\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
1077  *\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
1080  */\r
1081 void\r
1082 tcp_sent(struct tcp_pcb *pcb,\r
1083    err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))\r
1084 {\r
1085   pcb->sent = sent;\r
1086 }\r
1087 \r
1088 /**\r
1089  * Used to specify the function that should be called when a fatal error\r
1090  * has occured on the connection.\r
1091  *\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
1095  */\r
1096 void\r
1097 tcp_err(struct tcp_pcb *pcb,\r
1098    void (* errf)(void *arg, err_t err))\r
1099 {\r
1100   pcb->errf = errf;\r
1101 }\r
1102 \r
1103 /**\r
1104  * Used for specifying the function that should be called when a\r
1105  * LISTENing connection has been connected to another host.\r
1106  *\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
1110  */\r
1111 void\r
1112 tcp_accept(struct tcp_pcb *pcb,\r
1113      err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))\r
1114 {\r
1115   ((struct tcp_pcb_listen *)pcb)->accept = accept;\r
1116 }\r
1117 #endif /* LWIP_CALLBACK_API */\r
1118 \r
1119 \r
1120 /**\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
1124  *\r
1125  */\r
1126 void\r
1127 tcp_poll(struct tcp_pcb *pcb,\r
1128    err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)\r
1129 {\r
1130 #if LWIP_CALLBACK_API\r
1131   pcb->poll = poll;\r
1132 #endif /* LWIP_CALLBACK_API */\r
1133   pcb->pollinterval = interval;\r
1134 }\r
1135 \r
1136 /**\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
1139  *\r
1140  * @param pcb tcp_pcb to purge. The pcb itself is not deallocated!\r
1141  */\r
1142 void\r
1143 tcp_pcb_purge(struct tcp_pcb *pcb)\r
1144 {\r
1145   if (pcb->state != CLOSED &&\r
1146      pcb->state != TIME_WAIT &&\r
1147      pcb->state != LISTEN) {\r
1148 \r
1149     LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));\r
1150 \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
1155     }\r
1156     if (pcb->unsent != NULL) {\r
1157       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));\r
1158     }\r
1159     if (pcb->unacked != NULL) {\r
1160       LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));\r
1161     }\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
1165     }\r
1166 \r
1167     /* Stop the retransmission timer as it will expect data on unacked\r
1168        queue if it fires */\r
1169     pcb->rtime = -1;\r
1170 \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
1177   }\r
1178 }\r
1179 \r
1180 /**\r
1181  * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.\r
1182  *\r
1183  * @param pcblist PCB list to purge.\r
1184  * @param pcb tcp_pcb to purge. The pcb itself is also deallocated!\r
1185  */\r
1186 void\r
1187 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)\r
1188 {\r
1189   TCP_RMV(pcblist, pcb);\r
1190 \r
1191   tcp_pcb_purge(pcb);\r
1192 \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
1198     tcp_output(pcb);\r
1199   }\r
1200 \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
1207   }\r
1208 \r
1209   pcb->state = CLOSED;\r
1210 \r
1211   LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());\r
1212 }\r
1213 \r
1214 /**\r
1215  * Calculates a new initial sequence number for new connections.\r
1216  *\r
1217  * @return u32_t pseudo random sequence number\r
1218  */\r
1219 u32_t\r
1220 tcp_next_iss(void)\r
1221 {\r
1222   static u32_t iss = 6510;\r
1223 \r
1224   iss += tcp_ticks;       /* XXX */\r
1225   return iss;\r
1226 }\r
1227 \r
1228 #if TCP_CALCULATE_EFF_SEND_MSS\r
1229 /**\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
1233  */\r
1234 u16_t\r
1235 tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr)\r
1236 {\r
1237   u16_t mss_s;\r
1238   struct netif *outif;\r
1239 \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
1247   }\r
1248   return sendmss;\r
1249 }\r
1250 #endif /* TCP_CALCULATE_EFF_SEND_MSS */\r
1251 \r
1252 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG\r
1253 /**\r
1254  * Print a tcp header for debugging purposes.\r
1255  *\r
1256  * @param tcphdr pointer to a struct tcp_hdr\r
1257  */\r
1258 void\r
1259 tcp_debug_print(struct tcp_hdr *tcphdr)\r
1260 {\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
1287 }\r
1288 \r
1289 /**\r
1290  * Print a tcp state for debugging purposes.\r
1291  *\r
1292  * @param s enum tcp_state to print\r
1293  */\r
1294 void\r
1295 tcp_debug_print_state(enum tcp_state s)\r
1296 {\r
1297   LWIP_DEBUGF(TCP_DEBUG, ("State: "));\r
1298   switch (s) {\r
1299   case CLOSED:\r
1300     LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n"));\r
1301     break;\r
1302  case LISTEN:\r
1303    LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n"));\r
1304    break;\r
1305   case SYN_SENT:\r
1306     LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n"));\r
1307     break;\r
1308   case SYN_RCVD:\r
1309     LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n"));\r
1310     break;\r
1311   case ESTABLISHED:\r
1312     LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n"));\r
1313     break;\r
1314   case FIN_WAIT_1:\r
1315     LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n"));\r
1316     break;\r
1317   case FIN_WAIT_2:\r
1318     LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n"));\r
1319     break;\r
1320   case CLOSE_WAIT:\r
1321     LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n"));\r
1322     break;\r
1323   case CLOSING:\r
1324     LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n"));\r
1325     break;\r
1326   case LAST_ACK:\r
1327     LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n"));\r
1328     break;\r
1329   case TIME_WAIT:\r
1330     LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n"));\r
1331    break;\r
1332   }\r
1333 }\r
1334 \r
1335 /**\r
1336  * Print tcp flags for debugging purposes.\r
1337  *\r
1338  * @param flags tcp flags, all active flags are printed\r
1339  */\r
1340 void\r
1341 tcp_debug_print_flags(u8_t flags)\r
1342 {\r
1343   if (flags & TCP_FIN) {\r
1344     LWIP_DEBUGF(TCP_DEBUG, ("FIN "));\r
1345   }\r
1346   if (flags & TCP_SYN) {\r
1347     LWIP_DEBUGF(TCP_DEBUG, ("SYN "));\r
1348   }\r
1349   if (flags & TCP_RST) {\r
1350     LWIP_DEBUGF(TCP_DEBUG, ("RST "));\r
1351   }\r
1352   if (flags & TCP_PSH) {\r
1353     LWIP_DEBUGF(TCP_DEBUG, ("PSH "));\r
1354   }\r
1355   if (flags & TCP_ACK) {\r
1356     LWIP_DEBUGF(TCP_DEBUG, ("ACK "));\r
1357   }\r
1358   if (flags & TCP_URG) {\r
1359     LWIP_DEBUGF(TCP_DEBUG, ("URG "));\r
1360   }\r
1361   if (flags & TCP_ECE) {\r
1362     LWIP_DEBUGF(TCP_DEBUG, ("ECE "));\r
1363   }\r
1364   if (flags & TCP_CWR) {\r
1365     LWIP_DEBUGF(TCP_DEBUG, ("CWR "));\r
1366   }\r
1367 }\r
1368 \r
1369 /**\r
1370  * Print all tcp_pcbs in every list for debugging purposes.\r
1371  */\r
1372 void\r
1373 tcp_debug_print_pcbs(void)\r
1374 {\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
1382   }\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
1389   }\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
1396   }\r
1397 }\r
1398 \r
1399 /**\r
1400  * Check state consistency of the tcp_pcb lists.\r
1401  */\r
1402 s16_t\r
1403 tcp_pcbs_sane(void)\r
1404 {\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
1410   }\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
1413   }\r
1414   return 1;\r
1415 }\r
1416 #endif /* TCP_DEBUG */\r
1417 \r
1418 #endif /* LWIP_TCP */\r