]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/uIP_Demo_Rowley_ARM7/uip/uip.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / uIP_Demo_Rowley_ARM7 / uip / uip.c
1 /**\r
2  * \addtogroup uip\r
3  * @{\r
4  */\r
5 \r
6 /**\r
7  * \file\r
8  * The uIP TCP/IP stack code.\r
9  * \author Adam Dunkels <adam@dunkels.com>\r
10  */\r
11 \r
12 /*\r
13  * Copyright (c) 2001-2003, Adam Dunkels.\r
14  * All rights reserved. \r
15  *\r
16  * Redistribution and use in source and binary forms, with or without \r
17  * modification, are permitted provided that the following conditions \r
18  * are met: \r
19  * 1. Redistributions of source code must retain the above copyright \r
20  *    notice, this list of conditions and the following disclaimer. \r
21  * 2. Redistributions in binary form must reproduce the above copyright \r
22  *    notice, this list of conditions and the following disclaimer in the \r
23  *    documentation and/or other materials provided with the distribution. \r
24  * 3. The name of the author may not be used to endorse or promote\r
25  *    products derived from this software without specific prior\r
26  *    written permission.  \r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\r
29  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
30  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\r
32  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
34  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
36  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  \r
39  *\r
40  * This file is part of the uIP TCP/IP stack.\r
41  *\r
42  * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $\r
43  *\r
44  */\r
45 \r
46 /*\r
47 This is a small implementation of the IP and TCP protocols (as well as\r
48 some basic ICMP stuff). The implementation couples the IP, TCP and the\r
49 application layers very tightly. To keep the size of the compiled code\r
50 down, this code also features heavy usage of the goto statement.\r
51 \r
52 The principle is that we have a small buffer, called the uip_buf, in\r
53 which the device driver puts an incoming packet. The TCP/IP stack\r
54 parses the headers in the packet, and calls upon the application. If\r
55 the remote host has sent data to the application, this data is present\r
56 in the uip_buf and the application read the data from there. It is up\r
57 to the application to put this data into a byte stream if needed. The\r
58 application will not be fed with data that is out of sequence.\r
59 \r
60 If the application whishes to send data to the peer, it should put its\r
61 data into the uip_buf, 40 bytes from the start of the buffer. The\r
62 TCP/IP stack will calculate the checksums, and fill in the necessary\r
63 header fields and finally send the packet back to the peer.\r
64 */\r
65 \r
66 #include "uip.h"\r
67 #include "uipopt.h"\r
68 #include "uip_arch.h"\r
69 \r
70 /*-----------------------------------------------------------------------------------*/\r
71 /* Variable definitions. */\r
72 \r
73 \r
74 /* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */\r
75 #if UIP_FIXEDADDR > 0\r
76 const u16_t uip_hostaddr[2] =\r
77   {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),\r
78    HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};\r
79 const u16_t uip_arp_draddr[2] =\r
80   {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),\r
81    HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};\r
82 const u16_t uip_arp_netmask[2] =\r
83   {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),\r
84    HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};\r
85 #else\r
86 u16_t uip_hostaddr[2];       \r
87 u16_t uip_arp_draddr[2], uip_arp_netmask[2];\r
88 #endif /* UIP_FIXEDADDR */\r
89 \r
90 u8_t uip_buf[UIP_BUFSIZE+2];   /* The packet buffer that contains\r
91                                 incoming packets. */\r
92 volatile u8_t *uip_appdata;  /* The uip_appdata pointer points to\r
93                                 application data. */\r
94 volatile u8_t *uip_sappdata;  /* The uip_appdata pointer points to the\r
95                                  application data which is to be sent. */\r
96 #if UIP_URGDATA > 0\r
97 volatile u8_t *uip_urgdata;  /* The uip_urgdata pointer points to\r
98                                 urgent data (out-of-band data), if\r
99                                 present. */\r
100 volatile u8_t uip_urglen, uip_surglen;\r
101 #endif /* UIP_URGDATA > 0 */\r
102 \r
103 volatile u16_t uip_len, uip_slen;\r
104                              /* The uip_len is either 8 or 16 bits,\r
105                                 depending on the maximum packet\r
106                                 size. */\r
107 \r
108 volatile u8_t uip_flags;     /* The uip_flags variable is used for\r
109                                 communication between the TCP/IP stack\r
110                                 and the application program. */\r
111 struct uip_conn *uip_conn;   /* uip_conn always points to the current\r
112                                 connection. */\r
113 \r
114 struct uip_conn uip_conns[UIP_CONNS];\r
115                              /* The uip_conns array holds all TCP\r
116                                 connections. */\r
117 u16_t uip_listenports[UIP_LISTENPORTS];\r
118                              /* The uip_listenports list all currently\r
119                                 listning ports. */\r
120 #if UIP_UDP\r
121 struct uip_udp_conn *uip_udp_conn;\r
122 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];\r
123 #endif /* UIP_UDP */\r
124 \r
125 \r
126 static u16_t ipid;           /* Ths ipid variable is an increasing\r
127                                 number that is used for the IP ID\r
128                                 field. */\r
129 \r
130 static u8_t iss[4];          /* The iss variable is used for the TCP\r
131                                 initial sequence number. */\r
132 \r
133 #if UIP_ACTIVE_OPEN\r
134 static u16_t lastport;       /* Keeps track of the last port used for\r
135                                 a new connection. */\r
136 #endif /* UIP_ACTIVE_OPEN */\r
137 \r
138 /* Temporary variables. */\r
139 volatile u8_t uip_acc32[4];\r
140 static u8_t c, opt;\r
141 static u16_t tmp16;\r
142 \r
143 /* Structures and definitions. */\r
144 #define TCP_FIN 0x01\r
145 #define TCP_SYN 0x02\r
146 #define TCP_RST 0x04\r
147 #define TCP_PSH 0x08\r
148 #define TCP_ACK 0x10\r
149 #define TCP_URG 0x20\r
150 #define TCP_CTL 0x3f\r
151 \r
152 #define ICMP_ECHO_REPLY 0\r
153 #define ICMP_ECHO       8     \r
154 \r
155 /* Macros. */\r
156 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
157 #define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])\r
158 #define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
159 #define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])\r
160 \r
161 #if UIP_STATISTICS == 1\r
162 struct uip_stats uip_stat;\r
163 #define UIP_STAT(s) s\r
164 #else\r
165 #define UIP_STAT(s)\r
166 #endif /* UIP_STATISTICS == 1 */\r
167 \r
168 #if UIP_LOGGING == 1\r
169 #include <stdio.h>\r
170 void uip_log(char *msg);\r
171 #define UIP_LOG(m) uip_log(m)\r
172 #else\r
173 #define UIP_LOG(m)\r
174 #endif /* UIP_LOGGING == 1 */\r
175 \r
176 /*-----------------------------------------------------------------------------------*/\r
177 void\r
178 uip_init(void)\r
179 {\r
180   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
181     uip_listenports[c] = 0;\r
182   }\r
183   for(c = 0; c < UIP_CONNS; ++c) {\r
184     uip_conns[c].tcpstateflags = CLOSED;\r
185   }\r
186 #if UIP_ACTIVE_OPEN\r
187   lastport = 1024;\r
188 #endif /* UIP_ACTIVE_OPEN */\r
189 \r
190 #if UIP_UDP\r
191   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
192     uip_udp_conns[c].lport = 0;\r
193   }\r
194 #endif /* UIP_UDP */\r
195   \r
196 \r
197   /* IPv4 initialization. */\r
198 #if UIP_FIXEDADDR == 0\r
199   uip_hostaddr[0] = uip_hostaddr[1] = 0;\r
200 #endif /* UIP_FIXEDADDR */\r
201 \r
202 }\r
203 /*-----------------------------------------------------------------------------------*/\r
204 #if UIP_ACTIVE_OPEN\r
205 struct uip_conn *\r
206 uip_connect(u16_t *ripaddr, u16_t rport)\r
207 {\r
208   register struct uip_conn *conn, *cconn;\r
209   \r
210   /* Find an unused local port. */\r
211  again:\r
212   ++lastport;\r
213 \r
214   if(lastport >= 32000) {\r
215     lastport = 4096;\r
216   }\r
217 \r
218   /* Check if this port is already in use, and if so try to find\r
219      another one. */\r
220   for(c = 0; c < UIP_CONNS; ++c) {\r
221     conn = &uip_conns[c];\r
222     if(conn->tcpstateflags != CLOSED &&\r
223        conn->lport == htons(lastport)) {\r
224       goto again;\r
225     }\r
226   }\r
227 \r
228 \r
229   conn = 0;\r
230   for(c = 0; c < UIP_CONNS; ++c) {\r
231     cconn = &uip_conns[c]; \r
232     if(cconn->tcpstateflags == CLOSED) {\r
233       conn = cconn;\r
234       break;\r
235     }\r
236     if(cconn->tcpstateflags == TIME_WAIT) {\r
237       if(conn == 0 ||\r
238          cconn->timer > uip_conn->timer) {\r
239         conn = cconn;\r
240       }\r
241     }\r
242   }\r
243 \r
244   if(conn == 0) {\r
245     return 0;\r
246   }\r
247   \r
248   conn->tcpstateflags = SYN_SENT;\r
249 \r
250   conn->snd_nxt[0] = iss[0];\r
251   conn->snd_nxt[1] = iss[1];\r
252   conn->snd_nxt[2] = iss[2];\r
253   conn->snd_nxt[3] = iss[3];\r
254 \r
255   conn->initialmss = conn->mss = UIP_TCP_MSS;\r
256   \r
257   conn->len = 1;   /* TCP length of the SYN is one. */\r
258   conn->nrtx = 0;\r
259   conn->timer = 1; /* Send the SYN next time around. */\r
260   conn->rto = UIP_RTO;\r
261   conn->sa = 0;\r
262   conn->sv = 16;\r
263   conn->lport = htons(lastport);\r
264   conn->rport = rport;\r
265   conn->ripaddr[0] = ripaddr[0];\r
266   conn->ripaddr[1] = ripaddr[1];\r
267   \r
268   return conn;\r
269 }\r
270 #endif /* UIP_ACTIVE_OPEN */\r
271 /*-----------------------------------------------------------------------------------*/\r
272 #if UIP_UDP\r
273 struct uip_udp_conn *\r
274 uip_udp_new(u16_t *ripaddr, u16_t rport)\r
275 {\r
276   register struct uip_udp_conn *conn;\r
277   \r
278   /* Find an unused local port. */\r
279  again:\r
280   ++lastport;\r
281 \r
282   if(lastport >= 32000) {\r
283     lastport = 4096;\r
284   }\r
285   \r
286   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
287     if(uip_udp_conns[c].lport == lastport) {\r
288       goto again;\r
289     }\r
290   }\r
291 \r
292 \r
293   conn = 0;\r
294   for(c = 0; c < UIP_UDP_CONNS; ++c) {\r
295     if(uip_udp_conns[c].lport == 0) {\r
296       conn = &uip_udp_conns[c]; \r
297       break;\r
298     }\r
299   }\r
300 \r
301   if(conn == 0) {\r
302     return 0;\r
303   }\r
304   \r
305   conn->lport = HTONS(lastport);\r
306   conn->rport = HTONS(rport);\r
307   conn->ripaddr[0] = ripaddr[0];\r
308   conn->ripaddr[1] = ripaddr[1];\r
309   \r
310   return conn;\r
311 }\r
312 #endif /* UIP_UDP */\r
313 /*-----------------------------------------------------------------------------------*/\r
314 void\r
315 uip_unlisten(u16_t port)\r
316 {\r
317   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
318     if(uip_listenports[c] == port) {\r
319       uip_listenports[c] = 0;\r
320       return;\r
321     }\r
322   }\r
323 }\r
324 /*-----------------------------------------------------------------------------------*/\r
325 void\r
326 uip_listen(u16_t port)\r
327 {\r
328   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
329     if(uip_listenports[c] == 0) {\r
330       uip_listenports[c] = port;\r
331       return;\r
332     }\r
333   }\r
334 }\r
335 /*-----------------------------------------------------------------------------------*/\r
336 /* XXX: IP fragment reassembly: not well-tested. */\r
337 \r
338 #if UIP_REASSEMBLY\r
339 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)\r
340 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];\r
341 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];\r
342 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,\r
343                                     0x0f, 0x07, 0x03, 0x01};\r
344 static u16_t uip_reasslen;\r
345 static u8_t uip_reassflags;\r
346 #define UIP_REASS_FLAG_LASTFRAG 0x01\r
347 static u8_t uip_reasstmr;\r
348 \r
349 #define IP_HLEN 20\r
350 #define IP_MF   0x20\r
351 \r
352 static u8_t\r
353 uip_reass(void)\r
354 {\r
355   u16_t offset, len;\r
356   u16_t i;\r
357 \r
358   /* If ip_reasstmr is zero, no packet is present in the buffer, so we\r
359      write the IP header of the fragment into the reassembly\r
360      buffer. The timer is updated with the maximum age. */\r
361   if(uip_reasstmr == 0) {\r
362     memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);\r
363     uip_reasstmr = UIP_REASS_MAXAGE;\r
364     uip_reassflags = 0;\r
365     /* Clear the bitmap. */\r
366     memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);\r
367   }\r
368 \r
369   /* Check if the incoming fragment matches the one currently present\r
370      in the reasembly buffer. If so, we proceed with copying the\r
371      fragment into the buffer. */\r
372   if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&\r
373      BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&\r
374      BUF->destipaddr[0] == FBUF->destipaddr[0] &&\r
375      BUF->destipaddr[1] == FBUF->destipaddr[1] &&\r
376      BUF->ipid[0] == FBUF->ipid[0] &&\r
377      BUF->ipid[1] == FBUF->ipid[1]) {\r
378 \r
379     len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;\r
380     offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;\r
381 \r
382     /* If the offset or the offset + fragment length overflows the\r
383        reassembly buffer, we discard the entire packet. */\r
384     if(offset > UIP_REASS_BUFSIZE ||\r
385        offset + len > UIP_REASS_BUFSIZE) {\r
386       uip_reasstmr = 0;\r
387       goto nullreturn;\r
388     }\r
389 \r
390     /* Copy the fragment into the reassembly buffer, at the right\r
391        offset. */\r
392     memcpy(&uip_reassbuf[IP_HLEN + offset],\r
393            (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),\r
394            len);\r
395       \r
396     /* Update the bitmap. */\r
397     if(offset / (8 * 8) == (offset + len) / (8 * 8)) {\r
398       /* If the two endpoints are in the same byte, we only update\r
399          that byte. */\r
400              \r
401       uip_reassbitmap[offset / (8 * 8)] |=\r
402              bitmap_bits[(offset / 8 ) & 7] &\r
403              ~bitmap_bits[((offset + len) / 8 ) & 7];\r
404     } else {\r
405       /* If the two endpoints are in different bytes, we update the\r
406          bytes in the endpoints and fill the stuff inbetween with\r
407          0xff. */\r
408       uip_reassbitmap[offset / (8 * 8)] |=\r
409         bitmap_bits[(offset / 8 ) & 7];\r
410       for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {\r
411         uip_reassbitmap[i] = 0xff;\r
412       }      \r
413       uip_reassbitmap[(offset + len) / (8 * 8)] |=\r
414         ~bitmap_bits[((offset + len) / 8 ) & 7];\r
415     }\r
416     \r
417     /* If this fragment has the More Fragments flag set to zero, we\r
418        know that this is the last fragment, so we can calculate the\r
419        size of the entire packet. We also set the\r
420        IP_REASS_FLAG_LASTFRAG flag to indicate that we have received\r
421        the final fragment. */\r
422 \r
423     if((BUF->ipoffset[0] & IP_MF) == 0) {\r
424       uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;\r
425       uip_reasslen = offset + len;\r
426     }\r
427     \r
428     /* Finally, we check if we have a full packet in the buffer. We do\r
429        this by checking if we have the last fragment and if all bits\r
430        in the bitmap are set. */\r
431     if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {\r
432       /* Check all bytes up to and including all but the last byte in\r
433          the bitmap. */\r
434       for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {\r
435         if(uip_reassbitmap[i] != 0xff) {\r
436           goto nullreturn;\r
437         }\r
438       }\r
439       /* Check the last byte in the bitmap. It should contain just the\r
440          right amount of bits. */\r
441       if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=\r
442          (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {\r
443         goto nullreturn;\r
444       }\r
445 \r
446       /* If we have come this far, we have a full packet in the\r
447          buffer, so we allocate a pbuf and copy the packet into it. We\r
448          also reset the timer. */\r
449       uip_reasstmr = 0;\r
450       memcpy(BUF, FBUF, uip_reasslen);\r
451 \r
452       /* Pretend to be a "normal" (i.e., not fragmented) IP packet\r
453          from now on. */\r
454       BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
455       BUF->len[0] = uip_reasslen >> 8;\r
456       BUF->len[1] = uip_reasslen & 0xff;\r
457       BUF->ipchksum = 0;\r
458       BUF->ipchksum = ~(uip_ipchksum());\r
459 \r
460       return uip_reasslen;\r
461     }\r
462   }\r
463 \r
464  nullreturn:\r
465   return 0;\r
466 }\r
467 #endif /* UIP_REASSEMBL */\r
468 /*-----------------------------------------------------------------------------------*/\r
469 static void\r
470 uip_add_rcv_nxt(u16_t n)\r
471 {\r
472   uip_add32(uip_conn->rcv_nxt, n);\r
473   uip_conn->rcv_nxt[0] = uip_acc32[0];\r
474   uip_conn->rcv_nxt[1] = uip_acc32[1];\r
475   uip_conn->rcv_nxt[2] = uip_acc32[2];\r
476   uip_conn->rcv_nxt[3] = uip_acc32[3];\r
477 }\r
478 /*-----------------------------------------------------------------------------------*/\r
479 void\r
480 uip_process(u8_t flag)\r
481 {\r
482   register struct uip_conn *uip_connr = uip_conn;\r
483   \r
484   uip_appdata = &uip_buf[40 + UIP_LLH_LEN];\r
485 \r
486   \r
487   /* Check if we were invoked because of the perodic timer fireing. */\r
488   if(flag == UIP_TIMER) {\r
489 #if UIP_REASSEMBLY\r
490     if(uip_reasstmr != 0) {\r
491       --uip_reasstmr;\r
492     }\r
493 #endif /* UIP_REASSEMBLY */\r
494     /* Increase the initial sequence number. */\r
495     if(++iss[3] == 0) {\r
496       if(++iss[2] == 0) {\r
497         if(++iss[1] == 0) {\r
498           ++iss[0];\r
499         }\r
500       }\r
501     }    \r
502     uip_len = 0;\r
503     if(uip_connr->tcpstateflags == TIME_WAIT ||\r
504        uip_connr->tcpstateflags == FIN_WAIT_2) {\r
505       ++(uip_connr->timer);\r
506       if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {\r
507         uip_connr->tcpstateflags = CLOSED;\r
508       }\r
509     } else if(uip_connr->tcpstateflags != CLOSED) {\r
510       /* If the connection has outstanding data, we increase the\r
511          connection's timer and see if it has reached the RTO value\r
512          in which case we retransmit. */\r
513       if(uip_outstanding(uip_connr)) {\r
514         if(uip_connr->timer-- == 0) {\r
515           if(uip_connr->nrtx == UIP_MAXRTX ||\r
516              ((uip_connr->tcpstateflags == SYN_SENT ||\r
517                uip_connr->tcpstateflags == SYN_RCVD) &&\r
518               uip_connr->nrtx == UIP_MAXSYNRTX)) {\r
519             uip_connr->tcpstateflags = CLOSED;\r
520 \r
521             /* We call UIP_APPCALL() with uip_flags set to\r
522                UIP_TIMEDOUT to inform the application that the\r
523                connection has timed out. */\r
524             uip_flags = UIP_TIMEDOUT;\r
525             UIP_APPCALL();\r
526 \r
527             /* We also send a reset packet to the remote host. */\r
528             BUF->flags = TCP_RST | TCP_ACK;\r
529             goto tcp_send_nodata;\r
530           }\r
531 \r
532           /* Exponential backoff. */\r
533           uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?\r
534                                          4:\r
535                                          uip_connr->nrtx);\r
536           ++(uip_connr->nrtx);\r
537           \r
538           /* Ok, so we need to retransmit. We do this differently\r
539              depending on which state we are in. In ESTABLISHED, we\r
540              call upon the application so that it may prepare the\r
541              data for the retransmit. In SYN_RCVD, we resend the\r
542              SYNACK that we sent earlier and in LAST_ACK we have to\r
543              retransmit our FINACK. */\r
544           UIP_STAT(++uip_stat.tcp.rexmit);\r
545           switch(uip_connr->tcpstateflags & TS_MASK) {\r
546           case SYN_RCVD:\r
547             /* In the SYN_RCVD state, we should retransmit our\r
548                SYNACK. */\r
549             goto tcp_send_synack;\r
550             \r
551 #if UIP_ACTIVE_OPEN\r
552           case SYN_SENT:\r
553             /* In the SYN_SENT state, we retransmit out SYN. */\r
554             BUF->flags = 0;\r
555             goto tcp_send_syn;\r
556 #endif /* UIP_ACTIVE_OPEN */\r
557             \r
558           case ESTABLISHED:\r
559             /* In the ESTABLISHED state, we call upon the application\r
560                to do the actual retransmit after which we jump into\r
561                the code for sending out the packet (the apprexmit\r
562                label). */\r
563             uip_len = 0;\r
564             uip_slen = 0;\r
565             uip_flags = UIP_REXMIT;\r
566             UIP_APPCALL();\r
567             goto apprexmit;\r
568             \r
569           case FIN_WAIT_1:\r
570           case CLOSING:\r
571           case LAST_ACK:\r
572             /* In all these states we should retransmit a FINACK. */\r
573             goto tcp_send_finack;\r
574             \r
575           }\r
576         }\r
577       } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {\r
578         /* If there was no need for a retransmission, we poll the\r
579            application for new data. */\r
580         uip_len = 0;\r
581         uip_slen = 0;\r
582         uip_flags = UIP_POLL;\r
583         UIP_APPCALL();\r
584         goto appsend;\r
585       }\r
586     }\r
587     goto drop;\r
588   }\r
589 #if UIP_UDP \r
590   if(flag == UIP_UDP_TIMER) {\r
591     if(uip_udp_conn->lport != 0) {\r
592       uip_appdata = &uip_buf[UIP_LLH_LEN + 28];\r
593       uip_len = uip_slen = 0;\r
594       uip_flags = UIP_POLL;\r
595       UIP_UDP_APPCALL();\r
596       goto udp_send;\r
597     } else {\r
598       goto drop;\r
599     }\r
600   }\r
601 #endif\r
602 \r
603   /* This is where the input processing starts. */\r
604   UIP_STAT(++uip_stat.ip.recv);\r
605 \r
606 \r
607   /* Start of IPv4 input header processing code. */\r
608   \r
609   /* Check validity of the IP header. */  \r
610   if(BUF->vhl != 0x45)  { /* IP version and header length. */\r
611     UIP_STAT(++uip_stat.ip.drop);\r
612     UIP_STAT(++uip_stat.ip.vhlerr);\r
613     UIP_LOG("ip: invalid version or header length.");\r
614     goto drop;\r
615   }\r
616   \r
617   /* Check the size of the packet. If the size reported to us in\r
618      uip_len doesn't match the size reported in the IP header, there\r
619      has been a transmission error and we drop the packet. */\r
620   \r
621   if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */\r
622     uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);\r
623   }\r
624   if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */\r
625     uip_len = (uip_len & 0xff00) | BUF->len[1];\r
626   }\r
627 \r
628   /* Check the fragment flag. */\r
629   if((BUF->ipoffset[0] & 0x3f) != 0 ||\r
630      BUF->ipoffset[1] != 0) { \r
631 #if UIP_REASSEMBLY\r
632     uip_len = uip_reass();\r
633     if(uip_len == 0) {\r
634       goto drop;\r
635     }\r
636 #else\r
637     UIP_STAT(++uip_stat.ip.drop);\r
638     UIP_STAT(++uip_stat.ip.fragerr);\r
639     UIP_LOG("ip: fragment dropped.");    \r
640     goto drop;\r
641 #endif /* UIP_REASSEMBLY */\r
642   }\r
643 \r
644   /* If we are configured to use ping IP address configuration and\r
645      hasn't been assigned an IP address yet, we accept all ICMP\r
646      packets. */\r
647 #if UIP_PINGADDRCONF\r
648   if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {\r
649     if(BUF->proto == UIP_PROTO_ICMP) {\r
650       UIP_LOG("ip: possible ping config packet received.");\r
651       goto icmp_input;\r
652     } else {\r
653       UIP_LOG("ip: packet dropped since no address assigned.");\r
654       goto drop;\r
655     }\r
656   }\r
657 #endif /* UIP_PINGADDRCONF */\r
658   \r
659   /* Check if the packet is destined for our IP address. */  \r
660   if(BUF->destipaddr[0] != uip_hostaddr[0]) {\r
661     UIP_STAT(++uip_stat.ip.drop);\r
662     UIP_LOG("ip: packet not for us.");        \r
663     goto drop;\r
664   }\r
665   if(BUF->destipaddr[1] != uip_hostaddr[1]) {\r
666     UIP_STAT(++uip_stat.ip.drop);\r
667     UIP_LOG("ip: packet not for us.");        \r
668     goto drop;\r
669   }\r
670 \r
671 #if 0\r
672   // IP checksum is wrong through Netgear DSL router\r
673   if (uip_ipchksum() != 0xffff) { /* Compute and check the IP header\r
674                                     checksum. */\r
675     UIP_STAT(++uip_stat.ip.drop);\r
676     UIP_STAT(++uip_stat.ip.chkerr);\r
677     UIP_LOG("ip: bad checksum.");    \r
678     goto drop;\r
679   }\r
680 #endif\r
681 \r
682   if(BUF->proto == UIP_PROTO_TCP)  /* Check for TCP packet. If so, jump\r
683                                      to the tcp_input label. */\r
684     goto tcp_input;\r
685 \r
686 #if UIP_UDP\r
687   if(BUF->proto == UIP_PROTO_UDP)\r
688     goto udp_input;\r
689 #endif /* UIP_UDP */\r
690 \r
691   if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from\r
692                                         here. */\r
693     UIP_STAT(++uip_stat.ip.drop);\r
694     UIP_STAT(++uip_stat.ip.protoerr);\r
695     UIP_LOG("ip: neither tcp nor icmp.");        \r
696     goto drop;\r
697   }\r
698   \r
699  icmp_input:\r
700   UIP_STAT(++uip_stat.icmp.recv);\r
701   \r
702   /* ICMP echo (i.e., ping) processing. This is simple, we only change\r
703      the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP\r
704      checksum before we return the packet. */\r
705   if(ICMPBUF->type != ICMP_ECHO) {\r
706     UIP_STAT(++uip_stat.icmp.drop);\r
707     UIP_STAT(++uip_stat.icmp.typeerr);\r
708     UIP_LOG("icmp: not icmp echo.");\r
709     goto drop;\r
710   }\r
711 \r
712   /* If we are configured to use ping IP address assignment, we use\r
713      the destination IP address of this ping packet and assign it to\r
714      ourself. */\r
715 #if UIP_PINGADDRCONF\r
716   if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {\r
717     uip_hostaddr[0] = BUF->destipaddr[0];\r
718     uip_hostaddr[1] = BUF->destipaddr[1];\r
719   }\r
720 #endif /* UIP_PINGADDRCONF */  \r
721   \r
722   ICMPBUF->type = ICMP_ECHO_REPLY;\r
723   \r
724   if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {\r
725     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;\r
726   } else {\r
727     ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);\r
728   }\r
729   \r
730   /* Swap IP addresses. */\r
731   tmp16 = BUF->destipaddr[0];\r
732   BUF->destipaddr[0] = BUF->srcipaddr[0];\r
733   BUF->srcipaddr[0] = tmp16;\r
734   tmp16 = BUF->destipaddr[1];\r
735   BUF->destipaddr[1] = BUF->srcipaddr[1];\r
736   BUF->srcipaddr[1] = tmp16;\r
737 \r
738   UIP_STAT(++uip_stat.icmp.sent);\r
739   goto send;\r
740 \r
741   /* End of IPv4 input header processing code. */\r
742   \r
743 \r
744 #if UIP_UDP\r
745   /* UDP input processing. */\r
746  udp_input:\r
747   /* UDP processing is really just a hack. We don't do anything to the\r
748      UDP/IP headers, but let the UDP application do all the hard\r
749      work. If the application sets uip_slen, it has a packet to\r
750      send. */\r
751 #if UIP_UDP_CHECKSUMS\r
752   if(uip_udpchksum() != 0xffff) { \r
753     UIP_STAT(++uip_stat.udp.drop);\r
754     UIP_STAT(++uip_stat.udp.chkerr);\r
755     UIP_LOG("udp: bad checksum.");    \r
756     goto drop;\r
757   }  \r
758 #endif /* UIP_UDP_CHECKSUMS */\r
759 \r
760   /* Demultiplex this UDP packet between the UDP "connections". */\r
761   for(uip_udp_conn = &uip_udp_conns[0];\r
762       uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];\r
763       ++uip_udp_conn) {\r
764     if(uip_udp_conn->lport != 0 &&\r
765        UDPBUF->destport == uip_udp_conn->lport &&\r
766        (uip_udp_conn->rport == 0 ||\r
767         UDPBUF->srcport == uip_udp_conn->rport) &&\r
768        BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&\r
769        BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {\r
770       goto udp_found; \r
771     }\r
772   }\r
773   goto drop;\r
774   \r
775  udp_found:\r
776   uip_len = uip_len - 28;\r
777   uip_appdata = &uip_buf[UIP_LLH_LEN + 28];\r
778   uip_flags = UIP_NEWDATA;\r
779   uip_slen = 0;\r
780   UIP_UDP_APPCALL();\r
781  udp_send:\r
782   if(uip_slen == 0) {\r
783     goto drop;      \r
784   }\r
785   uip_len = uip_slen + 28;\r
786 \r
787   BUF->len[0] = (uip_len >> 8);\r
788   BUF->len[1] = (uip_len & 0xff);\r
789   \r
790   BUF->proto = UIP_PROTO_UDP;\r
791 \r
792   UDPBUF->udplen = HTONS(uip_slen + 8);\r
793   UDPBUF->udpchksum = 0;\r
794 #if UIP_UDP_CHECKSUMS \r
795   /* Calculate UDP checksum. */\r
796   UDPBUF->udpchksum = ~(uip_udpchksum());\r
797   if(UDPBUF->udpchksum == 0) {\r
798     UDPBUF->udpchksum = 0xffff;\r
799   }\r
800 #endif /* UIP_UDP_CHECKSUMS */\r
801 \r
802   BUF->srcport  = uip_udp_conn->lport;\r
803   BUF->destport = uip_udp_conn->rport;\r
804 \r
805   BUF->srcipaddr[0] = uip_hostaddr[0];\r
806   BUF->srcipaddr[1] = uip_hostaddr[1];\r
807   BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];\r
808   BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];\r
809  \r
810   uip_appdata = &uip_buf[UIP_LLH_LEN + 40];\r
811   goto ip_send_nolen;\r
812 #endif /* UIP_UDP */\r
813   \r
814   /* TCP input processing. */  \r
815  tcp_input:\r
816   UIP_STAT(++uip_stat.tcp.recv);\r
817 \r
818   /* Start of TCP input header processing code. */\r
819   \r
820 #if 1  // FIXME\r
821   if(uip_tcpchksum() != 0xffff) {   /* Compute and check the TCP\r
822                                        checksum. */\r
823     UIP_STAT(++uip_stat.tcp.drop);\r
824     UIP_STAT(++uip_stat.tcp.chkerr);\r
825     UIP_LOG("tcp: bad checksum.");    \r
826     goto drop;\r
827   }\r
828 #endif\r
829   \r
830   /* Demultiplex this segment. */\r
831   /* First check any active connections. */\r
832   for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {\r
833     if(uip_connr->tcpstateflags != CLOSED &&\r
834        BUF->destport == uip_connr->lport &&\r
835        BUF->srcport == uip_connr->rport &&\r
836        BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&\r
837        BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {\r
838       goto found;    \r
839     }\r
840   }\r
841 \r
842   /* If we didn't find and active connection that expected the packet,\r
843      either this packet is an old duplicate, or this is a SYN packet\r
844      destined for a connection in LISTEN. If the SYN flag isn't set,\r
845      it is an old packet and we send a RST. */\r
846   if((BUF->flags & TCP_CTL) != TCP_SYN)\r
847     goto reset;\r
848   \r
849   tmp16 = BUF->destport;\r
850   /* Next, check listening connections. */  \r
851   for(c = 0; c < UIP_LISTENPORTS; ++c) {\r
852     if(tmp16 == uip_listenports[c])\r
853       goto found_listen;\r
854   }\r
855   \r
856   /* No matching connection found, so we send a RST packet. */\r
857   UIP_STAT(++uip_stat.tcp.synrst);\r
858  reset:\r
859 \r
860   /* We do not send resets in response to resets. */\r
861   if(BUF->flags & TCP_RST) \r
862     goto drop;\r
863 \r
864   UIP_STAT(++uip_stat.tcp.rst);\r
865   \r
866   BUF->flags = TCP_RST | TCP_ACK;\r
867   uip_len = 40;\r
868   BUF->tcpoffset = 5 << 4;\r
869 \r
870   /* Flip the seqno and ackno fields in the TCP header. */\r
871   c = BUF->seqno[3];\r
872   BUF->seqno[3] = BUF->ackno[3];  \r
873   BUF->ackno[3] = c;\r
874   \r
875   c = BUF->seqno[2];\r
876   BUF->seqno[2] = BUF->ackno[2];  \r
877   BUF->ackno[2] = c;\r
878   \r
879   c = BUF->seqno[1];\r
880   BUF->seqno[1] = BUF->ackno[1];\r
881   BUF->ackno[1] = c;\r
882   \r
883   c = BUF->seqno[0];\r
884   BUF->seqno[0] = BUF->ackno[0];  \r
885   BUF->ackno[0] = c;\r
886 \r
887   /* We also have to increase the sequence number we are\r
888      acknowledging. If the least significant byte overflowed, we need\r
889      to propagate the carry to the other bytes as well. */\r
890   if(++BUF->ackno[3] == 0) {\r
891     if(++BUF->ackno[2] == 0) {\r
892       if(++BUF->ackno[1] == 0) {\r
893         ++BUF->ackno[0];\r
894       }\r
895     }\r
896   }\r
897  \r
898   /* Swap port numbers. */\r
899   tmp16 = BUF->srcport;\r
900   BUF->srcport = BUF->destport;\r
901   BUF->destport = tmp16;\r
902   \r
903   /* Swap IP addresses. */\r
904   tmp16 = BUF->destipaddr[0];\r
905   BUF->destipaddr[0] = BUF->srcipaddr[0];\r
906   BUF->srcipaddr[0] = tmp16;\r
907   tmp16 = BUF->destipaddr[1];\r
908   BUF->destipaddr[1] = BUF->srcipaddr[1];\r
909   BUF->srcipaddr[1] = tmp16;\r
910 \r
911   \r
912   /* And send out the RST packet! */\r
913   goto tcp_send_noconn;\r
914 \r
915   /* This label will be jumped to if we matched the incoming packet\r
916      with a connection in LISTEN. In that case, we should create a new\r
917      connection and send a SYNACK in return. */\r
918  found_listen:\r
919   /* First we check if there are any connections avaliable. Unused\r
920      connections are kept in the same table as used connections, but\r
921      unused ones have the tcpstate set to CLOSED. Also, connections in\r
922      TIME_WAIT are kept track of and we'll use the oldest one if no\r
923      CLOSED connections are found. Thanks to Eddie C. Dost for a very\r
924      nice algorithm for the TIME_WAIT search. */\r
925   uip_connr = 0;\r
926   for(c = 0; c < UIP_CONNS; ++c) {\r
927     if(uip_conns[c].tcpstateflags == CLOSED) {\r
928       uip_connr = &uip_conns[c];\r
929       break;\r
930     }\r
931     if(uip_conns[c].tcpstateflags == TIME_WAIT) {\r
932       if(uip_connr == 0 ||\r
933          uip_conns[c].timer > uip_connr->timer) {\r
934         uip_connr = &uip_conns[c];\r
935       }\r
936     }\r
937   }\r
938 \r
939   if(uip_connr == 0) {\r
940     /* All connections are used already, we drop packet and hope that\r
941        the remote end will retransmit the packet at a time when we\r
942        have more spare connections. */\r
943     UIP_STAT(++uip_stat.tcp.syndrop);\r
944     UIP_LOG("tcp: found no unused connections.");\r
945     goto drop;\r
946   }\r
947   uip_conn = uip_connr;\r
948   \r
949   /* Fill in the necessary fields for the new connection. */\r
950   uip_connr->rto = uip_connr->timer = UIP_RTO;\r
951   uip_connr->sa = 0;\r
952   uip_connr->sv = 4;  \r
953   uip_connr->nrtx = 0;\r
954   uip_connr->lport = BUF->destport;\r
955   uip_connr->rport = BUF->srcport;\r
956   uip_connr->ripaddr[0] = BUF->srcipaddr[0];\r
957   uip_connr->ripaddr[1] = BUF->srcipaddr[1];\r
958   uip_connr->tcpstateflags = SYN_RCVD;\r
959 \r
960   uip_connr->snd_nxt[0] = iss[0];\r
961   uip_connr->snd_nxt[1] = iss[1];\r
962   uip_connr->snd_nxt[2] = iss[2];\r
963   uip_connr->snd_nxt[3] = iss[3];\r
964   uip_connr->len = 1;\r
965 \r
966   /* rcv_nxt should be the seqno from the incoming packet + 1. */\r
967   uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
968   uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
969   uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
970   uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
971   uip_add_rcv_nxt(1);\r
972 \r
973   /* Parse the TCP MSS option, if present. */\r
974   if((BUF->tcpoffset & 0xf0) > 0x50) {\r
975     for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
976       opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];\r
977       if(opt == 0x00) {\r
978         /* End of options. */   \r
979         break;\r
980       } else if(opt == 0x01) {\r
981         ++c;\r
982         /* NOP option. */\r
983       } else if(opt == 0x02 &&\r
984                 uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {\r
985         /* An MSS option with the right option length. */       \r
986         tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
987           (u16_t)uip_buf[40 + UIP_LLH_LEN + 3 + c];\r
988         uip_connr->initialmss = uip_connr->mss =\r
989           tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
990         \r
991         /* And we are done processing options. */\r
992         break;\r
993       } else {\r
994         /* All other options have a length field, so that we easily\r
995            can skip past them. */\r
996         if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
997           /* If the length field is zero, the options are malformed\r
998              and we don't process them further. */\r
999           break;\r
1000         }\r
1001         c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1002       }      \r
1003     }\r
1004   }\r
1005   \r
1006   /* Our response will be a SYNACK. */\r
1007 #if UIP_ACTIVE_OPEN\r
1008  tcp_send_synack:\r
1009   BUF->flags = TCP_ACK;    \r
1010   \r
1011  tcp_send_syn:\r
1012   BUF->flags |= TCP_SYN;    \r
1013 #else /* UIP_ACTIVE_OPEN */\r
1014  tcp_send_synack:\r
1015   BUF->flags = TCP_SYN | TCP_ACK;    \r
1016 #endif /* UIP_ACTIVE_OPEN */\r
1017   \r
1018   /* We send out the TCP Maximum Segment Size option with our\r
1019      SYNACK. */\r
1020   BUF->optdata[0] = 2;\r
1021   BUF->optdata[1] = 4;\r
1022   BUF->optdata[2] = (UIP_TCP_MSS) / 256;\r
1023   BUF->optdata[3] = (UIP_TCP_MSS) & 255;\r
1024   uip_len = 44;\r
1025   BUF->tcpoffset = 6 << 4;\r
1026   goto tcp_send;\r
1027 \r
1028   /* This label will be jumped to if we found an active connection. */\r
1029  found:\r
1030   uip_conn = uip_connr;\r
1031   uip_flags = 0;\r
1032 \r
1033   /* We do a very naive form of TCP reset processing; we just accept\r
1034      any RST and kill our connection. We should in fact check if the\r
1035      sequence number of this reset is wihtin our advertised window\r
1036      before we accept the reset. */\r
1037   if(BUF->flags & TCP_RST) {\r
1038     uip_connr->tcpstateflags = CLOSED;\r
1039     UIP_LOG("tcp: got reset, aborting connection.");\r
1040     uip_flags = UIP_ABORT;\r
1041     UIP_APPCALL();\r
1042     goto drop;\r
1043   }      \r
1044   /* Calculated the length of the data, if the application has sent\r
1045      any data to us. */\r
1046   c = (BUF->tcpoffset >> 4) << 2;\r
1047   /* uip_len will contain the length of the actual TCP data. This is\r
1048      calculated by subtracing the length of the TCP header (in\r
1049      c) and the length of the IP header (20 bytes). */\r
1050   uip_len = uip_len - c - 20;\r
1051 \r
1052   /* First, check if the sequence number of the incoming packet is\r
1053      what we're expecting next. If not, we send out an ACK with the\r
1054      correct numbers in. */\r
1055   if(uip_len > 0 &&\r
1056      (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||\r
1057       BUF->seqno[1] != uip_connr->rcv_nxt[1] ||\r
1058       BUF->seqno[2] != uip_connr->rcv_nxt[2] ||\r
1059       BUF->seqno[3] != uip_connr->rcv_nxt[3])) {\r
1060     goto tcp_send_ack;\r
1061   }\r
1062 \r
1063   /* Next, check if the incoming segment acknowledges any outstanding\r
1064      data. If so, we update the sequence number, reset the length of\r
1065      the outstanding data, calculate RTT estimations, and reset the\r
1066      retransmission timer. */\r
1067   if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {\r
1068     uip_add32(uip_connr->snd_nxt, uip_connr->len);\r
1069     if(BUF->ackno[0] == uip_acc32[0] &&\r
1070        BUF->ackno[1] == uip_acc32[1] &&\r
1071        BUF->ackno[2] == uip_acc32[2] &&\r
1072        BUF->ackno[3] == uip_acc32[3]) {\r
1073       /* Update sequence number. */\r
1074       uip_connr->snd_nxt[0] = uip_acc32[0];\r
1075       uip_connr->snd_nxt[1] = uip_acc32[1];\r
1076       uip_connr->snd_nxt[2] = uip_acc32[2];\r
1077       uip_connr->snd_nxt[3] = uip_acc32[3];\r
1078         \r
1079 \r
1080       /* Do RTT estimation, unless we have done retransmissions. */\r
1081       if(uip_connr->nrtx == 0) {\r
1082         signed char m;\r
1083         m = uip_connr->rto - uip_connr->timer;\r
1084         /* This is taken directly from VJs original code in his paper */\r
1085         m = m - (uip_connr->sa >> 3);\r
1086         uip_connr->sa += m;\r
1087         if(m < 0) {\r
1088           m = -m;\r
1089         }\r
1090         m = m - (uip_connr->sv >> 2);\r
1091         uip_connr->sv += m;\r
1092         uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;\r
1093 \r
1094       }\r
1095       /* Set the acknowledged flag. */\r
1096       uip_flags = UIP_ACKDATA;\r
1097       /* Reset the retransmission timer. */\r
1098       uip_connr->timer = uip_connr->rto;\r
1099     }\r
1100     \r
1101   }\r
1102 \r
1103   /* Do different things depending on in what state the connection is. */\r
1104   switch(uip_connr->tcpstateflags & TS_MASK) {\r
1105     /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not\r
1106         implemented, since we force the application to close when the\r
1107         peer sends a FIN (hence the application goes directly from\r
1108         ESTABLISHED to LAST_ACK). */\r
1109   case SYN_RCVD:\r
1110     /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and\r
1111        we are waiting for an ACK that acknowledges the data we sent\r
1112        out the last time. Therefore, we want to have the UIP_ACKDATA\r
1113        flag set. If so, we enter the ESTABLISHED state. */\r
1114     if(uip_flags & UIP_ACKDATA) {\r
1115       uip_connr->tcpstateflags = ESTABLISHED;\r
1116       uip_flags = UIP_CONNECTED;\r
1117       uip_connr->len = 0;\r
1118       if(uip_len > 0) {\r
1119         uip_flags |= UIP_NEWDATA;\r
1120         uip_add_rcv_nxt(uip_len);\r
1121       }\r
1122       uip_slen = 0;\r
1123       UIP_APPCALL();\r
1124       goto appsend;\r
1125     }\r
1126     goto drop;\r
1127 #if UIP_ACTIVE_OPEN\r
1128   case SYN_SENT:\r
1129     /* In SYN_SENT, we wait for a SYNACK that is sent in response to\r
1130        our SYN. The rcv_nxt is set to sequence number in the SYNACK\r
1131        plus one, and we send an ACK. We move into the ESTABLISHED\r
1132        state. */\r
1133     if((uip_flags & UIP_ACKDATA) &&\r
1134        BUF->flags == (TCP_SYN | TCP_ACK)) {\r
1135 \r
1136       /* Parse the TCP MSS option, if present. */\r
1137       if((BUF->tcpoffset & 0xf0) > 0x50) {\r
1138         for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {\r
1139           opt = uip_buf[40 + UIP_LLH_LEN + c];\r
1140           if(opt == 0x00) {\r
1141             /* End of options. */       \r
1142             break;\r
1143           } else if(opt == 0x01) {\r
1144             ++c;\r
1145             /* NOP option. */\r
1146           } else if(opt == 0x02 &&\r
1147                     uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {\r
1148             /* An MSS option with the right option length. */\r
1149             tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |\r
1150               uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];\r
1151             uip_connr->initialmss =\r
1152               uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;\r
1153 \r
1154             /* And we are done processing options. */\r
1155             break;\r
1156           } else {\r
1157             /* All other options have a length field, so that we easily\r
1158                can skip past them. */\r
1159             if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {\r
1160               /* If the length field is zero, the options are malformed\r
1161                  and we don't process them further. */\r
1162               break;\r
1163             }\r
1164             c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];\r
1165           }      \r
1166         }\r
1167       }\r
1168       uip_connr->tcpstateflags = ESTABLISHED;      \r
1169       uip_connr->rcv_nxt[0] = BUF->seqno[0];\r
1170       uip_connr->rcv_nxt[1] = BUF->seqno[1];\r
1171       uip_connr->rcv_nxt[2] = BUF->seqno[2];\r
1172       uip_connr->rcv_nxt[3] = BUF->seqno[3];\r
1173       uip_add_rcv_nxt(1);\r
1174       uip_flags = UIP_CONNECTED | UIP_NEWDATA;\r
1175       uip_connr->len = 0;\r
1176       uip_len = 0;\r
1177       uip_slen = 0;\r
1178       UIP_APPCALL();\r
1179       goto appsend;\r
1180     }\r
1181     goto reset;\r
1182 #endif /* UIP_ACTIVE_OPEN */\r
1183     \r
1184   case ESTABLISHED:\r
1185     /* In the ESTABLISHED state, we call upon the application to feed\r
1186     data into the uip_buf. If the UIP_ACKDATA flag is set, the\r
1187     application should put new data into the buffer, otherwise we are\r
1188     retransmitting an old segment, and the application should put that\r
1189     data into the buffer.\r
1190 \r
1191     If the incoming packet is a FIN, we should close the connection on\r
1192     this side as well, and we send out a FIN and enter the LAST_ACK\r
1193     state. We require that there is no outstanding data; otherwise the\r
1194     sequence numbers will be screwed up. */\r
1195 \r
1196     if(BUF->flags & TCP_FIN) {\r
1197       if(uip_outstanding(uip_connr)) {\r
1198         goto drop;\r
1199       }\r
1200       uip_add_rcv_nxt(1 + uip_len);      \r
1201       uip_flags = UIP_CLOSE;\r
1202       if(uip_len > 0) {\r
1203         uip_flags |= UIP_NEWDATA;\r
1204       }\r
1205       UIP_APPCALL();\r
1206       uip_connr->len = 1;\r
1207       uip_connr->tcpstateflags = LAST_ACK;\r
1208       uip_connr->nrtx = 0;\r
1209     tcp_send_finack:\r
1210       BUF->flags = TCP_FIN | TCP_ACK;      \r
1211       goto tcp_send_nodata;\r
1212     }\r
1213 \r
1214     /* Check the URG flag. If this is set, the segment carries urgent\r
1215        data that we must pass to the application. */\r
1216     if(BUF->flags & TCP_URG) {\r
1217 #if UIP_URGDATA > 0\r
1218       uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1219       if(uip_urglen > uip_len) {\r
1220         /* There is more urgent data in the next segment to come. */\r
1221         uip_urglen = uip_len;\r
1222       }\r
1223       uip_add_rcv_nxt(uip_urglen);\r
1224       uip_len -= uip_urglen;\r
1225       uip_urgdata = uip_appdata;\r
1226       uip_appdata += uip_urglen;\r
1227     } else {\r
1228       uip_urglen = 0;\r
1229 #endif /* UIP_URGDATA > 0 */\r
1230       uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1231       uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];\r
1232     }\r
1233     \r
1234     \r
1235     /* If uip_len > 0 we have TCP data in the packet, and we flag this\r
1236        by setting the UIP_NEWDATA flag and update the sequence number\r
1237        we acknowledge. If the application has stopped the dataflow\r
1238        using uip_stop(), we must not accept any data packets from the\r
1239        remote host. */\r
1240     if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {\r
1241       uip_flags |= UIP_NEWDATA;\r
1242       uip_add_rcv_nxt(uip_len);\r
1243     }\r
1244 \r
1245     /* Check if the available buffer space advertised by the other end\r
1246        is smaller than the initial MSS for this connection. If so, we\r
1247        set the current MSS to the window size to ensure that the\r
1248        application does not send more data than the other end can\r
1249        handle.\r
1250 \r
1251        If the remote host advertises a zero window, we set the MSS to\r
1252        the initial MSS so that the application will send an entire MSS\r
1253        of data. This data will not be acknowledged by the receiver,\r
1254        and the application will retransmit it. This is called the\r
1255        "persistent timer" and uses the retransmission mechanim.\r
1256     */\r
1257     tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];\r
1258     if(tmp16 > uip_connr->initialmss ||\r
1259        tmp16 == 0) {\r
1260       tmp16 = uip_connr->initialmss;\r
1261     }\r
1262     uip_connr->mss = tmp16;\r
1263 \r
1264     /* If this packet constitutes an ACK for outstanding data (flagged\r
1265        by the UIP_ACKDATA flag, we should call the application since it\r
1266        might want to send more data. If the incoming packet had data\r
1267        from the peer (as flagged by the UIP_NEWDATA flag), the\r
1268        application must also be notified.\r
1269 \r
1270        When the application is called, the global variable uip_len\r
1271        contains the length of the incoming data. The application can\r
1272        access the incoming data through the global pointer\r
1273        uip_appdata, which usually points 40 bytes into the uip_buf\r
1274        array.\r
1275 \r
1276        If the application wishes to send any data, this data should be\r
1277        put into the uip_appdata and the length of the data should be\r
1278        put into uip_len. If the application don't have any data to\r
1279        send, uip_len must be set to 0. */\r
1280     if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {\r
1281       uip_slen = 0;\r
1282       UIP_APPCALL();\r
1283 \r
1284     appsend:\r
1285       \r
1286       if(uip_flags & UIP_ABORT) {\r
1287         uip_slen = 0;\r
1288         uip_connr->tcpstateflags = CLOSED;\r
1289         BUF->flags = TCP_RST | TCP_ACK;\r
1290         goto tcp_send_nodata;\r
1291       }\r
1292 \r
1293       if(uip_flags & UIP_CLOSE) {\r
1294         uip_slen = 0;\r
1295         uip_connr->len = 1;\r
1296         uip_connr->tcpstateflags = FIN_WAIT_1;\r
1297         uip_connr->nrtx = 0;\r
1298         BUF->flags = TCP_FIN | TCP_ACK;\r
1299         goto tcp_send_nodata;   \r
1300       }\r
1301 \r
1302       /* If uip_slen > 0, the application has data to be sent. */\r
1303       if(uip_slen > 0) {\r
1304 \r
1305         /* If the connection has acknowledged data, the contents of\r
1306            the ->len variable should be discarded. */ \r
1307         if((uip_flags & UIP_ACKDATA) != 0) {\r
1308           uip_connr->len = 0;\r
1309         }\r
1310 \r
1311         /* If the ->len variable is non-zero the connection has\r
1312            already data in transit and cannot send anymore right\r
1313            now. */\r
1314         if(uip_connr->len == 0) {\r
1315 \r
1316           /* The application cannot send more than what is allowed by\r
1317              the mss (the minumum of the MSS and the available\r
1318              window). */\r
1319           if(uip_slen > uip_connr->mss) {\r
1320             uip_slen = uip_connr->mss;\r
1321           }\r
1322 \r
1323           /* Remember how much data we send out now so that we know\r
1324              when everything has been acknowledged. */\r
1325           uip_connr->len = uip_slen;\r
1326         } else {\r
1327 \r
1328           /* If the application already had unacknowledged data, we\r
1329              make sure that the application does not send (i.e.,\r
1330              retransmit) out more than it previously sent out. */\r
1331           uip_slen = uip_connr->len;\r
1332         }\r
1333       } else {\r
1334         uip_connr->len = 0;\r
1335       }\r
1336       uip_connr->nrtx = 0;\r
1337     apprexmit:\r
1338       uip_appdata = uip_sappdata;\r
1339       \r
1340       /* If the application has data to be sent, or if the incoming\r
1341          packet had new data in it, we must send out a packet. */\r
1342       if(uip_slen > 0 && uip_connr->len > 0) {\r
1343         /* Add the length of the IP and TCP headers. */\r
1344         uip_len = uip_connr->len + UIP_TCPIP_HLEN;\r
1345         /* We always set the ACK flag in response packets. */\r
1346         BUF->flags = TCP_ACK | TCP_PSH;\r
1347         /* Send the packet. */\r
1348         goto tcp_send_noopts;\r
1349       }\r
1350       /* If there is no data to send, just send out a pure ACK if\r
1351          there is newdata. */\r
1352       if(uip_flags & UIP_NEWDATA) {\r
1353         uip_len = UIP_TCPIP_HLEN;\r
1354         BUF->flags = TCP_ACK;\r
1355         goto tcp_send_noopts;\r
1356       }\r
1357     }\r
1358     goto drop;\r
1359   case LAST_ACK:\r
1360     /* We can close this connection if the peer has acknowledged our\r
1361        FIN. This is indicated by the UIP_ACKDATA flag. */     \r
1362     if(uip_flags & UIP_ACKDATA) {\r
1363       uip_connr->tcpstateflags = CLOSED;\r
1364       uip_flags = UIP_CLOSE;\r
1365       UIP_APPCALL();\r
1366     }\r
1367     break;\r
1368     \r
1369   case FIN_WAIT_1:\r
1370     /* The application has closed the connection, but the remote host\r
1371        hasn't closed its end yet. Thus we do nothing but wait for a\r
1372        FIN from the other side. */\r
1373     if(uip_len > 0) {\r
1374       uip_add_rcv_nxt(uip_len);\r
1375     }\r
1376     if(BUF->flags & TCP_FIN) {\r
1377       if(uip_flags & UIP_ACKDATA) {\r
1378         uip_connr->tcpstateflags = TIME_WAIT;\r
1379         uip_connr->timer = 0;\r
1380         uip_connr->len = 0;\r
1381       } else {\r
1382         uip_connr->tcpstateflags = CLOSING;\r
1383       }\r
1384       uip_add_rcv_nxt(1);\r
1385       uip_flags = UIP_CLOSE;\r
1386       UIP_APPCALL();\r
1387       goto tcp_send_ack;\r
1388     } else if(uip_flags & UIP_ACKDATA) {\r
1389       uip_connr->tcpstateflags = FIN_WAIT_2;\r
1390       uip_connr->len = 0;\r
1391       goto drop;\r
1392     }\r
1393     if(uip_len > 0) {\r
1394       goto tcp_send_ack;\r
1395     }\r
1396     goto drop;\r
1397       \r
1398   case FIN_WAIT_2:\r
1399     if(uip_len > 0) {\r
1400       uip_add_rcv_nxt(uip_len);\r
1401     }\r
1402     if(BUF->flags & TCP_FIN) {\r
1403       uip_connr->tcpstateflags = TIME_WAIT;\r
1404       uip_connr->timer = 0;\r
1405       uip_add_rcv_nxt(1);\r
1406       uip_flags = UIP_CLOSE;\r
1407       UIP_APPCALL();\r
1408       goto tcp_send_ack;\r
1409     }\r
1410     if(uip_len > 0) {\r
1411       goto tcp_send_ack;\r
1412     }\r
1413     goto drop;\r
1414 \r
1415   case TIME_WAIT:\r
1416     goto tcp_send_ack;\r
1417     \r
1418   case CLOSING:\r
1419     if(uip_flags & UIP_ACKDATA) {\r
1420       uip_connr->tcpstateflags = TIME_WAIT;\r
1421       uip_connr->timer = 0;\r
1422     }\r
1423   }  \r
1424   goto drop;\r
1425   \r
1426 \r
1427   /* We jump here when we are ready to send the packet, and just want\r
1428      to set the appropriate TCP sequence numbers in the TCP header. */\r
1429  tcp_send_ack:\r
1430   BUF->flags = TCP_ACK;\r
1431  tcp_send_nodata:\r
1432   uip_len = 40;\r
1433  tcp_send_noopts:\r
1434   BUF->tcpoffset = 5 << 4;\r
1435  tcp_send:\r
1436   /* We're done with the input processing. We are now ready to send a\r
1437      reply. Our job is to fill in all the fields of the TCP and IP\r
1438      headers before calculating the checksum and finally send the\r
1439      packet. */\r
1440   BUF->ackno[0] = uip_connr->rcv_nxt[0];\r
1441   BUF->ackno[1] = uip_connr->rcv_nxt[1];\r
1442   BUF->ackno[2] = uip_connr->rcv_nxt[2];\r
1443   BUF->ackno[3] = uip_connr->rcv_nxt[3];\r
1444   \r
1445   BUF->seqno[0] = uip_connr->snd_nxt[0];\r
1446   BUF->seqno[1] = uip_connr->snd_nxt[1];\r
1447   BUF->seqno[2] = uip_connr->snd_nxt[2];\r
1448   BUF->seqno[3] = uip_connr->snd_nxt[3];\r
1449 \r
1450   BUF->proto = UIP_PROTO_TCP;\r
1451   \r
1452   BUF->srcport  = uip_connr->lport;\r
1453   BUF->destport = uip_connr->rport;\r
1454 \r
1455   BUF->srcipaddr[0] = uip_hostaddr[0];\r
1456   BUF->srcipaddr[1] = uip_hostaddr[1];\r
1457   BUF->destipaddr[0] = uip_connr->ripaddr[0];\r
1458   BUF->destipaddr[1] = uip_connr->ripaddr[1];\r
1459  \r
1460 \r
1461   if(uip_connr->tcpstateflags & UIP_STOPPED) {\r
1462     /* If the connection has issued uip_stop(), we advertise a zero\r
1463        window so that the remote host will stop sending data. */\r
1464     BUF->wnd[0] = BUF->wnd[1] = 0;\r
1465   } else {\r
1466     BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);\r
1467     BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); \r
1468   }\r
1469 \r
1470  tcp_send_noconn:\r
1471 \r
1472   BUF->len[0] = (uip_len >> 8);\r
1473   BUF->len[1] = (uip_len & 0xff);\r
1474 \r
1475   /* Calculate TCP checksum. */\r
1476   BUF->tcpchksum = 0;\r
1477   BUF->tcpchksum = ~(uip_tcpchksum());\r
1478   \r
1479  ip_send_nolen:\r
1480 \r
1481   BUF->vhl = 0x45;\r
1482   BUF->tos = 0;\r
1483   BUF->ipoffset[0] = BUF->ipoffset[1] = 0;\r
1484   BUF->ttl  = UIP_TTL;\r
1485   ++ipid;\r
1486   BUF->ipid[0] = ipid >> 8;\r
1487   BUF->ipid[1] = ipid & 0xff;\r
1488   \r
1489   /* Calculate IP checksum. */\r
1490   BUF->ipchksum = 0;\r
1491   BUF->ipchksum = ~(uip_ipchksum());\r
1492 \r
1493   UIP_STAT(++uip_stat.tcp.sent);\r
1494  send:\r
1495   UIP_STAT(++uip_stat.ip.sent);\r
1496   /* Return and let the caller do the actual transmission. */\r
1497   return;\r
1498  drop:\r
1499   uip_len = 0;\r
1500   return;\r
1501 }\r
1502 /*-----------------------------------------------------------------------------------*/\r
1503 u16_t\r
1504 htons(u16_t val)\r
1505 {\r
1506   return HTONS(val);\r
1507 }\r
1508 /*-----------------------------------------------------------------------------------*/\r
1509 /** @} */\r