]>
Commit | Line | Data |
---|---|---|
6e6d4a8b JP |
1 | /** |
2 | * @file | |
3 | * Transmission Control Protocol for IP | |
4 | * | |
5 | * This file contains common functions for the TCP implementation, such as functinos | |
6 | * for manipulating the data structures and the TCP timer functions. TCP functions | |
7 | * related to input and output is found in tcp_in.c and tcp_out.c respectively. | |
8 | * | |
9 | */ | |
10 | ||
11 | /* | |
12 | * Copyright (c) 2001-2004 Swedish Institute of Computer Science. | |
13 | * All rights reserved. | |
14 | * | |
15 | * Redistribution and use in source and binary forms, with or without modification, | |
16 | * are permitted provided that the following conditions are met: | |
17 | * | |
18 | * 1. Redistributions of source code must retain the above copyright notice, | |
19 | * this list of conditions and the following disclaimer. | |
20 | * 2. Redistributions in binary form must reproduce the above copyright notice, | |
21 | * this list of conditions and the following disclaimer in the documentation | |
22 | * and/or other materials provided with the distribution. | |
23 | * 3. The name of the author may not be used to endorse or promote products | |
24 | * derived from this software without specific prior written permission. | |
25 | * | |
26 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
27 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
28 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT | |
29 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
30 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
31 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
34 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY | |
35 | * OF SUCH DAMAGE. | |
36 | * | |
37 | * This file is part of the lwIP TCP/IP stack. | |
38 | * | |
39 | * Author: Adam Dunkels <adam@sics.se> | |
40 | * | |
41 | */ | |
42 | ||
43 | #include "lwip/opt.h" | |
44 | ||
45 | #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ | |
46 | ||
47 | #include "lwip/def.h" | |
48 | #include "lwip/mem.h" | |
49 | #include "lwip/memp.h" | |
50 | #include "lwip/snmp.h" | |
51 | #include "lwip/tcp.h" | |
52 | ||
53 | #include <string.h> | |
54 | ||
55 | /* Incremented every coarse grained timer shot (typically every 500 ms). */ | |
56 | u32_t tcp_ticks; | |
57 | const u8_t tcp_backoff[13] = | |
58 | { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; | |
59 | /* Times per slowtmr hits */ | |
60 | const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; | |
61 | ||
62 | /* The TCP PCB lists. */ | |
63 | ||
64 | /** List of all TCP PCBs bound but not yet (connected || listening) */ | |
65 | struct tcp_pcb *tcp_bound_pcbs; | |
66 | /** List of all TCP PCBs in LISTEN state */ | |
67 | union tcp_listen_pcbs_t tcp_listen_pcbs; | |
68 | /** List of all TCP PCBs that are in a state in which | |
69 | * they accept or send data. */ | |
70 | struct tcp_pcb *tcp_active_pcbs; | |
71 | /** List of all TCP PCBs in TIME-WAIT state */ | |
72 | struct tcp_pcb *tcp_tw_pcbs; | |
73 | ||
74 | struct tcp_pcb *tcp_tmp_pcb; | |
75 | ||
76 | static u8_t tcp_timer; | |
77 | static u16_t tcp_new_port(void); | |
78 | ||
79 | /** | |
80 | * Called periodically to dispatch TCP timers. | |
81 | * | |
82 | */ | |
83 | void | |
84 | tcp_tmr(void) | |
85 | { | |
86 | /* Call tcp_fasttmr() every 250 ms */ | |
87 | tcp_fasttmr(); | |
88 | ||
89 | if (++tcp_timer & 1) { | |
90 | /* Call tcp_tmr() every 500 ms, i.e., every other timer | |
91 | tcp_tmr() is called. */ | |
92 | tcp_slowtmr(); | |
93 | } | |
94 | } | |
95 | ||
96 | /** | |
97 | * Closes the connection held by the PCB. | |
98 | * | |
99 | * Listening pcbs are freed and may not be referenced any more. | |
100 | * Connection pcbs are freed if not yet connected and may not be referenced | |
101 | * any more. If a connection is established (at least SYN received or in | |
102 | * a closing state), the connection is closed, and put in a closing state. | |
103 | * The pcb is then automatically freed in tcp_slowtmr(). It is therefore | |
104 | * unsafe to reference it. | |
105 | * | |
106 | * @param pcb the tcp_pcb to close | |
107 | * @return ERR_OK if connection has been closed | |
108 | * another err_t if closing failed and pcb is not freed | |
109 | */ | |
110 | err_t | |
111 | tcp_close(struct tcp_pcb *pcb) | |
112 | { | |
113 | err_t err; | |
114 | ||
115 | #if TCP_DEBUG | |
116 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); | |
117 | tcp_debug_print_state(pcb->state); | |
118 | #endif /* TCP_DEBUG */ | |
119 | ||
120 | switch (pcb->state) { | |
121 | case CLOSED: | |
122 | /* Closing a pcb in the CLOSED state might seem erroneous, | |
123 | * however, it is in this state once allocated and as yet unused | |
124 | * and the user needs some way to free it should the need arise. | |
125 | * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) | |
126 | * or for a pcb that has been used and then entered the CLOSED state | |
127 | * is erroneous, but this should never happen as the pcb has in those cases | |
128 | * been freed, and so any remaining handles are bogus. */ | |
129 | err = ERR_OK; | |
130 | TCP_RMV(&tcp_bound_pcbs, pcb); | |
131 | memp_free(MEMP_TCP_PCB, pcb); | |
132 | pcb = NULL; | |
133 | break; | |
134 | case LISTEN: | |
135 | err = ERR_OK; | |
136 | tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb); | |
137 | memp_free(MEMP_TCP_PCB_LISTEN, pcb); | |
138 | pcb = NULL; | |
139 | break; | |
140 | case SYN_SENT: | |
141 | err = ERR_OK; | |
142 | tcp_pcb_remove(&tcp_active_pcbs, pcb); | |
143 | memp_free(MEMP_TCP_PCB, pcb); | |
144 | pcb = NULL; | |
145 | snmp_inc_tcpattemptfails(); | |
146 | break; | |
147 | case SYN_RCVD: | |
148 | err = tcp_send_ctrl(pcb, TCP_FIN); | |
149 | if (err == ERR_OK) { | |
150 | snmp_inc_tcpattemptfails(); | |
151 | pcb->state = FIN_WAIT_1; | |
152 | } | |
153 | break; | |
154 | case ESTABLISHED: | |
155 | err = tcp_send_ctrl(pcb, TCP_FIN); | |
156 | if (err == ERR_OK) { | |
157 | snmp_inc_tcpestabresets(); | |
158 | pcb->state = FIN_WAIT_1; | |
159 | } | |
160 | break; | |
161 | case CLOSE_WAIT: | |
162 | err = tcp_send_ctrl(pcb, TCP_FIN); | |
163 | if (err == ERR_OK) { | |
164 | snmp_inc_tcpestabresets(); | |
165 | pcb->state = LAST_ACK; | |
166 | } | |
167 | break; | |
168 | default: | |
169 | /* Has already been closed, do nothing. */ | |
170 | err = ERR_OK; | |
171 | pcb = NULL; | |
172 | break; | |
173 | } | |
174 | ||
175 | if (pcb != NULL && err == ERR_OK) { | |
176 | /* To ensure all data has been sent when tcp_close returns, we have | |
177 | to make sure tcp_output doesn't fail. | |
178 | Since we don't really have to ensure all data has been sent when tcp_close | |
179 | returns (unsent data is sent from tcp timer functions, also), we don't care | |
180 | for the return value of tcp_output for now. */ | |
181 | /* @todo: When implementing SO_LINGER, this must be changed somehow: | |
182 | If SOF_LINGER is set, the data should be sent when tcp_close returns. */ | |
183 | tcp_output(pcb); | |
184 | } | |
185 | return err; | |
186 | } | |
187 | ||
188 | /** | |
189 | * Aborts a connection by sending a RST to the remote host and deletes | |
190 | * the local protocol control block. This is done when a connection is | |
191 | * killed because of shortage of memory. | |
192 | * | |
193 | * @param pcb the tcp_pcb to abort | |
194 | */ | |
195 | void | |
196 | tcp_abort(struct tcp_pcb *pcb) | |
197 | { | |
198 | u32_t seqno, ackno; | |
199 | u16_t remote_port, local_port; | |
200 | struct ip_addr remote_ip, local_ip; | |
201 | #if LWIP_CALLBACK_API | |
202 | void (* errf)(void *arg, err_t err); | |
203 | #endif /* LWIP_CALLBACK_API */ | |
204 | void *errf_arg; | |
205 | ||
206 | ||
207 | /* Figure out on which TCP PCB list we are, and remove us. If we | |
208 | are in an active state, call the receive function associated with | |
209 | the PCB with a NULL argument, and send an RST to the remote end. */ | |
210 | if (pcb->state == TIME_WAIT) { | |
211 | tcp_pcb_remove(&tcp_tw_pcbs, pcb); | |
212 | memp_free(MEMP_TCP_PCB, pcb); | |
213 | } else { | |
214 | seqno = pcb->snd_nxt; | |
215 | ackno = pcb->rcv_nxt; | |
216 | ip_addr_set(&local_ip, &(pcb->local_ip)); | |
217 | ip_addr_set(&remote_ip, &(pcb->remote_ip)); | |
218 | local_port = pcb->local_port; | |
219 | remote_port = pcb->remote_port; | |
220 | #if LWIP_CALLBACK_API | |
221 | errf = pcb->errf; | |
222 | #endif /* LWIP_CALLBACK_API */ | |
223 | errf_arg = pcb->callback_arg; | |
224 | tcp_pcb_remove(&tcp_active_pcbs, pcb); | |
225 | if (pcb->unacked != NULL) { | |
226 | tcp_segs_free(pcb->unacked); | |
227 | } | |
228 | if (pcb->unsent != NULL) { | |
229 | tcp_segs_free(pcb->unsent); | |
230 | } | |
231 | #if TCP_QUEUE_OOSEQ | |
232 | if (pcb->ooseq != NULL) { | |
233 | tcp_segs_free(pcb->ooseq); | |
234 | } | |
235 | #endif /* TCP_QUEUE_OOSEQ */ | |
236 | memp_free(MEMP_TCP_PCB, pcb); | |
237 | TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); | |
238 | LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abort: sending RST\n")); | |
239 | tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); | |
240 | } | |
241 | } | |
242 | ||
243 | /** | |
244 | * Binds the connection to a local portnumber and IP address. If the | |
245 | * IP address is not given (i.e., ipaddr == NULL), the IP address of | |
246 | * the outgoing network interface is used instead. | |
247 | * | |
248 | * @param pcb the tcp_pcb to bind (no check is done whether this pcb is | |
249 | * already bound!) | |
250 | * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind | |
251 | * to any local address | |
252 | * @param port the local port to bind to | |
253 | * @return ERR_USE if the port is already in use | |
254 | * ERR_OK if bound | |
255 | */ | |
256 | err_t | |
257 | tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) | |
258 | { | |
259 | struct tcp_pcb *cpcb; | |
260 | ||
261 | LWIP_ERROR("tcp_connect: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); | |
262 | ||
263 | if (port == 0) { | |
264 | port = tcp_new_port(); | |
265 | } | |
266 | /* Check if the address already is in use. */ | |
267 | /* Check the listen pcbs. */ | |
268 | for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; | |
269 | cpcb != NULL; cpcb = cpcb->next) { | |
270 | if (cpcb->local_port == port) { | |
271 | if (ip_addr_isany(&(cpcb->local_ip)) || | |
272 | ip_addr_isany(ipaddr) || | |
273 | ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { | |
274 | return ERR_USE; | |
275 | } | |
276 | } | |
277 | } | |
278 | /* Check the connected pcbs. */ | |
279 | for(cpcb = tcp_active_pcbs; | |
280 | cpcb != NULL; cpcb = cpcb->next) { | |
281 | if (cpcb->local_port == port) { | |
282 | if (ip_addr_isany(&(cpcb->local_ip)) || | |
283 | ip_addr_isany(ipaddr) || | |
284 | ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { | |
285 | return ERR_USE; | |
286 | } | |
287 | } | |
288 | } | |
289 | /* Check the bound, not yet connected pcbs. */ | |
290 | for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) { | |
291 | if (cpcb->local_port == port) { | |
292 | if (ip_addr_isany(&(cpcb->local_ip)) || | |
293 | ip_addr_isany(ipaddr) || | |
294 | ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { | |
295 | return ERR_USE; | |
296 | } | |
297 | } | |
298 | } | |
299 | /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah), | |
300 | * we have to check the pcbs in TIME-WAIT state, also: */ | |
301 | for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) { | |
302 | if (cpcb->local_port == port) { | |
303 | if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { | |
304 | return ERR_USE; | |
305 | } | |
306 | } | |
307 | } | |
308 | ||
309 | if (!ip_addr_isany(ipaddr)) { | |
310 | pcb->local_ip = *ipaddr; | |
311 | } | |
312 | pcb->local_port = port; | |
313 | TCP_REG(&tcp_bound_pcbs, pcb); | |
314 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); | |
315 | return ERR_OK; | |
316 | } | |
317 | #if LWIP_CALLBACK_API | |
318 | /** | |
319 | * Default accept callback if no accept callback is specified by the user. | |
320 | */ | |
321 | static err_t | |
322 | tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) | |
323 | { | |
324 | LWIP_UNUSED_ARG(arg); | |
325 | LWIP_UNUSED_ARG(pcb); | |
326 | LWIP_UNUSED_ARG(err); | |
327 | ||
328 | return ERR_ABRT; | |
329 | } | |
330 | #endif /* LWIP_CALLBACK_API */ | |
331 | ||
332 | /** | |
333 | * Set the state of the connection to be LISTEN, which means that it | |
334 | * is able to accept incoming connections. The protocol control block | |
335 | * is reallocated in order to consume less memory. Setting the | |
336 | * connection to LISTEN is an irreversible process. | |
337 | * | |
338 | * @param pcb the original tcp_pcb | |
339 | * @param backlog the incoming connections queue limit | |
340 | * @return tcp_pcb used for listening, consumes less memory. | |
341 | * | |
342 | * @note The original tcp_pcb is freed. This function therefore has to be | |
343 | * called like this: | |
344 | * tpcb = tcp_listen(tpcb); | |
345 | */ | |
346 | struct tcp_pcb * | |
347 | tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) | |
348 | { | |
349 | struct tcp_pcb_listen *lpcb; | |
350 | ||
351 | LWIP_UNUSED_ARG(backlog); | |
352 | LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); | |
353 | ||
354 | /* already listening? */ | |
355 | if (pcb->state == LISTEN) { | |
356 | return pcb; | |
357 | } | |
358 | lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN); | |
359 | if (lpcb == NULL) { | |
360 | return NULL; | |
361 | } | |
362 | lpcb->callback_arg = pcb->callback_arg; | |
363 | lpcb->local_port = pcb->local_port; | |
364 | lpcb->state = LISTEN; | |
365 | lpcb->so_options = pcb->so_options; | |
366 | lpcb->so_options |= SOF_ACCEPTCONN; | |
367 | lpcb->ttl = pcb->ttl; | |
368 | lpcb->tos = pcb->tos; | |
369 | ip_addr_set(&lpcb->local_ip, &pcb->local_ip); | |
370 | TCP_RMV(&tcp_bound_pcbs, pcb); | |
371 | memp_free(MEMP_TCP_PCB, pcb); | |
372 | #if LWIP_CALLBACK_API | |
373 | lpcb->accept = tcp_accept_null; | |
374 | #endif /* LWIP_CALLBACK_API */ | |
375 | #if TCP_LISTEN_BACKLOG | |
376 | lpcb->accepts_pending = 0; | |
377 | lpcb->backlog = (backlog ? backlog : 1); | |
378 | #endif /* TCP_LISTEN_BACKLOG */ | |
379 | TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb); | |
380 | return (struct tcp_pcb *)lpcb; | |
381 | } | |
382 | ||
383 | /** | |
384 | * This function should be called by the application when it has | |
385 | * processed the data. The purpose is to advertise a larger window | |
386 | * when the data has been processed. | |
387 | * | |
388 | * @param pcb the tcp_pcb for which data is read | |
389 | * @param len the amount of bytes that have been read by the application | |
390 | */ | |
391 | void | |
392 | tcp_recved(struct tcp_pcb *pcb, u16_t len) | |
393 | { | |
394 | if ((u32_t)pcb->rcv_wnd + len > TCP_WND) { | |
395 | pcb->rcv_wnd = TCP_WND; | |
396 | pcb->rcv_ann_wnd = TCP_WND; | |
397 | } else { | |
398 | pcb->rcv_wnd += len; | |
399 | if (pcb->rcv_wnd >= pcb->mss) { | |
400 | pcb->rcv_ann_wnd = pcb->rcv_wnd; | |
401 | } | |
402 | } | |
403 | ||
404 | if (!(pcb->flags & TF_ACK_DELAY) && | |
405 | !(pcb->flags & TF_ACK_NOW)) { | |
406 | /* | |
407 | * We send an ACK here (if one is not already pending, hence | |
408 | * the above tests) as tcp_recved() implies that the application | |
409 | * has processed some data, and so we can open the receiver's | |
410 | * window to allow more to be transmitted. This could result in | |
411 | * two ACKs being sent for each received packet in some limited cases | |
412 | * (where the application is only receiving data, and is slow to | |
413 | * process it) but it is necessary to guarantee that the sender can | |
414 | * continue to transmit. | |
415 | */ | |
416 | tcp_ack(pcb); | |
417 | } | |
418 | else if (pcb->flags & TF_ACK_DELAY && pcb->rcv_wnd >= TCP_WND/2) { | |
419 | /* If we can send a window update such that there is a full | |
420 | * segment available in the window, do so now. This is sort of | |
421 | * nagle-like in its goals, and tries to hit a compromise between | |
422 | * sending acks each time the window is updated, and only sending | |
423 | * window updates when a timer expires. The "threshold" used | |
424 | * above (currently TCP_WND/2) can be tuned to be more or less | |
425 | * aggressive */ | |
426 | tcp_ack_now(pcb); | |
427 | } | |
428 | ||
429 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", | |
430 | len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); | |
431 | } | |
432 | ||
433 | /** | |
434 | * A nastly hack featuring 'goto' statements that allocates a | |
435 | * new TCP local port. | |
436 | * | |
437 | * @return a new (free) local TCP port number | |
438 | */ | |
439 | static u16_t | |
440 | tcp_new_port(void) | |
441 | { | |
442 | struct tcp_pcb *pcb; | |
443 | #ifndef TCP_LOCAL_PORT_RANGE_START | |
444 | #define TCP_LOCAL_PORT_RANGE_START 4096 | |
445 | #define TCP_LOCAL_PORT_RANGE_END 0x7fff | |
446 | #endif | |
447 | static u16_t port = TCP_LOCAL_PORT_RANGE_START; | |
448 | ||
449 | again: | |
450 | if (++port > TCP_LOCAL_PORT_RANGE_END) { | |
451 | port = TCP_LOCAL_PORT_RANGE_START; | |
452 | } | |
453 | ||
454 | for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { | |
455 | if (pcb->local_port == port) { | |
456 | goto again; | |
457 | } | |
458 | } | |
459 | for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { | |
460 | if (pcb->local_port == port) { | |
461 | goto again; | |
462 | } | |
463 | } | |
464 | for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { | |
465 | if (pcb->local_port == port) { | |
466 | goto again; | |
467 | } | |
468 | } | |
469 | return port; | |
470 | } | |
471 | ||
472 | /** | |
473 | * Connects to another host. The function given as the "connected" | |
474 | * argument will be called when the connection has been established. | |
475 | * | |
476 | * @param pcb the tcp_pcb used to establish the connection | |
477 | * @param ipaddr the remote ip address to connect to | |
478 | * @param port the remote tcp port to connect to | |
479 | * @param connected callback function to call when connected (or on error) | |
480 | * @return ERR_VAL if invalid arguments are given | |
481 | * ERR_OK if connect request has been sent | |
482 | * other err_t values if connect request couldn't be sent | |
483 | */ | |
484 | err_t | |
485 | tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, | |
486 | err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) | |
487 | { | |
488 | u32_t optdata; | |
489 | err_t ret; | |
490 | u32_t iss; | |
491 | ||
492 | LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); | |
493 | ||
494 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); | |
495 | if (ipaddr != NULL) { | |
496 | pcb->remote_ip = *ipaddr; | |
497 | } else { | |
498 | return ERR_VAL; | |
499 | } | |
500 | pcb->remote_port = port; | |
501 | if (pcb->local_port == 0) { | |
502 | pcb->local_port = tcp_new_port(); | |
503 | } | |
504 | iss = tcp_next_iss(); | |
505 | pcb->rcv_nxt = 0; | |
506 | pcb->snd_nxt = iss; | |
507 | pcb->lastack = iss - 1; | |
508 | pcb->snd_lbb = iss - 1; | |
509 | pcb->rcv_wnd = TCP_WND; | |
510 | pcb->rcv_ann_wnd = TCP_WND; | |
511 | pcb->snd_wnd = TCP_WND; | |
512 | /* The send MSS is updated when an MSS option is received. */ | |
513 | pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; | |
514 | #if TCP_CALCULATE_EFF_SEND_MSS | |
515 | pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); | |
516 | #endif /* TCP_CALCULATE_EFF_SEND_MSS */ | |
517 | pcb->cwnd = 1; | |
518 | pcb->ssthresh = pcb->mss * 10; | |
519 | pcb->state = SYN_SENT; | |
520 | #if LWIP_CALLBACK_API | |
521 | pcb->connected = connected; | |
522 | #endif /* LWIP_CALLBACK_API */ | |
523 | TCP_RMV(&tcp_bound_pcbs, pcb); | |
524 | TCP_REG(&tcp_active_pcbs, pcb); | |
525 | ||
526 | snmp_inc_tcpactiveopens(); | |
527 | ||
528 | /* Build an MSS option */ | |
529 | optdata = TCP_BUILD_MSS_OPTION(); | |
530 | ||
531 | ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4); | |
532 | if (ret == ERR_OK) { | |
533 | tcp_output(pcb); | |
534 | } | |
535 | return ret; | |
536 | } | |
537 | ||
538 | /** | |
539 | * Called every 500 ms and implements the retransmission timer and the timer that | |
540 | * removes PCBs that have been in TIME-WAIT for enough time. It also increments | |
541 | * various timers such as the inactivity timer in each PCB. | |
542 | * | |
543 | * Automatically called from tcp_tmr(). | |
544 | */ | |
545 | void | |
546 | tcp_slowtmr(void) | |
547 | { | |
548 | struct tcp_pcb *pcb, *pcb2, *prev; | |
549 | u16_t eff_wnd; | |
550 | u8_t pcb_remove; /* flag if a PCB should be removed */ | |
551 | err_t err; | |
552 | ||
553 | err = ERR_OK; | |
554 | ||
555 | ++tcp_ticks; | |
556 | ||
557 | /* Steps through all of the active PCBs. */ | |
558 | prev = NULL; | |
559 | pcb = tcp_active_pcbs; | |
560 | if (pcb == NULL) { | |
561 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); | |
562 | } | |
563 | while (pcb != NULL) { | |
564 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); | |
565 | LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); | |
566 | LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); | |
567 | LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); | |
568 | ||
569 | pcb_remove = 0; | |
570 | ||
571 | if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { | |
572 | ++pcb_remove; | |
573 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); | |
574 | } | |
575 | else if (pcb->nrtx == TCP_MAXRTX) { | |
576 | ++pcb_remove; | |
577 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); | |
578 | } else { | |
579 | if (pcb->persist_backoff > 0) { | |
580 | /* If snd_wnd is zero, use persist timer to send 1 byte probes | |
581 | * instead of using the standard retransmission mechanism. */ | |
582 | pcb->persist_cnt++; | |
583 | if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { | |
584 | pcb->persist_cnt = 0; | |
585 | if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { | |
586 | pcb->persist_backoff++; | |
587 | } | |
588 | tcp_zero_window_probe(pcb); | |
589 | } | |
590 | } else { | |
591 | /* Increase the retransmission timer if it is running */ | |
592 | if(pcb->rtime >= 0) | |
593 | ++pcb->rtime; | |
594 | ||
595 | if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { | |
596 | /* Time for a retransmission. */ | |
597 | LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F | |
598 | " pcb->rto %"S16_F"\n", | |
599 | pcb->rtime, pcb->rto)); | |
600 | ||
601 | /* Double retransmission time-out unless we are trying to | |
602 | * connect to somebody (i.e., we are in SYN_SENT). */ | |
603 | if (pcb->state != SYN_SENT) { | |
604 | pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; | |
605 | } | |
606 | ||
607 | /* Reset the retransmission timer. */ | |
608 | pcb->rtime = 0; | |
609 | ||
610 | /* Reduce congestion window and ssthresh. */ | |
611 | eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); | |
612 | pcb->ssthresh = eff_wnd >> 1; | |
613 | if (pcb->ssthresh < pcb->mss) { | |
614 | pcb->ssthresh = pcb->mss * 2; | |
615 | } | |
616 | pcb->cwnd = pcb->mss; | |
617 | LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F | |
618 | " ssthresh %"U16_F"\n", | |
619 | pcb->cwnd, pcb->ssthresh)); | |
620 | ||
621 | /* The following needs to be called AFTER cwnd is set to one | |
622 | mss - STJ */ | |
623 | tcp_rexmit_rto(pcb); | |
624 | } | |
625 | } | |
626 | } | |
627 | /* Check if this PCB has stayed too long in FIN-WAIT-2 */ | |
628 | if (pcb->state == FIN_WAIT_2) { | |
629 | if ((u32_t)(tcp_ticks - pcb->tmr) > | |
630 | TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { | |
631 | ++pcb_remove; | |
632 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); | |
633 | } | |
634 | } | |
635 | ||
636 | /* Check if KEEPALIVE should be sent */ | |
637 | if((pcb->so_options & SOF_KEEPALIVE) && | |
638 | ((pcb->state == ESTABLISHED) || | |
639 | (pcb->state == CLOSE_WAIT))) { | |
640 | #if LWIP_TCP_KEEPALIVE | |
641 | if((u32_t)(tcp_ticks - pcb->tmr) > | |
642 | (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl)) | |
643 | / TCP_SLOW_INTERVAL) | |
644 | #else | |
645 | if((u32_t)(tcp_ticks - pcb->tmr) > | |
646 | (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) | |
647 | #endif /* LWIP_TCP_KEEPALIVE */ | |
648 | { | |
649 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", | |
650 | ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), | |
651 | ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); | |
652 | ||
653 | tcp_abort(pcb); | |
654 | } | |
655 | #if LWIP_TCP_KEEPALIVE | |
656 | else if((u32_t)(tcp_ticks - pcb->tmr) > | |
657 | (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl) | |
658 | / TCP_SLOW_INTERVAL) | |
659 | #else | |
660 | else if((u32_t)(tcp_ticks - pcb->tmr) > | |
661 | (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT) | |
662 | / TCP_SLOW_INTERVAL) | |
663 | #endif /* LWIP_TCP_KEEPALIVE */ | |
664 | { | |
665 | tcp_keepalive(pcb); | |
666 | pcb->keep_cnt_sent++; | |
667 | } | |
668 | } | |
669 | ||
670 | /* If this PCB has queued out of sequence data, but has been | |
671 | inactive for too long, will drop the data (it will eventually | |
672 | be retransmitted). */ | |
673 | #if TCP_QUEUE_OOSEQ | |
674 | if (pcb->ooseq != NULL && | |
675 | (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { | |
676 | tcp_segs_free(pcb->ooseq); | |
677 | pcb->ooseq = NULL; | |
678 | LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); | |
679 | } | |
680 | #endif /* TCP_QUEUE_OOSEQ */ | |
681 | ||
682 | /* Check if this PCB has stayed too long in SYN-RCVD */ | |
683 | if (pcb->state == SYN_RCVD) { | |
684 | if ((u32_t)(tcp_ticks - pcb->tmr) > | |
685 | TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { | |
686 | ++pcb_remove; | |
687 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); | |
688 | } | |
689 | } | |
690 | ||
691 | /* Check if this PCB has stayed too long in LAST-ACK */ | |
692 | if (pcb->state == LAST_ACK) { | |
693 | if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { | |
694 | ++pcb_remove; | |
695 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); | |
696 | } | |
697 | } | |
698 | ||
699 | /* If the PCB should be removed, do it. */ | |
700 | if (pcb_remove) { | |
701 | tcp_pcb_purge(pcb); | |
702 | /* Remove PCB from tcp_active_pcbs list. */ | |
703 | if (prev != NULL) { | |
704 | LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); | |
705 | prev->next = pcb->next; | |
706 | } else { | |
707 | /* This PCB was the first. */ | |
708 | LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); | |
709 | tcp_active_pcbs = pcb->next; | |
710 | } | |
711 | ||
712 | TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT); | |
713 | ||
714 | pcb2 = pcb->next; | |
715 | memp_free(MEMP_TCP_PCB, pcb); | |
716 | pcb = pcb2; | |
717 | } else { | |
718 | ||
719 | /* We check if we should poll the connection. */ | |
720 | ++pcb->polltmr; | |
721 | if (pcb->polltmr >= pcb->pollinterval) { | |
722 | pcb->polltmr = 0; | |
723 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); | |
724 | TCP_EVENT_POLL(pcb, err); | |
725 | if (err == ERR_OK) { | |
726 | tcp_output(pcb); | |
727 | } | |
728 | } | |
729 | ||
730 | prev = pcb; | |
731 | pcb = pcb->next; | |
732 | } | |
733 | } | |
734 | ||
735 | ||
736 | /* Steps through all of the TIME-WAIT PCBs. */ | |
737 | prev = NULL; | |
738 | pcb = tcp_tw_pcbs; | |
739 | while (pcb != NULL) { | |
740 | LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); | |
741 | pcb_remove = 0; | |
742 | ||
743 | /* Check if this PCB has stayed long enough in TIME-WAIT */ | |
744 | if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { | |
745 | ++pcb_remove; | |
746 | } | |
747 | ||
748 | ||
749 | ||
750 | /* If the PCB should be removed, do it. */ | |
751 | if (pcb_remove) { | |
752 | tcp_pcb_purge(pcb); | |
753 | /* Remove PCB from tcp_tw_pcbs list. */ | |
754 | if (prev != NULL) { | |
755 | LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); | |
756 | prev->next = pcb->next; | |
757 | } else { | |
758 | /* This PCB was the first. */ | |
759 | LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); | |
760 | tcp_tw_pcbs = pcb->next; | |
761 | } | |
762 | pcb2 = pcb->next; | |
763 | memp_free(MEMP_TCP_PCB, pcb); | |
764 | pcb = pcb2; | |
765 | } else { | |
766 | prev = pcb; | |
767 | pcb = pcb->next; | |
768 | } | |
769 | } | |
770 | } | |
771 | ||
772 | /** | |
773 | * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously | |
774 | * "refused" by upper layer (application) and sends delayed ACKs. | |
775 | * | |
776 | * Automatically called from tcp_tmr(). | |
777 | */ | |
778 | void | |
779 | tcp_fasttmr(void) | |
780 | { | |
781 | struct tcp_pcb *pcb; | |
782 | ||
783 | for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { | |
784 | /* If there is data which was previously "refused" by upper layer */ | |
785 | if (pcb->refused_data != NULL) { | |
786 | /* Notify again application with data previously received. */ | |
787 | err_t err; | |
788 | LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n")); | |
789 | TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); | |
790 | if (err == ERR_OK) { | |
791 | pcb->refused_data = NULL; | |
792 | } | |
793 | } | |
794 | ||
795 | /* send delayed ACKs */ | |
796 | if (pcb->flags & TF_ACK_DELAY) { | |
797 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); | |
798 | tcp_ack_now(pcb); | |
799 | pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); | |
800 | } | |
801 | } | |
802 | } | |
803 | ||
804 | /** | |
805 | * Deallocates a list of TCP segments (tcp_seg structures). | |
806 | * | |
807 | * @param seg tcp_seg list of TCP segments to free | |
808 | * @return the number of pbufs that were deallocated | |
809 | */ | |
810 | u8_t | |
811 | tcp_segs_free(struct tcp_seg *seg) | |
812 | { | |
813 | u8_t count = 0; | |
814 | struct tcp_seg *next; | |
815 | while (seg != NULL) { | |
816 | next = seg->next; | |
817 | count += tcp_seg_free(seg); | |
818 | seg = next; | |
819 | } | |
820 | return count; | |
821 | } | |
822 | ||
823 | /** | |
824 | * Frees a TCP segment (tcp_seg structure). | |
825 | * | |
826 | * @param seg single tcp_seg to free | |
827 | * @return the number of pbufs that were deallocated | |
828 | */ | |
829 | u8_t | |
830 | tcp_seg_free(struct tcp_seg *seg) | |
831 | { | |
832 | u8_t count = 0; | |
833 | ||
834 | if (seg != NULL) { | |
835 | if (seg->p != NULL) { | |
836 | count = pbuf_free(seg->p); | |
837 | #if TCP_DEBUG | |
838 | seg->p = NULL; | |
839 | #endif /* TCP_DEBUG */ | |
840 | } | |
841 | memp_free(MEMP_TCP_SEG, seg); | |
842 | } | |
843 | return count; | |
844 | } | |
845 | ||
846 | /** | |
847 | * Sets the priority of a connection. | |
848 | * | |
849 | * @param pcb the tcp_pcb to manipulate | |
850 | * @param prio new priority | |
851 | */ | |
852 | void | |
853 | tcp_setprio(struct tcp_pcb *pcb, u8_t prio) | |
854 | { | |
855 | pcb->prio = prio; | |
856 | } | |
857 | #if TCP_QUEUE_OOSEQ | |
858 | ||
859 | /** | |
860 | * Returns a copy of the given TCP segment. | |
861 | * The pbuf and data are not copied, only the pointers | |
862 | * | |
863 | * @param seg the old tcp_seg | |
864 | * @return a copy of seg | |
865 | */ | |
866 | struct tcp_seg * | |
867 | tcp_seg_copy(struct tcp_seg *seg) | |
868 | { | |
869 | struct tcp_seg *cseg; | |
870 | ||
871 | cseg = memp_malloc(MEMP_TCP_SEG); | |
872 | if (cseg == NULL) { | |
873 | return NULL; | |
874 | } | |
875 | SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); | |
876 | pbuf_ref(cseg->p); | |
877 | return cseg; | |
878 | } | |
879 | #endif | |
880 | ||
881 | #if LWIP_CALLBACK_API | |
882 | /** | |
883 | * Default receive callback that is called if the user didn't register | |
884 | * a recv callback for the pcb. | |
885 | */ | |
886 | static err_t | |
887 | tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) | |
888 | { | |
889 | arg = arg; | |
890 | if (p != NULL) { | |
891 | pbuf_free(p); | |
892 | } else if (err == ERR_OK) { | |
893 | return tcp_close(pcb); | |
894 | } | |
895 | return ERR_OK; | |
896 | } | |
897 | #endif /* LWIP_CALLBACK_API */ | |
898 | ||
899 | /** | |
900 | * Kills the oldest active connection that has lower priority than prio. | |
901 | * | |
902 | * @param prio minimum priority | |
903 | */ | |
904 | static void | |
905 | tcp_kill_prio(u8_t prio) | |
906 | { | |
907 | struct tcp_pcb *pcb, *inactive; | |
908 | u32_t inactivity; | |
909 | u8_t mprio; | |
910 | ||
911 | ||
912 | mprio = TCP_PRIO_MAX; | |
913 | ||
914 | /* We kill the oldest active connection that has lower priority than prio. */ | |
915 | inactivity = 0; | |
916 | inactive = NULL; | |
917 | for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { | |
918 | if (pcb->prio <= prio && | |
919 | pcb->prio <= mprio && | |
920 | (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { | |
921 | inactivity = tcp_ticks - pcb->tmr; | |
922 | inactive = pcb; | |
923 | mprio = pcb->prio; | |
924 | } | |
925 | } | |
926 | if (inactive != NULL) { | |
927 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", | |
928 | (void *)inactive, inactivity)); | |
929 | tcp_abort(inactive); | |
930 | } | |
931 | } | |
932 | ||
933 | /** | |
934 | * Kills the oldest connection that is in TIME_WAIT state. | |
935 | * Called from tcp_alloc() if no more connections are available. | |
936 | */ | |
937 | static void | |
938 | tcp_kill_timewait(void) | |
939 | { | |
940 | struct tcp_pcb *pcb, *inactive; | |
941 | u32_t inactivity; | |
942 | ||
943 | inactivity = 0; | |
944 | inactive = NULL; | |
945 | /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ | |
946 | for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { | |
947 | if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { | |
948 | inactivity = tcp_ticks - pcb->tmr; | |
949 | inactive = pcb; | |
950 | } | |
951 | } | |
952 | if (inactive != NULL) { | |
953 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", | |
954 | (void *)inactive, inactivity)); | |
955 | tcp_abort(inactive); | |
956 | } | |
957 | } | |
958 | ||
959 | /** | |
960 | * Allocate a new tcp_pcb structure. | |
961 | * | |
962 | * @param prio priority for the new pcb | |
963 | * @return a new tcp_pcb that initially is in state CLOSED | |
964 | */ | |
965 | struct tcp_pcb * | |
966 | tcp_alloc(u8_t prio) | |
967 | { | |
968 | struct tcp_pcb *pcb; | |
969 | u32_t iss; | |
970 | ||
971 | pcb = memp_malloc(MEMP_TCP_PCB); | |
972 | if (pcb == NULL) { | |
973 | /* Try killing oldest connection in TIME-WAIT. */ | |
974 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); | |
975 | tcp_kill_timewait(); | |
976 | /* Try to allocate a tcp_pcb again. */ | |
977 | pcb = memp_malloc(MEMP_TCP_PCB); | |
978 | if (pcb == NULL) { | |
979 | /* Try killing active connections with lower priority than the new one. */ | |
980 | tcp_kill_prio(prio); | |
981 | /* Try to allocate a tcp_pcb again. */ | |
982 | pcb = memp_malloc(MEMP_TCP_PCB); | |
983 | } | |
984 | } | |
985 | if (pcb != NULL) { | |
986 | memset(pcb, 0, sizeof(struct tcp_pcb)); | |
987 | pcb->prio = TCP_PRIO_NORMAL; | |
988 | pcb->snd_buf = TCP_SND_BUF; | |
989 | pcb->snd_queuelen = 0; | |
990 | pcb->rcv_wnd = TCP_WND; | |
991 | pcb->rcv_ann_wnd = TCP_WND; | |
992 | pcb->tos = 0; | |
993 | pcb->ttl = TCP_TTL; | |
994 | /* The send MSS is updated when an MSS option is received. */ | |
995 | pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; | |
996 | pcb->rto = 3000 / TCP_SLOW_INTERVAL; | |
997 | pcb->sa = 0; | |
998 | pcb->sv = 3000 / TCP_SLOW_INTERVAL; | |
999 | pcb->rtime = -1; | |
1000 | pcb->cwnd = 1; | |
1001 | iss = tcp_next_iss(); | |
1002 | pcb->snd_wl2 = iss; | |
1003 | pcb->snd_nxt = iss; | |
1004 | pcb->snd_max = iss; | |
1005 | pcb->lastack = iss; | |
1006 | pcb->snd_lbb = iss; | |
1007 | pcb->tmr = tcp_ticks; | |
1008 | ||
1009 | pcb->polltmr = 0; | |
1010 | ||
1011 | #if LWIP_CALLBACK_API | |
1012 | pcb->recv = tcp_recv_null; | |
1013 | #endif /* LWIP_CALLBACK_API */ | |
1014 | ||
1015 | /* Init KEEPALIVE timer */ | |
1016 | pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; | |
1017 | ||
1018 | #if LWIP_TCP_KEEPALIVE | |
1019 | pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; | |
1020 | pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; | |
1021 | #endif /* LWIP_TCP_KEEPALIVE */ | |
1022 | ||
1023 | pcb->keep_cnt_sent = 0; | |
1024 | } | |
1025 | return pcb; | |
1026 | } | |
1027 | ||
1028 | /** | |
1029 | * Creates a new TCP protocol control block but doesn't place it on | |
1030 | * any of the TCP PCB lists. | |
1031 | * The pcb is not put on any list until binding using tcp_bind(). | |
1032 | * | |
1033 | * @internal: Maybe there should be a idle TCP PCB list where these | |
1034 | * PCBs are put on. Port reservation using tcp_bind() is implemented but | |
1035 | * allocated pcbs that are not bound can't be killed automatically if wanting | |
1036 | * to allocate a pcb with higher prio (@see tcp_kill_prio()) | |
1037 | * | |
1038 | * @return a new tcp_pcb that initially is in state CLOSED | |
1039 | */ | |
1040 | struct tcp_pcb * | |
1041 | tcp_new(void) | |
1042 | { | |
1043 | return tcp_alloc(TCP_PRIO_NORMAL); | |
1044 | } | |
1045 | ||
1046 | /** | |
1047 | * Used to specify the argument that should be passed callback | |
1048 | * functions. | |
1049 | * | |
1050 | * @param pcb tcp_pcb to set the callback argument | |
1051 | * @param arg void pointer argument to pass to callback functions | |
1052 | */ | |
1053 | void | |
1054 | tcp_arg(struct tcp_pcb *pcb, void *arg) | |
1055 | { | |
1056 | pcb->callback_arg = arg; | |
1057 | } | |
1058 | #if LWIP_CALLBACK_API | |
1059 | ||
1060 | /** | |
1061 | * Used to specify the function that should be called when a TCP | |
1062 | * connection receives data. | |
1063 | * | |
1064 | * @param pcb tcp_pcb to set the recv callback | |
1065 | * @param recv callback function to call for this pcb when data is received | |
1066 | */ | |
1067 | void | |
1068 | tcp_recv(struct tcp_pcb *pcb, | |
1069 | err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) | |
1070 | { | |
1071 | pcb->recv = recv; | |
1072 | } | |
1073 | ||
1074 | /** | |
1075 | * Used to specify the function that should be called when TCP data | |
1076 | * has been successfully delivered to the remote host. | |
1077 | * | |
1078 | * @param pcb tcp_pcb to set the sent callback | |
1079 | * @param sent callback function to call for this pcb when data is successfully sent | |
1080 | */ | |
1081 | void | |
1082 | tcp_sent(struct tcp_pcb *pcb, | |
1083 | err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) | |
1084 | { | |
1085 | pcb->sent = sent; | |
1086 | } | |
1087 | ||
1088 | /** | |
1089 | * Used to specify the function that should be called when a fatal error | |
1090 | * has occured on the connection. | |
1091 | * | |
1092 | * @param pcb tcp_pcb to set the err callback | |
1093 | * @param errf callback function to call for this pcb when a fatal error | |
1094 | * has occured on the connection | |
1095 | */ | |
1096 | void | |
1097 | tcp_err(struct tcp_pcb *pcb, | |
1098 | void (* errf)(void *arg, err_t err)) | |
1099 | { | |
1100 | pcb->errf = errf; | |
1101 | } | |
1102 | ||
1103 | /** | |
1104 | * Used for specifying the function that should be called when a | |
1105 | * LISTENing connection has been connected to another host. | |
1106 | * | |
1107 | * @param pcb tcp_pcb to set the accept callback | |
1108 | * @param accept callback function to call for this pcb when LISTENing | |
1109 | * connection has been connected to another host | |
1110 | */ | |
1111 | void | |
1112 | tcp_accept(struct tcp_pcb *pcb, | |
1113 | err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) | |
1114 | { | |
1115 | ((struct tcp_pcb_listen *)pcb)->accept = accept; | |
1116 | } | |
1117 | #endif /* LWIP_CALLBACK_API */ | |
1118 | ||
1119 | ||
1120 | /** | |
1121 | * Used to specify the function that should be called periodically | |
1122 | * from TCP. The interval is specified in terms of the TCP coarse | |
1123 | * timer interval, which is called twice a second. | |
1124 | * | |
1125 | */ | |
1126 | void | |
1127 | tcp_poll(struct tcp_pcb *pcb, | |
1128 | err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) | |
1129 | { | |
1130 | #if LWIP_CALLBACK_API | |
1131 | pcb->poll = poll; | |
1132 | #endif /* LWIP_CALLBACK_API */ | |
1133 | pcb->pollinterval = interval; | |
1134 | } | |
1135 | ||
1136 | /** | |
1137 | * Purges a TCP PCB. Removes any buffered data and frees the buffer memory | |
1138 | * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). | |
1139 | * | |
1140 | * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! | |
1141 | */ | |
1142 | void | |
1143 | tcp_pcb_purge(struct tcp_pcb *pcb) | |
1144 | { | |
1145 | if (pcb->state != CLOSED && | |
1146 | pcb->state != TIME_WAIT && | |
1147 | pcb->state != LISTEN) { | |
1148 | ||
1149 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); | |
1150 | ||
1151 | if (pcb->refused_data != NULL) { | |
1152 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); | |
1153 | pbuf_free(pcb->refused_data); | |
1154 | pcb->refused_data = NULL; | |
1155 | } | |
1156 | if (pcb->unsent != NULL) { | |
1157 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); | |
1158 | } | |
1159 | if (pcb->unacked != NULL) { | |
1160 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); | |
1161 | } | |
1162 | #if TCP_QUEUE_OOSEQ /* LW */ | |
1163 | if (pcb->ooseq != NULL) { | |
1164 | LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); | |
1165 | } | |
1166 | ||
1167 | /* Stop the retransmission timer as it will expect data on unacked | |
1168 | queue if it fires */ | |
1169 | pcb->rtime = -1; | |
1170 | ||
1171 | tcp_segs_free(pcb->ooseq); | |
1172 | pcb->ooseq = NULL; | |
1173 | #endif /* TCP_QUEUE_OOSEQ */ | |
1174 | tcp_segs_free(pcb->unsent); | |
1175 | tcp_segs_free(pcb->unacked); | |
1176 | pcb->unacked = pcb->unsent = NULL; | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | /** | |
1181 | * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. | |
1182 | * | |
1183 | * @param pcblist PCB list to purge. | |
1184 | * @param pcb tcp_pcb to purge. The pcb itself is also deallocated! | |
1185 | */ | |
1186 | void | |
1187 | tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) | |
1188 | { | |
1189 | TCP_RMV(pcblist, pcb); | |
1190 | ||
1191 | tcp_pcb_purge(pcb); | |
1192 | ||
1193 | /* if there is an outstanding delayed ACKs, send it */ | |
1194 | if (pcb->state != TIME_WAIT && | |
1195 | pcb->state != LISTEN && | |
1196 | pcb->flags & TF_ACK_DELAY) { | |
1197 | pcb->flags |= TF_ACK_NOW; | |
1198 | tcp_output(pcb); | |
1199 | } | |
1200 | ||
1201 | if (pcb->state != LISTEN) { | |
1202 | LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); | |
1203 | LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); | |
1204 | #if TCP_QUEUE_OOSEQ | |
1205 | LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); | |
1206 | #endif /* TCP_QUEUE_OOSEQ */ | |
1207 | } | |
1208 | ||
1209 | pcb->state = CLOSED; | |
1210 | ||
1211 | LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); | |
1212 | } | |
1213 | ||
1214 | /** | |
1215 | * Calculates a new initial sequence number for new connections. | |
1216 | * | |
1217 | * @return u32_t pseudo random sequence number | |
1218 | */ | |
1219 | u32_t | |
1220 | tcp_next_iss(void) | |
1221 | { | |
1222 | static u32_t iss = 6510; | |
1223 | ||
1224 | iss += tcp_ticks; /* XXX */ | |
1225 | return iss; | |
1226 | } | |
1227 | ||
1228 | #if TCP_CALCULATE_EFF_SEND_MSS | |
1229 | /** | |
1230 | * Calcluates the effective send mss that can be used for a specific IP address | |
1231 | * by using ip_route to determin the netif used to send to the address and | |
1232 | * calculating the minimum of TCP_MSS and that netif's mtu (if set). | |
1233 | */ | |
1234 | u16_t | |
1235 | tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr) | |
1236 | { | |
1237 | u16_t mss_s; | |
1238 | struct netif *outif; | |
1239 | ||
1240 | outif = ip_route(addr); | |
1241 | if ((outif != NULL) && (outif->mtu != 0)) { | |
1242 | mss_s = outif->mtu - IP_HLEN - TCP_HLEN; | |
1243 | /* RFC 1122, chap 4.2.2.6: | |
1244 | * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize | |
1245 | * but we only send options with SYN and that is never filled with data! */ | |
1246 | sendmss = LWIP_MIN(sendmss, mss_s); | |
1247 | } | |
1248 | return sendmss; | |
1249 | } | |
1250 | #endif /* TCP_CALCULATE_EFF_SEND_MSS */ | |
1251 | ||
1252 | #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG | |
1253 | /** | |
1254 | * Print a tcp header for debugging purposes. | |
1255 | * | |
1256 | * @param tcphdr pointer to a struct tcp_hdr | |
1257 | */ | |
1258 | void | |
1259 | tcp_debug_print(struct tcp_hdr *tcphdr) | |
1260 | { | |
1261 | LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); | |
1262 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
1263 | LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", | |
1264 | ntohs(tcphdr->src), ntohs(tcphdr->dest))); | |
1265 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
1266 | LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", | |
1267 | ntohl(tcphdr->seqno))); | |
1268 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
1269 | LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", | |
1270 | ntohl(tcphdr->ackno))); | |
1271 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
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 (", | |
1273 | TCPH_HDRLEN(tcphdr), | |
1274 | TCPH_FLAGS(tcphdr) >> 5 & 1, | |
1275 | TCPH_FLAGS(tcphdr) >> 4 & 1, | |
1276 | TCPH_FLAGS(tcphdr) >> 3 & 1, | |
1277 | TCPH_FLAGS(tcphdr) >> 2 & 1, | |
1278 | TCPH_FLAGS(tcphdr) >> 1 & 1, | |
1279 | TCPH_FLAGS(tcphdr) & 1, | |
1280 | ntohs(tcphdr->wnd))); | |
1281 | tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); | |
1282 | LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); | |
1283 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
1284 | LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", | |
1285 | ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); | |
1286 | LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); | |
1287 | } | |
1288 | ||
1289 | /** | |
1290 | * Print a tcp state for debugging purposes. | |
1291 | * | |
1292 | * @param s enum tcp_state to print | |
1293 | */ | |
1294 | void | |
1295 | tcp_debug_print_state(enum tcp_state s) | |
1296 | { | |
1297 | LWIP_DEBUGF(TCP_DEBUG, ("State: ")); | |
1298 | switch (s) { | |
1299 | case CLOSED: | |
1300 | LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n")); | |
1301 | break; | |
1302 | case LISTEN: | |
1303 | LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n")); | |
1304 | break; | |
1305 | case SYN_SENT: | |
1306 | LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n")); | |
1307 | break; | |
1308 | case SYN_RCVD: | |
1309 | LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n")); | |
1310 | break; | |
1311 | case ESTABLISHED: | |
1312 | LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n")); | |
1313 | break; | |
1314 | case FIN_WAIT_1: | |
1315 | LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n")); | |
1316 | break; | |
1317 | case FIN_WAIT_2: | |
1318 | LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n")); | |
1319 | break; | |
1320 | case CLOSE_WAIT: | |
1321 | LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n")); | |
1322 | break; | |
1323 | case CLOSING: | |
1324 | LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n")); | |
1325 | break; | |
1326 | case LAST_ACK: | |
1327 | LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n")); | |
1328 | break; | |
1329 | case TIME_WAIT: | |
1330 | LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n")); | |
1331 | break; | |
1332 | } | |
1333 | } | |
1334 | ||
1335 | /** | |
1336 | * Print tcp flags for debugging purposes. | |
1337 | * | |
1338 | * @param flags tcp flags, all active flags are printed | |
1339 | */ | |
1340 | void | |
1341 | tcp_debug_print_flags(u8_t flags) | |
1342 | { | |
1343 | if (flags & TCP_FIN) { | |
1344 | LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); | |
1345 | } | |
1346 | if (flags & TCP_SYN) { | |
1347 | LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); | |
1348 | } | |
1349 | if (flags & TCP_RST) { | |
1350 | LWIP_DEBUGF(TCP_DEBUG, ("RST ")); | |
1351 | } | |
1352 | if (flags & TCP_PSH) { | |
1353 | LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); | |
1354 | } | |
1355 | if (flags & TCP_ACK) { | |
1356 | LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); | |
1357 | } | |
1358 | if (flags & TCP_URG) { | |
1359 | LWIP_DEBUGF(TCP_DEBUG, ("URG ")); | |
1360 | } | |
1361 | if (flags & TCP_ECE) { | |
1362 | LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); | |
1363 | } | |
1364 | if (flags & TCP_CWR) { | |
1365 | LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); | |
1366 | } | |
1367 | } | |
1368 | ||
1369 | /** | |
1370 | * Print all tcp_pcbs in every list for debugging purposes. | |
1371 | */ | |
1372 | void | |
1373 | tcp_debug_print_pcbs(void) | |
1374 | { | |
1375 | struct tcp_pcb *pcb; | |
1376 | LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); | |
1377 | for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { | |
1378 | LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", | |
1379 | pcb->local_port, pcb->remote_port, | |
1380 | pcb->snd_nxt, pcb->rcv_nxt)); | |
1381 | tcp_debug_print_state(pcb->state); | |
1382 | } | |
1383 | LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); | |
1384 | for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { | |
1385 | LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", | |
1386 | pcb->local_port, pcb->remote_port, | |
1387 | pcb->snd_nxt, pcb->rcv_nxt)); | |
1388 | tcp_debug_print_state(pcb->state); | |
1389 | } | |
1390 | LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); | |
1391 | for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { | |
1392 | LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", | |
1393 | pcb->local_port, pcb->remote_port, | |
1394 | pcb->snd_nxt, pcb->rcv_nxt)); | |
1395 | tcp_debug_print_state(pcb->state); | |
1396 | } | |
1397 | } | |
1398 | ||
1399 | /** | |
1400 | * Check state consistency of the tcp_pcb lists. | |
1401 | */ | |
1402 | s16_t | |
1403 | tcp_pcbs_sane(void) | |
1404 | { | |
1405 | struct tcp_pcb *pcb; | |
1406 | for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { | |
1407 | LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); | |
1408 | LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); | |
1409 | LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); | |
1410 | } | |
1411 | for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { | |
1412 | LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); | |
1413 | } | |
1414 | return 1; | |
1415 | } | |
1416 | #endif /* TCP_DEBUG */ | |
1417 | ||
1418 | #endif /* LWIP_TCP */ |