uIP 1.0
C:/asm/STM32-ethernet/ENC28J60prj/uip-master/uip/uip.c
См. документацию.
00001 #define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/
00002 
00003 /**
00004  * \defgroup uip The uIP TCP/IP stack
00005  * @{
00006  *
00007  * uIP является реализацией стека протоколов TCP/IP, предназначенной
00008  * для маленьких 8-битных и 16-битных микроконтроллеров.
00009  *
00010  * uIP предоставляет протоколы, необходимые для обмена данными через
00011  * сеть Internet, с очень малым размером кода и низкими требованиями
00012  * к объему RAM - размер кода uIP составляет порядка нескольких килобайт,
00013  * и количество задействованной памяти RAM составляет несколько сотен
00014  * байт.
00015  */
00016 
00017 /**
00018  * \file
00019  * Код стека uIP TCP/IP.
00020  * \author Adam Dunkels <adam@dunkels.com>
00021  */
00022 
00023 /*
00024  * Copyright (c) 2001-2003, Adam Dunkels.
00025  * Все права зарезервированы. *
00026  * Повторное распространение, использование в исходном и двоичном виде,
00027  * с модификацией или без - разрешается, если выполняются следующие
00028  * условия:
00029  * 1. Распространение исходного кода должно сохранить вышеуказанную пометку
00030  *    копирайта, этот список условий и следующую правовую оговорку.
00031  * 2. Распространение исходного кода должно сохранить вышеуказанную пометку
00032  *    копирайта, этот список условий и следующую правовую оговорку в
00033  *    документации и/или других материалах, которые будут предоставлены
00034  *    вместе с распространяемыми материалами.
00035  * 3. Имя автора не может использоваться, чтобы подтвердить или продвинуть
00036  *    продукты, написанные с использованием этого программного обеспечения
00037  *    без специального на то разрешения.
00038  *
00039  * ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ АВТОРОМ ``КАК ЕСТЬ'', БЕЗ
00040  * КАКОЙ-ЛИБО ЛЮБОЙ РАСШИРЕННОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ГАРАНТИИ, ВКЛЮЧАЯ,
00041  * НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ГАРАНТИИ ВЫСОКОГО СПРОСА И ПРИГОДНОСТИ
00042  * ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. АВТОР НИ ПРИ КАКИХ УСЛОВИЯХ НЕ ОТВЕТСТВЕНЕН
00043  * ЗА ЛЮБЫЕ УБЫТКИ - ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ОБРАЗЦОВЫЕ
00044  * ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ТРЕБОВАНИЯ
00045  * ЗАМЕНЫ ТОВАРА ИЛИ СЕРВИСА; ПОТЕРИ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ВЫГОДЫ;
00046  * ИЛИ ПРЕКРАЩЕНИЕ БИЗНЕСА), ОДНАКО ВЫЗВАННЫЕ ПО ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ,
00047  * ЛИБО В КОНТРАКТЕ, ПРЯМОЙ ОТВЕТСТВЕННОСТИ, ЛИБО В НАРУШЕНИИ ЗАКОННЫХ ПРАВ
00048  * (ВКЛЮЧАЯ ТАК ИЛИ ИНАЧЕ НЕБРЕЖНОСТЬ), ВОЗНИКАЮЩИЕ ВСЕГДА ИЗ ИСПОЛЬЗОВАНИЯ
00049  * ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ
00050  * ТАКОГО ПОВРЕЖДЕНИЯ.
00051  *
00052  * Этот файл является частью стека uIP TCP/IP.
00053  *
00054  * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
00055  *
00056  */
00057 
00058 /*
00059  * uIP является малой реализацеий протоколов IP, UDP и TCP (а также
00060  * базовой части ICMP). Реализаци слоев IP, UDP, TCP и слоя приложения
00061  * очень тесно взаимосвязаны. Чтобы снизить размер компилируемого кода,
00062  * часто используется оператор goto. Хотя можно было бы разбить uip_process()
00063  * на несколько функций поменьше, это увеличит размер кода на передачу 
00064  * параметров и снижения эффективности работы оптимизации.
00065  *
00066  * Принцип работы состоит в том, что у нас есть маленький буфер uip_buf,
00067  * в который драйвер устройства помещает пришедший пакет. Стек TCP/IP
00068  * делает парсинг заголовков в пакете, и вызывает приложение. Если
00069  * remote host отправил данные приложению, то эти данные представлены
00070  * в буфере uip_buf, и приложение проитает данные оттуда. Также приложение
00071  * при необходимости может поместить туда для передаваемого потока байт. 
00072  * Приложению не будут поставляться данные, которые выпадают из
00073  * последовательности обмена.
00074  *
00075  * Если приложение хочет отправить данные другому участнику обмена 
00076  * (на сторону remote host), то оно должно поместить данные в буфер
00077  * uip_buf. Указатель uip_appdata указывает на первый доступный байт. 
00078  * Стек TCP/IP вычислит контрольные суммы, и заполнит необходимые поля
00079  * заголовка, и затем отправит обратно пакет участнику обмена.
00080 */
00081 
00082 #include "uip.h"
00083 #include "uipopt.h"
00084 #include "uip_arch.h"
00085 
00086 #if UIP_CONF_IPV6
00087 #include "uip-neighbor.h"
00088 #endif /* UIP_CONF_IPV6 */
00089 
00090 #include <string.h>
00091 
00092 /*---------------------------------------------------------------------------*/
00093 /* Определения переменных. */
00094 
00095 
00096 /* Адрес IP для этого хоста. Если он задан как фиксированный (путем
00097    установки UIP_FIXEDADDR на 1 в файле uipopt.h), то адрес будет
00098    установлен здесь в виде констант. Иначе адрес будет задан переменными. */
00099 #if UIP_FIXEDADDR > 0
00100 const uip_ipaddr_t uip_hostaddr =
00101   {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
00102    HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
00103 const uip_ipaddr_t uip_draddr =
00104   {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
00105    HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
00106 const uip_ipaddr_t uip_netmask =
00107   {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
00108    HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
00109 #else
00110 uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
00111 #endif /* UIP_FIXEDADDR */
00112 
00113 static const uip_ipaddr_t all_ones_addr =
00114 #if UIP_CONF_IPV6
00115   {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
00116 #else /* UIP_CONF_IPV6 */
00117   {0xffff,0xffff};
00118 #endif /* UIP_CONF_IPV6 */
00119 static const uip_ipaddr_t all_zeroes_addr =
00120 #if UIP_CONF_IPV6
00121   {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
00122 #else /* UIP_CONF_IPV6 */
00123   {0x0000,0x0000};
00124 #endif /* UIP_CONF_IPV6 */
00125 
00126 
00127 #if UIP_FIXEDETHADDR
00128 const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
00129                                           UIP_ETHADDR1,
00130                                           UIP_ETHADDR2,
00131                                           UIP_ETHADDR3,
00132                                           UIP_ETHADDR4,
00133                                           UIP_ETHADDR5}};
00134 #else
00135 struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
00136 #endif
00137 
00138 #ifndef UIP_CONF_EXTERNAL_BUFFER
00139 u8_t uip_buf[UIP_BUFSIZE + 2];   /* Буфер пакета, который будет содержать
00140                                     поступающие пакеты. */
00141 #endif /* UIP_CONF_EXTERNAL_BUFFER */
00142 
00143 void *uip_appdata;               /* Указатель uip_appdata, указывающий на
00144                                     данные приложения. */
00145 void *uip_sappdata;              /* Указатель uip_sappdata указывает на
00146                                     данные приложения, которые должны быть
00147                                     отправлены. */
00148 #if UIP_URGDATA > 0
00149 void *uip_urgdata;               /* Указатель uip_urgdata указывает на
00150                                     urgent data (out-of-band data), если
00151                                     таковые имеются. */
00152 u16_t uip_urglen, uip_surglen;
00153 #endif /* UIP_URGDATA > 0 */
00154 
00155 u16_t uip_len, uip_slen;
00156                                  /* Переменная uip_len будет 8-или 16-битная,
00157                                     в зависимости от максимального размера
00158                                     пакета. */
00159 
00160 u8_t uip_flags;                  /* Переменная uip_flags, используемая в обмене
00161                                     между стеком TCP/IP и программой приложения. */
00162 struct uip_conn *uip_conn;      /* Переменная uip_conn всегда указывает на
00163                                     текущее соединение. */
00164 
00165 struct uip_conn uip_conns[UIP_CONNS];
00166                                  /* Массив uip_conns содержит все соединения TCP. */
00167 u16_t uip_listenports[UIP_LISTENPORTS];
00168                                  /* Массив uip_listenports содержит список всех
00169                                     прослушиваемых сейчас портов. */
00170 #if UIP_UDP
00171 struct uip_udp_conn *uip_udp_conn;
00172 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
00173 #endif /* UIP_UDP */
00174 
00175 static u16_t ipid;               /* Эта переменная содержит увеличиваемое число,
00176                                      используемое в поле IP ID. */
00177 
00178 void uip_setipid(u16_t id) { ipid = id; }
00179 
00180 static u8_t iss[4];              /* Эта переменная используется для начального номера
00181                                      последовательности TCP. */
00182 
00183 #if UIP_ACTIVE_OPEN
00184 static u16_t lastport;           /* Отслеживает последний порт, используемый для
00185                                      нового соединения. */
00186 #endif /* UIP_ACTIVE_OPEN */
00187 
00188 /* Временные переменные. */
00189 u8_t uip_acc32[4];
00190 static u8_t c, opt;
00191 static u16_t tmp16;
00192 
00193 /* Структуры и определения. */
00194 #define TCP_FIN 0x01
00195 #define TCP_SYN 0x02
00196 #define TCP_RST 0x04
00197 #define TCP_PSH 0x08
00198 #define TCP_ACK 0x10
00199 #define TCP_URG 0x20
00200 #define TCP_CTL 0x3f
00201 
00202 #define TCP_OPT_END     0   /* Конец списка опций TCP */
00203 #define TCP_OPT_NOOP    1   /* Опция TCP "No-operation" (нет операции) */
00204 #define TCP_OPT_MSS     2   /* Опция TCP максимального размера сегмента */
00205 
00206 #define TCP_OPT_MSS_LEN 4   /* Длина опции TCP MSS. */
00207 
00208 #define ICMP_ECHO_REPLY 0
00209 #define ICMP_ECHO       8
00210 
00211 #define ICMP6_ECHO_REPLY             129
00212 #define ICMP6_ECHO                   128
00213 #define ICMP6_NEIGHBOR_SOLICITATION  135
00214 #define ICMP6_NEIGHBOR_ADVERTISEMENT 136
00215 
00216 #define ICMP6_FLAG_S (1 << 6)
00217 
00218 #define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
00219 #define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
00220 
00221 
00222 /* Macros. */
00223 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00224 #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
00225 #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
00226 #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
00227 
00228 
00229 #if UIP_STATISTICS == 1
00230 struct uip_stats uip_stat;
00231 #define UIP_STAT(s) s
00232 #else
00233 #define UIP_STAT(s)
00234 #endif /* UIP_STATISTICS == 1 */
00235 
00236 #if UIP_LOGGING == 1
00237 #include <stdio.h>
00238 void uip_log(char *msg);
00239 #define UIP_LOG(m) uip_log(m)
00240 #else
00241 #define UIP_LOG(m)
00242 #endif /* UIP_LOGGING == 1 */
00243 
00244 #if ! UIP_ARCH_ADD32
00245 void
00246 uip_add32(u8_t *op32, u16_t op16)
00247 {
00248   uip_acc32[3] = op32[3] + (op16 & 0xff);
00249   uip_acc32[2] = op32[2] + (op16 >> 8);
00250   uip_acc32[1] = op32[1];
00251   uip_acc32[0] = op32[0];
00252   
00253   if(uip_acc32[2] < (op16 >> 8)) {
00254     ++uip_acc32[1];
00255     if(uip_acc32[1] == 0) {
00256       ++uip_acc32[0];
00257     }
00258   }
00259   
00260   
00261   if(uip_acc32[3] < (op16 & 0xff)) {
00262     ++uip_acc32[2];
00263     if(uip_acc32[2] == 0) {
00264       ++uip_acc32[1];
00265       if(uip_acc32[1] == 0) {
00266         ++uip_acc32[0];
00267       }
00268     }
00269   }
00270 }
00271 
00272 #endif /* UIP_ARCH_ADD32 */
00273 
00274 #if ! UIP_ARCH_CHKSUM
00275 /*---------------------------------------------------------------------------*/
00276 static u16_t
00277 chksum(u16_t sum, const u8_t *data, u16_t len)
00278 {
00279   u16_t t;
00280   const u8_t *dataptr;
00281   const u8_t *last_byte;
00282 
00283   dataptr = data;
00284   last_byte = data + len - 1;
00285   
00286   while(dataptr < last_byte) {   /* Еще по крайней мере два байта */
00287     t = (dataptr[0] << 8) + dataptr[1];
00288     sum += t;
00289     if(sum < t) {
00290       sum++;                     /* перенос */
00291     }
00292     dataptr += 2;
00293   }
00294   
00295   if(dataptr == last_byte) {
00296     t = (dataptr[0] << 8) + 0;
00297     sum += t;
00298     if(sum < t) {
00299       sum++;                     /* перенос */
00300     }
00301   }
00302 
00303   /* Возврат суммы, где порядок байт как у хоста. */
00304   return sum;
00305 }
00306 /*---------------------------------------------------------------------------*/
00307 u16_t
00308 uip_chksum(u16_t *data, u16_t len)
00309 {
00310   return htons(chksum(0, (u8_t *)data, len));
00311 }
00312 /*---------------------------------------------------------------------------*/
00313 #ifndef UIP_ARCH_IPCHKSUM
00314 u16_t
00315 uip_ipchksum(void)
00316 {
00317   u16_t sum;
00318 
00319   sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
00320   DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
00321   return (sum == 0) ? 0xffff : htons(sum);
00322 }
00323 #endif
00324 /*---------------------------------------------------------------------------*/
00325 static u16_t
00326 upper_layer_chksum(u8_t proto)
00327 {
00328   u16_t upper_layer_len;
00329   u16_t sum;
00330   
00331 #if UIP_CONF_IPV6
00332   upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
00333 #else /* UIP_CONF_IPV6 */
00334   upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
00335 #endif /* UIP_CONF_IPV6 */
00336   
00337   /* Первый псевдозаголовок суммы. */
00338   
00339   /* Поля протокола IP и длины. В этом месте добавление без переноса. */
00340   sum = upper_layer_len + proto;
00341   /* Сумма адресов IP source и IP destination. */
00342   sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
00343 
00344   /* Sum TCP header and data. */
00345   sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
00346                upper_layer_len);
00347     
00348   return (sum == 0) ? 0xffff : htons(sum);
00349 }
00350 /*---------------------------------------------------------------------------*/
00351 #if UIP_CONF_IPV6
00352 u16_t
00353 uip_icmp6chksum(void)
00354 {
00355   return upper_layer_chksum(UIP_PROTO_ICMP6);
00356   
00357 }
00358 #endif /* UIP_CONF_IPV6 */
00359 /*---------------------------------------------------------------------------*/
00360 u16_t
00361 uip_tcpchksum(void)
00362 {
00363   return upper_layer_chksum(UIP_PROTO_TCP);
00364 }
00365 /*---------------------------------------------------------------------------*/
00366 #if UIP_UDP_CHECKSUMS
00367 u16_t
00368 uip_udpchksum(void)
00369 {
00370   return upper_layer_chksum(UIP_PROTO_UDP);
00371 }
00372 #endif /* UIP_UDP_CHECKSUMS */
00373 #endif /* UIP_ARCH_CHKSUM */
00374 /*---------------------------------------------------------------------------*/
00375 void
00376 uip_init(void)
00377 {
00378   for(c = 0; c < UIP_LISTENPORTS; ++c) {
00379     uip_listenports[c] = 0;
00380   }
00381   for(c = 0; c < UIP_CONNS; ++c) {
00382     uip_conns[c].tcpstateflags = UIP_CLOSED;
00383   }
00384 #if UIP_ACTIVE_OPEN
00385   lastport = 1024;
00386 #endif /* UIP_ACTIVE_OPEN */
00387 
00388 #if UIP_UDP
00389   for(c = 0; c < UIP_UDP_CONNS; ++c) {
00390     uip_udp_conns[c].lport = 0;
00391   }
00392 #endif /* UIP_UDP */
00393   
00394 
00395   /* Инициализация IPv4. */
00396 #if UIP_FIXEDADDR == 0
00397   /*  uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
00398 #endif /* UIP_FIXEDADDR */
00399 
00400 }
00401 /*---------------------------------------------------------------------------*/
00402 #if UIP_ACTIVE_OPEN
00403 struct uip_conn *
00404 uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
00405 {
00406   register struct uip_conn *conn, *cconn;
00407   
00408   /* Поиск неиспользуемого локального порта. */
00409  again:
00410   ++lastport;
00411 
00412   if(lastport >= 32000) {
00413     lastport = 4096;
00414   }
00415 
00416   /* Проверка: этот порт уже используется? Если так, то попытка
00417      найти другой. */
00418   for(c = 0; c < UIP_CONNS; ++c) {
00419     conn = &uip_conns[c];
00420     if(conn->tcpstateflags != UIP_CLOSED &&
00421        conn->lport == htons(lastport)) {
00422       goto again;
00423     }
00424   }
00425 
00426   conn = 0;
00427   for(c = 0; c < UIP_CONNS; ++c) {
00428     cconn = &uip_conns[c];
00429     if(cconn->tcpstateflags == UIP_CLOSED) {
00430       conn = cconn;
00431       break;
00432     }
00433     if(cconn->tcpstateflags == UIP_TIME_WAIT) {
00434       if(conn == 0 ||
00435          cconn->timer > conn->timer) {
00436          conn = cconn;
00437       }
00438     }
00439   }
00440 
00441   if(conn == 0) {
00442     return 0;
00443   }
00444   
00445   conn->tcpstateflags = UIP_SYN_SENT;
00446 
00447   conn->snd_nxt[0] = iss[0];
00448   conn->snd_nxt[1] = iss[1];
00449   conn->snd_nxt[2] = iss[2];
00450   conn->snd_nxt[3] = iss[3];
00451 
00452   conn->initialmss = conn->mss = UIP_TCP_MSS;
00453   
00454   conn->len = 1;   /* Длина TCP для SYN равна 1. */
00455   conn->nrtx = 0;
00456   conn->timer = 1; /* SYN будет отправлен в следующий раз. */
00457   conn->rto = UIP_RTO;
00458   conn->sa = 0;
00459   conn->sv = 16;   /* Начальное значение для вариации RTT. */
00460   conn->lport = htons(lastport);
00461   conn->rport = rport;
00462   uip_ipaddr_copy(&conn->ripaddr, ripaddr);
00463   
00464   return conn;
00465 }
00466 #endif /* UIP_ACTIVE_OPEN */
00467 /*---------------------------------------------------------------------------*/
00468 #if UIP_UDP
00469 struct uip_udp_conn *
00470 uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
00471 {
00472   register struct uip_udp_conn *conn;
00473   
00474   /* Поиск неиспользуемого локального порта. */
00475  again:
00476   ++lastport;
00477 
00478   if(lastport >= 32000) {
00479     lastport = 4096;
00480   }
00481   
00482   for(c = 0; c < UIP_UDP_CONNS; ++c) {
00483     if(uip_udp_conns[c].lport == htons(lastport)) {
00484       goto again;
00485     }
00486   }
00487 
00488 
00489   conn = 0;
00490   for(c = 0; c < UIP_UDP_CONNS; ++c) {
00491     if(uip_udp_conns[c].lport == 0) {
00492       conn = &uip_udp_conns[c];
00493       break;
00494     }
00495   }
00496 
00497   if(conn == 0) {
00498     return 0;
00499   }
00500   
00501   conn->lport = HTONS(lastport);
00502   conn->rport = rport;
00503   if(ripaddr == NULL) {
00504     memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
00505   } else {
00506     uip_ipaddr_copy(&conn->ripaddr, ripaddr);
00507   }
00508   conn->ttl = UIP_TTL;
00509   
00510   return conn;
00511 }
00512 #endif /* UIP_UDP */
00513 /*---------------------------------------------------------------------------*/
00514 void
00515 uip_unlisten(u16_t port)
00516 {
00517   for(c = 0; c < UIP_LISTENPORTS; ++c) {
00518     if(uip_listenports[c] == port) {
00519       uip_listenports[c] = 0;
00520       return;
00521     }
00522   }
00523 }
00524 /*---------------------------------------------------------------------------*/
00525 void
00526 uip_listen(u16_t port)
00527 {
00528   for(c = 0; c < UIP_LISTENPORTS; ++c) {
00529     if(uip_listenports[c] == 0) {
00530       uip_listenports[c] = port;
00531       return;
00532     }
00533   }
00534 }
00535 /*---------------------------------------------------------------------------*/
00536 /* XXX: пересборка фрагментации IP: протестировано не очень хорошо. */
00537 
00538 #if UIP_REASSEMBLY && !UIP_CONF_IPV6
00539 #define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
00540 static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
00541 static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
00542 static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
00543                                      0x0f, 0x07, 0x03, 0x01};
00544 static u16_t uip_reasslen;
00545 static u8_t uip_reassflags;
00546 #define UIP_REASS_FLAG_LASTFRAG 0x01
00547 static u8_t uip_reasstmr;
00548 
00549 #define IP_MF   0x20
00550 
00551 static u8_t
00552 uip_reass(void)
00553 {
00554   u16_t offset, len;
00555   u16_t i;
00556 
00557   /* Если ip_reasstmr равен 0, то в буфере нет пакета, поэтому
00558      запишем заголовок IP фрагмента в буфер пересборки.
00559      Таймер обновляестя на максимальное время. */
00560   if(uip_reasstmr == 0) {
00561     memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
00562     uip_reasstmr = UIP_REASS_MAXAGE;
00563     uip_reassflags = 0;
00564     /* Очистка битовой карты. */
00565     memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
00566   }
00567 
00568   /* Проверка - соответствует ли входящий фрагмент текущему фрагменту,
00569      находящемуся в буфере пересборки. Если это так, то фрагмент
00570      будет скопирован в буфер. */
00571   if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
00572      BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
00573      BUF->destipaddr[0] == FBUF->destipaddr[0] &&
00574      BUF->destipaddr[1] == FBUF->destipaddr[1] &&
00575      BUF->ipid[0] == FBUF->ipid[0] &&
00576      BUF->ipid[1] == FBUF->ipid[1]) {
00577 
00578     len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
00579     offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
00580 
00581     /* Если смещение или смешщение + длина фрагмента переполняют
00582        буфер пересборки, то отбросим весь пакет. */
00583     if(offset > UIP_REASS_BUFSIZE ||
00584        offset + len > UIP_REASS_BUFSIZE) {
00585       uip_reasstmr = 0;
00586       goto nullreturn;
00587     }
00588 
00589     /* Копирование фрагмента в буфер пересборки, со смещением
00590        вправо. */
00591     memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
00592            (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
00593            len);
00594       
00595     /* Обновление битовой карты. */
00596     if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
00597       /* Если две конечные точки находятся в одном и том же байте,
00598          то будет обновлен только этот байт. */
00599       uip_reassbitmap[offset / (8 * 8)] |=
00600           bitmap_bits[(offset / 8 ) & 7] &
00601          ~bitmap_bits[((offset + len) / 8 ) & 7];
00602     } else {
00603       /* Если две конечные точки находятся в разных байтах, обновим байты
00604          в конечных точках и заполним данные между ними байтами 0xff. */
00605       uip_reassbitmap[offset / (8 * 8)] |=
00606             bitmap_bits[(offset / 8 ) & 7];
00607       for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
00608          uip_reassbitmap[i] = 0xff;
00609       }
00610       uip_reassbitmap[(offset + len) / (8 * 8)] |=
00611             ~bitmap_bits[((offset + len) / 8 ) & 7];
00612     }
00613     
00614     /* Если в этом фрагменте флаг More Fragments равен 0, то мы знаем,
00615        это последний фрагмент, так что можно теперь вычислить размер
00616        всего пакета. Мы также установим флаг IP_REASS_FLAG_LASTFRAG,
00617        чтобы показать, что мы приняли завершающий фрагмент. */
00618 
00619     if((BUF->ipoffset[0] & IP_MF) == 0) {
00620       uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
00621       uip_reasslen = offset + len;
00622     }
00623     
00624     /* И в завершение проверим, находится ли буфере полный пакет. Мы делаем
00625        это путем проверки - был ли последний фрагмент, все ли биты
00626        в карте бит установлены. */
00627     if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
00628       /* Проверка всех байт, кроме последнего байта в карте бит. */
00629       for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
00630          if(uip_reassbitmap[i] != 0xff) {
00631             goto nullreturn;
00632          }
00633       }
00634       /* Проверка последнего байта в карте бит. Он должне содержать просто
00635          правильную сумму бит. */
00636       if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
00637          (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
00638          goto nullreturn;
00639       }
00640 
00641       /* Если мы попали сюда, то у нас есть в буфере полный пакет, так что
00642          выделим pbuf и скопируем пакет туда. Также сбросим таймер. */
00643       uip_reasstmr = 0;
00644       memcpy(BUF, FBUF, uip_reasslen);
00645 
00646       /* Покажем, что теперь IP пакет "нормальный" (т. е. не фрагментированный). */
00647       BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
00648       BUF->len[0] = uip_reasslen >> 8;
00649       BUF->len[1] = uip_reasslen & 0xff;
00650       BUF->ipchksum = 0;
00651       BUF->ipchksum = ~(uip_ipchksum());
00652 
00653       return uip_reasslen;
00654     }
00655   }
00656 
00657  nullreturn:
00658   return 0;
00659 }
00660 #endif /* UIP_REASSEMBLY */
00661 /*---------------------------------------------------------------------------*/
00662 static void uip_add_rcv_nxt(u16_t n)
00663 {
00664   uip_add32(uip_conn->rcv_nxt, n);
00665   uip_conn->rcv_nxt[0] = uip_acc32[0];
00666   uip_conn->rcv_nxt[1] = uip_acc32[1];
00667   uip_conn->rcv_nxt[2] = uip_acc32[2];
00668   uip_conn->rcv_nxt[3] = uip_acc32[3];
00669 }
00670 /*---------------------------------------------------------------------------*/
00671 void uip_process(u8_t flag)
00672 {
00673    register struct uip_conn *uip_connr = uip_conn;
00674 
00675 #if UIP_UDP
00676    if(flag == UIP_UDP_SEND_CONN) {
00677       goto udp_send;
00678    }
00679 #endif /* UIP_UDP */
00680   
00681    uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
00682 
00683    /* Проверка - был ли вызов по причине опроса отдельного соединения. */
00684    if(flag == UIP_POLL_REQUEST) {
00685       if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
00686          !uip_outstanding(uip_connr)) {
00687          uip_flags = UIP_POLL;
00688          UIP_APPCALL();
00689          goto appsend;
00690       }
00691       goto drop;
00692     
00693       /* Проверка - был ли вызов по причине срабатывания периодического
00694          таймера. */
00695    } else if(flag == UIP_TIMER) {
00696 #if UIP_REASSEMBLY
00697       if(uip_reasstmr != 0) {
00698          --uip_reasstmr;
00699       }
00700 #endif /* UIP_REASSEMBLY */
00701       /* Увеличение начального последовательного номера. */
00702       if(++iss[3] == 0) {
00703          if(++iss[2] == 0) {
00704             if(++iss[1] == 0) {
00705                ++iss[0];
00706             }
00707          }
00708       }
00709 
00710       /* Сброс переменных длины. */
00711       uip_len = 0;
00712       uip_slen = 0;
00713 
00714       /* Проверка - находится ли соединение в состоянии, когда
00715          просто идет отслеживание таймаута. Если это так, то
00716          увеличим таймер соединения, и удалим соединение
00717          если таймаут истек. */
00718       if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
00719          uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
00720          ++(uip_connr->timer);
00721          if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
00722             uip_connr->tcpstateflags = UIP_CLOSED;
00723          }
00724       } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
00725          /* Если соединение имеет неподтвержденные данные,
00726             то увеличим таймер соединения и посмотрим,
00727             достигнуто ли значение RTO, в этом случае
00728             делаем ретрансмиссию. */
00729          if(uip_outstanding(uip_connr)) {
00730             if(uip_connr->timer-- == 0) {
00731                if(uip_connr->nrtx == UIP_MAXRTX ||
00732                   ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
00733                   uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
00734                   uip_connr->nrtx == UIP_MAXSYNRTX)) {
00735                   uip_connr->tcpstateflags = UIP_CLOSED;
00736 
00737                   /* Мы вызвали UIP_APPCALL() с переменной uip_flags,
00738                      где установлен UIP_TIMEDOUT, чтобы оповестить
00739                      приложение о том, что таймаут соединения истек. */
00740                   uip_flags = UIP_TIMEDOUT;
00741                   UIP_APPCALL();
00742 
00743                   /* Также мы пошлем пакет сброса на remote host. */
00744                   BUF->flags = TCP_RST | TCP_ACK;
00745                   goto tcp_send_nodata;
00746                }
00747 
00748                /* Экспоненциальный возврат. */
00749                uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
00750                                               4:
00751                                               uip_connr->nrtx);
00752                ++(uip_connr->nrtx);
00753    
00754                /* ОК, теперь нам нужна повторная передача. Это мы будем
00755                   делать по-разному, в зависимости от состояния, 
00756                   в котором находимся. Если в ESTABLISHED, то вызовем
00757                   приложение, которое может подготовить данные к
00758                   повторной передаче. Если в SYN_RCVD, мы заново отправим
00759                   SYNACK, который мы отправмли ранее и если LAST_ACK,
00760                   то заново передадим наш FINACK. */
00761                UIP_STAT(++uip_stat.tcp.rexmit);
00762                switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
00763                case UIP_SYN_RCVD:
00764                   /* В состояии SYN_RCVD state, мы должны заново передать
00765                      наш SYNACK. */
00766                   goto tcp_send_synack;
00767    
00768 #if UIP_ACTIVE_OPEN
00769                case UIP_SYN_SENT:
00770                   /* В состоянии SYN_SENT заново передадим SYN. */
00771                   BUF->flags = 0;
00772                   goto tcp_send_syn;
00773 #endif /* UIP_ACTIVE_OPEN */
00774    
00775                case UIP_ESTABLISHED:
00776                   /* В состоянии ESTABLISHED мы вызовем приложение,
00777                      чтобы сделать действительный ретрансмит, после
00778                      этого перепрыгнем на код для отправки пакета
00779                      (по метке apprexmit). */
00780                   uip_flags = UIP_REXMIT;
00781                   UIP_APPCALL();
00782                   goto apprexmit;
00783    
00784                case UIP_FIN_WAIT_1:
00785                case UIP_CLOSING:
00786                case UIP_LAST_ACK:
00787                   /* Во всех этих состояниях мы должны заново передать
00788                      FINACK. */
00789                   goto tcp_send_finack;
00790                }
00791             }
00792          } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
00793             /* Если в этом месте не нужно делать ретрансмиссию, то
00794                опросим приложение на предмет новых данных. */
00795             uip_flags = UIP_POLL;
00796             UIP_APPCALL();
00797             goto appsend;
00798          }
00799       }
00800       goto drop;
00801    }
00802 #if UIP_UDP
00803    if(flag == UIP_UDP_TIMER) {
00804       if(uip_udp_conn->lport != 0) {
00805          uip_conn = NULL;
00806          uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
00807          uip_len = uip_slen = 0;
00808          uip_flags = UIP_POLL;
00809          UIP_UDP_APPCALL();
00810          goto udp_send;
00811       } else {
00812          goto drop;
00813       }
00814    }
00815 #endif
00816 
00817    /* В этом месте начитается обработка входных данных. */
00818    UIP_STAT(++uip_stat.ip.recv);
00819 
00820    /* Начало кода обработки входного заголовка IP. */
00821   
00822 #if UIP_CONF_IPV6
00823    /* Проверка правильности заголовка IP. */
00824    if((BUF->vtc & 0xf0) != 0x60) { /* Версия IP и длина заголовка. */
00825       UIP_STAT(++uip_stat.ip.drop);
00826       UIP_STAT(++uip_stat.ip.vhlerr);
00827       UIP_LOG("ipv6: invalid version.");
00828       goto drop;
00829    }
00830 #else /* UIP_CONF_IPV6 */
00831    /* Проверка правильности заголовка IP. */
00832    if(BUF->vhl != 0x45) { /* Версия IP и длина заголовка. */
00833       UIP_STAT(++uip_stat.ip.drop);
00834       UIP_STAT(++uip_stat.ip.vhlerr);
00835       UIP_LOG("ip: invalid version or header length.");
00836       goto drop;
00837    }
00838 #endif /* UIP_CONF_IPV6 */
00839   
00840    /* Проверка размера пакета. Если размер, который сообщает переменная
00841       uip_len, меньше размера, сообщенного в заголовке IP, предполагаем
00842       что пакет был поврежден при передаче. Если размер в uip_len
00843       больше, чем размер в заголовке пакета IP, то пакет был дополнен,
00844       и мы установим uip_len в правильное значение. */
00845 
00846    if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
00847       uip_len = (BUF->len[0] << 8) + BUF->len[1];
00848 #if UIP_CONF_IPV6
00849       uip_len += 40; /* Длина, сообщенная в заголовке IPv6,
00850                         является длиной полезной нагрузки,
00851                         которая идет за заголовком. Однако
00852                         uIP использует переменную uip_len
00853                         для удержания размера всего пакета,
00854                         включая заголовок IP. Для IPv4 это
00855                         не проблема, так как поле длины в
00856                         заголовке IPv4 содержит длину целого
00857                         пакета. Но для IPv6 нам нужно добавить
00858                         размер заголовка IPv6 (40 байт). */
00859 #endif /* UIP_CONF_IPV6 */
00860    } else {
00861       UIP_LOG("ip: packet shorter than reported in IP header.");
00862       goto drop;
00863    }
00864 
00865 #if !UIP_CONF_IPV6
00866    /* Проверка флага фрагмента. */
00867    if((BUF->ipoffset[0] & 0x3f) != 0 ||
00868       BUF->ipoffset[1] != 0) {
00869 #if UIP_REASSEMBLY
00870       uip_len = uip_reass();
00871       if(uip_len == 0) {
00872          goto drop;
00873       }
00874 #else /* UIP_REASSEMBLY */
00875       UIP_STAT(++uip_stat.ip.drop);
00876       UIP_STAT(++uip_stat.ip.fragerr);
00877       UIP_LOG("ip: fragment dropped.");
00878       goto drop;
00879 #endif /* UIP_REASSEMBLY */
00880    }
00881 #endif /* UIP_CONF_IPV6 */
00882 
00883    if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
00884       /* Если мы сконфигурированы использовать ping адреса IP, и
00885          адрес IP еще не назначен, то мы примем все пакеты ICMP. */
00886 #if UIP_PINGADDRCONF && !UIP_CONF_IPV6
00887       if(BUF->proto == UIP_PROTO_ICMP) {
00888          UIP_LOG("ip: possible ping config packet received.");
00889          goto icmp_input;
00890       } else {
00891          UIP_LOG("ip: packet dropped since no address assigned.");
00892          goto drop;
00893       }
00894 #endif /* UIP_PINGADDRCONF */
00895 
00896    } else {
00897       /* Если сконфигурирована поддержка IP broadcast, то проверим
00898          пакет UDP на broadcast, который мог предназначаться нам. */
00899 #if UIP_BROADCAST
00900       DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
00901       if(BUF->proto == UIP_PROTO_UDP &&
00902          uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
00903          /*&&
00904          uip_ipchksum() == 0xffff*/) {
00905          goto udp_input;
00906       }
00907 #endif /* UIP_BROADCAST */
00908     
00909       /* Проверка, предназначен ли пакет нашему адресу IP. */
00910 #if !UIP_CONF_IPV6
00911       if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
00912          UIP_STAT(++uip_stat.ip.drop);
00913          goto drop;
00914       }
00915 #else /* UIP_CONF_IPV6 */
00916       /* Для IPv6 прием пакета немного сложнее, так как нам нужно
00917          убедиться, что мы также прослушиваем определенные адреса multicast
00918          (все multicast адреса хостов, требуемые адреса узлов multicast).
00919          Однако тут мы будем читить, и принимать все пакеты multicast,
00920          которые были отправлены на адреса ff02::/16 адресов. */
00921       if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
00922          BUF->destipaddr[0] != HTONS(0xff02)) {
00923          UIP_STAT(++uip_stat.ip.drop);
00924          goto drop;
00925       }
00926 #endif /* UIP_CONF_IPV6 */
00927    }
00928 
00929 #if !UIP_CONF_IPV6
00930    if(uip_ipchksum() != 0xffff) { /* Вычисление и проверка контрольной
00931                                      суммы заголовка IP. */
00932       UIP_STAT(++uip_stat.ip.drop);
00933       UIP_STAT(++uip_stat.ip.chkerr);
00934       UIP_LOG("ip: bad checksum.");
00935       goto drop;
00936    }
00937 #endif /* UIP_CONF_IPV6 */
00938 
00939    if(BUF->proto == UIP_PROTO_TCP) { /* Проверка пакета TCP. Если это так,
00940                                         начинаем обработку ввода TCP. */
00941       goto tcp_input;
00942    }
00943 
00944 #if UIP_UDP
00945    if(BUF->proto == UIP_PROTO_UDP) {
00946       goto udp_input;
00947    }
00948 #endif /* UIP_UDP */
00949 
00950 #if !UIP_CONF_IPV6
00951    /* Далее идет код обработки ICMPv4. */
00952    if(BUF->proto != UIP_PROTO_ICMP) { /* Отсюда будем разрешать только
00953                                          пакеты ICMP. */
00954       UIP_STAT(++uip_stat.ip.drop);
00955       UIP_STAT(++uip_stat.ip.protoerr);
00956       UIP_LOG("ip: neither tcp nor icmp.");
00957       goto drop;
00958    }
00959 
00960 #if UIP_PINGADDRCONF
00961  icmp_input:
00962 #endif /* UIP_PINGADDRCONF */
00963    UIP_STAT(++uip_stat.icmp.recv);
00964 
00965    /* Обработка ICMP echo (например ping). Она проста, мы только поменяем
00966       тип ICMP с ECHO на ECHO_REPLY, и подстроим контрольную сумму ICMP
00967       перед возвратом пакета. */
00968    if(ICMPBUF->type != ICMP_ECHO) {
00969       UIP_STAT(++uip_stat.icmp.drop);
00970       UIP_STAT(++uip_stat.icmp.typeerr);
00971       UIP_LOG("icmp: not icmp echo.");
00972       goto drop;
00973    }
00974 
00975    /* Если мы были сконфигурированы для использования назначенного IP адреса
00976       ping. мы используем адрес IP назначения этого пакета ping и назначим
00977       его самим себе. */
00978 #if UIP_PINGADDRCONF
00979    if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
00980       uip_hostaddr[0] = BUF->destipaddr[0];
00981       uip_hostaddr[1] = BUF->destipaddr[1];
00982    }
00983 #endif /* UIP_PINGADDRCONF */
00984 
00985   ICMPBUF->type = ICMP_ECHO_REPLY;
00986 
00987    if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
00988       ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
00989    } else {
00990       ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
00991    }
00992 
00993    /* Перестановка адресов IP. */
00994    uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
00995    uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
00996 
00997    UIP_STAT(++uip_stat.icmp.sent);
00998    goto send;
00999 
01000   /* Конец кода обработки входного заголовка IPv4. */
01001 #else /* !UIP_CONF_IPV6 */
01002 
01003   /* Это код обработки IPv6 ICMPv6. */
01004   DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
01005 
01006    if(BUF->proto != UIP_PROTO_ICMP6) { /* Отсюда будем разрешать только
01007                                           пакеты ICMPv6. */
01008       UIP_STAT(++uip_stat.ip.drop);
01009       UIP_STAT(++uip_stat.ip.protoerr);
01010       UIP_LOG("ip: neither tcp nor icmp6.");
01011       goto drop;
01012    }
01013 
01014    UIP_STAT(++uip_stat.icmp.recv);
01015 
01016    /* Если мы получаем ходатайство соседа для нашего адреса, то мы
01017       должны передать сообщение соседа обратно. */
01018    if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
01019       if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
01020          if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
01021             /* Сохранение адреса отправителя в списке наших соседей. */
01022             uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
01023          }
01024       
01025          /* Теперь нужно отправить сообщение соседа обратно туда,
01026              откуда оно пришло. */
01027          ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
01028          ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
01029       
01030          ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
01031       
01032          uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
01033          uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
01034          ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
01035          ICMPBUF->options[1] = 1;  /* Options length, 1 = 8 bytes. */
01036          memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
01037          ICMPBUF->icmpchksum = 0;
01038          ICMPBUF->icmpchksum = ~uip_icmp6chksum();
01039          goto send;
01040       }
01041       goto drop;
01042    } else if(ICMPBUF->type == ICMP6_ECHO) {
01043       /* Обработка ICMP echo (например ping). Она проста, мы только
01044          меняем тип ICMP с ECHO на ECHO_REPLY, и обновляем контролную
01045          сумму ICMP перед возвратом пакета. */
01046       ICMPBUF->type = ICMP6_ECHO_REPLY;
01047     
01048       uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
01049       uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
01050       ICMPBUF->icmpchksum = 0;
01051       ICMPBUF->icmpchksum = ~uip_icmp6chksum();
01052     
01053       UIP_STAT(++uip_stat.icmp.sent);
01054       goto send;
01055    } else {
01056       DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
01057       UIP_STAT(++uip_stat.icmp.drop);
01058       UIP_STAT(++uip_stat.icmp.typeerr);
01059       UIP_LOG("icmp: unknown ICMP message.");
01060       goto drop;
01061    }
01062    /* Конец обработки IPv6 ICMP. */
01063 #endif /* !UIP_CONF_IPV6 */
01064 
01065 #if UIP_UDP
01066    /* Обработка входа UDP. */
01067  udp_input:
01068    /* Обработка UDP реально похожа на хак. Мы ничего не делаем 
01069       с заголовками UDP/IP, просто позволим приложению UDP
01070       сделать всю сложную работу. Если приложение установило
01071       uip_slen, то у нас есть пакет для отправки. */
01072 #if UIP_UDP_CHECKSUMS
01073    uip_len = uip_len - UIP_IPUDPH_LEN;
01074    uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
01075    if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
01076       UIP_STAT(++uip_stat.udp.drop);
01077       UIP_STAT(++uip_stat.udp.chkerr);
01078       UIP_LOG("udp: bad checksum.");
01079       goto drop;
01080    }
01081 #else /* UIP_UDP_CHECKSUMS */
01082    uip_len = uip_len - UIP_IPUDPH_LEN;
01083 #endif /* UIP_UDP_CHECKSUMS */
01084 
01085    /* Демультиплексирование этого пакета UDP между "подключениями" UDP. */
01086    for(uip_udp_conn = &uip_udp_conns[0];
01087       uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
01088       ++uip_udp_conn) {
01089       /* Если локальный порт UDP не 0, то считается что соединение
01090          используется. Если это так, то локальный номер порта проверяется
01091          на номер порта назначения в принятом пакете. Если эти два
01092          номера порта совпадают, номер порта дальнего конца проверяется
01093          на предмет привязки к соединения к порту дальнего конца. 
01094          В завершение, если соединение привязано к адресу IP дальнего
01095          конца, в пакете проверяется адрес IP источника. */
01096       if(uip_udp_conn->lport != 0 &&
01097          UDPBUF->destport == uip_udp_conn->lport &&
01098          (uip_udp_conn->rport == 0 ||
01099          UDPBUF->srcport == uip_udp_conn->rport) &&
01100          (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
01101          uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
01102          uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
01103          goto udp_found;
01104       }
01105    }
01106    UIP_LOG("udp: no matching connection found");
01107    goto drop;
01108   
01109  udp_found:
01110    uip_conn = NULL;
01111    uip_flags = UIP_NEWDATA;
01112    uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
01113    uip_slen = 0;
01114    UIP_UDP_APPCALL();
01115  udp_send:
01116    if(uip_slen == 0) {
01117       goto drop;
01118    }
01119    uip_len = uip_slen + UIP_IPUDPH_LEN;
01120 
01121 #if UIP_CONF_IPV6
01122    /* Для IPv6 длина поля IP не включено в длину IP заголовка IPv6. */
01123    BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
01124    BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
01125 #else /* UIP_CONF_IPV6 */
01126    BUF->len[0] = (uip_len >> 8);
01127    BUF->len[1] = (uip_len & 0xff);
01128 #endif /* UIP_CONF_IPV6 */
01129 
01130    BUF->ttl = uip_udp_conn->ttl;
01131    BUF->proto = UIP_PROTO_UDP;
01132 
01133    UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
01134    UDPBUF->udpchksum = 0;
01135 
01136    BUF->srcport  = uip_udp_conn->lport;
01137    BUF->destport = uip_udp_conn->rport;
01138 
01139    uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
01140    uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
01141    
01142    uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
01143 
01144 #if UIP_UDP_CHECKSUMS
01145    /* Вычисление контрольной суммы UDP. */
01146    UDPBUF->udpchksum = ~(uip_udpchksum());
01147    if(UDPBUF->udpchksum == 0) {
01148       UDPBUF->udpchksum = 0xffff;
01149    }
01150 #endif /* UIP_UDP_CHECKSUMS */
01151   
01152    goto ip_send_nolen;
01153 #endif /* UIP_UDP */
01154   
01155    /* Обработка ввода TCP. */
01156  tcp_input:
01157    UIP_STAT(++uip_stat.tcp.recv);
01158 
01159    /* Начало кода обработки входного заголовка TCP. */
01160   
01161    if(uip_tcpchksum() != 0xffff) { /* Вычисление и проверка 
01162                                       контрольной суммы TCP. */
01163       UIP_STAT(++uip_stat.tcp.drop);
01164       UIP_STAT(++uip_stat.tcp.chkerr);
01165       UIP_LOG("tcp: bad checksum.");
01166       goto drop;
01167    }
01168   
01169    /* Демультиплексирование этого сегмента. */
01170    /* Сначала проверяем активные соединения. */
01171    for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
01172        ++uip_connr) {
01173       if(uip_connr->tcpstateflags != UIP_CLOSED &&
01174          BUF->destport == uip_connr->lport &&
01175          BUF->srcport == uip_connr->rport &&
01176          uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
01177          goto found;
01178       }
01179    }
01180 
01181    /* Если мы не нашли и активное соедиение, которое ожидает пакет,
01182       либо этот пакет старая копия, или он является пакетом SYN,
01183       предназначенный для соединения в состоянии LISTEN. Если флаг
01184       SYN не установлен, это старый пакет, и мы пошлем RST. */
01185    if((BUF->flags & TCP_CTL) != TCP_SYN) {
01186       goto reset;
01187    }
01188   
01189    tmp16 = BUF->destport;
01190    /* Далее проверим прослушиваемые соединения. */
01191    for(c = 0; c < UIP_LISTENPORTS; ++c) {
01192       if(tmp16 == uip_listenports[c]) {
01193          goto found_listen;
01194       }
01195    }
01196   
01197    /* Не найдено подходящих соединений, так что пошлем пакет RST. */
01198    UIP_STAT(++uip_stat.tcp.synrst);
01199  reset:
01200 
01201    /* Мы не посылаем сбросы в ответ на сбросы. */
01202    if(BUF->flags & TCP_RST) {
01203       goto drop;
01204    }
01205 
01206    UIP_STAT(++uip_stat.tcp.rst);
01207   
01208    BUF->flags = TCP_RST | TCP_ACK;
01209    uip_len = UIP_IPTCPH_LEN;
01210    BUF->tcpoffset = 5 << 4;
01211 
01212    /* Переставим поля seqno и ackno в заголовке TCP. */
01213    c = BUF->seqno[3];
01214    BUF->seqno[3] = BUF->ackno[3];
01215    BUF->ackno[3] = c;
01216   
01217    c = BUF->seqno[2];
01218    BUF->seqno[2] = BUF->ackno[2];
01219    BUF->ackno[2] = c;
01220   
01221    c = BUF->seqno[1];
01222    BUF->seqno[1] = BUF->ackno[1];
01223    BUF->ackno[1] = c;
01224   
01225    c = BUF->seqno[0];
01226    BUF->seqno[0] = BUF->ackno[0];
01227    BUF->ackno[0] = c;
01228 
01229    /* Также увеличим номер последовательности, который подтверждаем.
01230       Если наименее значемый байт переполнился, то нужно распространить
01231       перенос на более старшие байты. */
01232    if(++BUF->ackno[3] == 0) {
01233       if(++BUF->ackno[2] == 0) {
01234          if(++BUF->ackno[1] == 0) {
01235             ++BUF->ackno[0];
01236          }
01237       }
01238    }
01239  
01240    /* Переставим номера портов. */
01241    tmp16 = BUF->srcport;
01242    BUF->srcport = BUF->destport;
01243    BUF->destport = tmp16;
01244   
01245    /* Переставим адреса IP. */
01246    uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
01247    uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
01248   
01249    /* И отправим пакет RST! */
01250    goto tcp_send_noconn;
01251 
01252    /* По этой метке будут переходы, если обнаружено, что входящий пакет
01253       для соединения в состоянии LISTEN. Тогда мы должны создать новое
01254       соединение и отправить в ответ SYNACK. */
01255  found_listen:
01256    /* Сначала проверим, есть ли доступные соединения. Не используемые
01257       соединения хранятся в той же таблице, что и используемые, однако
01258       у неиспользуемых поле tcpstate установлено в состояние CLOSED.
01259       Также отслеживаются соединения в состоянии TIME_WAIT, и будем
01260       использовать самые старые из них, если не найдено соединений
01261       в состоянии CLOSED. Благодарю Eddie C. Dost за отличный алгоритм
01262       для поиска TIME_WAIT. */
01263    uip_connr = 0;
01264    for(c = 0; c < UIP_CONNS; ++c) {
01265       if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
01266          uip_connr = &uip_conns[c];
01267          break;
01268       }
01269       if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
01270          if(uip_connr == 0 ||
01271             uip_conns[c].timer > uip_connr->timer) {
01272             uip_connr = &uip_conns[c];
01273          }
01274       }
01275    }
01276 
01277    if(uip_connr == 0) {
01278       /* Все соединения уже задействованы, так что отбросим пакет
01279          и будем надеяться, что дальний конец переотправит пакет
01280          тогда, когда у нас будет больше свободных соединений. */
01281       UIP_STAT(++uip_stat.tcp.syndrop);
01282       UIP_LOG("tcp: found no unused connections.");
01283       goto drop;
01284    }
01285    uip_conn = uip_connr;
01286   
01287    /* Заполним нужные поля для нового соединения. */
01288    uip_connr->rto = uip_connr->timer = UIP_RTO;
01289    uip_connr->sa = 0;
01290    uip_connr->sv = 4;
01291    uip_connr->nrtx = 0;
01292    uip_connr->lport = BUF->destport;
01293    uip_connr->rport = BUF->srcport;
01294    uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
01295    uip_connr->tcpstateflags = UIP_SYN_RCVD;
01296    
01297    uip_connr->snd_nxt[0] = iss[0];
01298    uip_connr->snd_nxt[1] = iss[1];
01299    uip_connr->snd_nxt[2] = iss[2];
01300    uip_connr->snd_nxt[3] = iss[3];
01301    uip_connr->len = 1;
01302    
01303    /* rcv_nxt должно быть seqno из входящего пакета + 1. */
01304    uip_connr->rcv_nxt[3] = BUF->seqno[3];
01305    uip_connr->rcv_nxt[2] = BUF->seqno[2];
01306    uip_connr->rcv_nxt[1] = BUF->seqno[1];
01307    uip_connr->rcv_nxt[0] = BUF->seqno[0];
01308    uip_add_rcv_nxt(1);
01309 
01310    /* Парсинг опции TCP MSS, если она есть. */
01311    if((BUF->tcpoffset & 0xf0) > 0x50) {
01312       for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
01313          opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
01314          if(opt == TCP_OPT_END) {
01315             /* Конец опций. */
01316             break;
01317          } else if(opt == TCP_OPT_NOOP) {
01318             ++c;
01319             /* Опция NOP. */
01320          } else if(opt == TCP_OPT_MSS &&
01321              uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
01322             /* Опция MSS с правильной длиной опции. */
01323             tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
01324                     (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
01325             uip_connr->initialmss = uip_connr->mss =
01326             tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
01327       
01328             /* И мы завершили обработку опций. */
01329             break;
01330          } else {
01331             /* Все другие опции имеют поле длины, так что нам проще
01332                их пропустить. */
01333             if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
01334                /* Если поле длины 0, то опции ошибочно сформированы,
01335                   и мы их не будем дальше обрабатывать. */
01336                break;
01337             }
01338             c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
01339          }
01340       }
01341    }
01342   
01343    /* Наш ответ будет SYNACK. */
01344 #if UIP_ACTIVE_OPEN
01345    tcp_send_synack:
01346    BUF->flags = TCP_ACK;
01347   
01348  tcp_send_syn:
01349    BUF->flags |= TCP_SYN;
01350 #else /* UIP_ACTIVE_OPEN */
01351  tcp_send_synack:
01352    BUF->flags = TCP_SYN | TCP_ACK;
01353 #endif /* UIP_ACTIVE_OPEN */
01354   
01355    /* Отправим опцию TCP Maximum Segment Size с нашим SYNACK. */
01356    BUF->optdata[0] = TCP_OPT_MSS;
01357    BUF->optdata[1] = TCP_OPT_MSS_LEN;
01358    BUF->optdata[2] = (UIP_TCP_MSS) / 256;
01359    BUF->optdata[3] = (UIP_TCP_MSS) & 255;
01360    uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
01361    BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
01362    goto tcp_send;
01363 
01364    /* По этой метке будут переходы, если будет найдено
01365       активное соединение. */
01366  found:
01367    uip_conn = uip_connr;
01368    uip_flags = 0;
01369    /* Будет сделана самая стандартная обработка сброса TCP; мы просто
01370       примем любой RST и убъем наше соединение. Мы фактически должны
01371       проверить, является ли номер последовательности этого сброса
01372       в нашем предоставленном окне, перед тем как мы примем сброс. */
01373    if(BUF->flags & TCP_RST) {
01374       uip_connr->tcpstateflags = UIP_CLOSED;
01375       UIP_LOG("tcp: got reset, aborting connection.");
01376       uip_flags = UIP_ABORT;
01377       UIP_APPCALL();
01378       goto drop;
01379    }
01380    /* Вычисленная длина данных, если приложение послало нам
01381       любые данные. */
01382    c = (BUF->tcpoffset >> 4) << 2;
01383    /* uip_len будет содержать длину действительных данных TCP. Она будет
01384       вычислена путем вычитания длины заголовка TCP (в переменной c)
01385       и длины заголовка IP (20 байт). */
01386    uip_len = uip_len - c - UIP_IPH_LEN;
01387 
01388    /* Сначала проверим номер последовательности входящего пакета, тот ли
01389       он, что ожидается как следующий. Если нет, то пошлем ACK с правильным
01390       номером. */
01391    if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
01392        ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
01393       if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
01394          (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
01395          BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
01396          BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
01397          BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
01398          goto tcp_send_ack;
01399       }
01400    }
01401 
01402    /* Далее проверим, подтверждает ли входящий сегмент какие-нибудь еще
01403       не подтвержденные данные. Если это так, то обновим номер
01404       последовательности, сбросим длину неподтвержденных данных,
01405       вычислим оценки RTT, и сбросим таймер ретрансмиссии. */
01406    if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
01407       uip_add32(uip_connr->snd_nxt, uip_connr->len);
01408 
01409       if(BUF->ackno[0] == uip_acc32[0] &&
01410          BUF->ackno[1] == uip_acc32[1] &&
01411          BUF->ackno[2] == uip_acc32[2] &&
01412          BUF->ackno[3] == uip_acc32[3]) {
01413          /* Обновление номера последовательности. */
01414          uip_connr->snd_nxt[0] = uip_acc32[0];
01415          uip_connr->snd_nxt[1] = uip_acc32[1];
01416          uip_connr->snd_nxt[2] = uip_acc32[2];
01417          uip_connr->snd_nxt[3] = uip_acc32[3];
01418 
01419          /* Сделаем оценку RTT, если мы не сделали ретрансмиссии. */
01420          if(uip_connr->nrtx == 0) {
01421             signed char m;
01422             m = uip_connr->rto - uip_connr->timer;
01423             /* Это взято непосредственно из оригинального коа VJ в его статье */
01424             m = m - (uip_connr->sa >> 3);
01425             uip_connr->sa += m;
01426             if(m < 0) {
01427                m = -m;
01428             }
01429             m = m - (uip_connr->sv >> 2);
01430             uip_connr->sv += m;
01431             uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
01432          }
01433          /* Установка флага, что было подтверждение. */
01434          uip_flags = UIP_ACKDATA;
01435          /* Сброс таймера ретрансмиссии. */
01436          uip_connr->timer = uip_connr->rto;
01437 
01438          /* Сброс длины неподтвержденных данных. */
01439          uip_connr->len = 0;
01440       }
01441   }
01442 
01443    /* Предпримем разные действия в зависимости от того, в каком состоянии
01444       находится соединение. */
01445    switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
01446       /* Здесь не обрабатываются состояния CLOSED и LISTEN. CLOSE_WAIT
01447          не реализовано, поскольку мы вынуждаем приложение сделать закрытие,
01448          когда участник обмена посылает FIN (следовательно приложение
01449          перейдет непосредственно от ESTABLISHED к LAST_ACK). */
01450    case UIP_SYN_RCVD:
01451       /* В состоянии SYN_RCVD отправим SYNACK в ответ на SYN, и
01452          ждем ACK, который подтвердит данные, которые мы послали последний
01453          раз. Таким образом, мы хотим иметь установленным флаг UIP_ACKDATA.
01454          Если так, то входим в состояние ESTABLISHED. */
01455       if(uip_flags & UIP_ACKDATA) {
01456          uip_connr->tcpstateflags = UIP_ESTABLISHED;
01457          uip_flags = UIP_CONNECTED;
01458          uip_connr->len = 0;
01459          if(uip_len > 0) {
01460             uip_flags |= UIP_NEWDATA;
01461             uip_add_rcv_nxt(uip_len);
01462          }
01463          uip_slen = 0;
01464          UIP_APPCALL();
01465          goto appsend;
01466       }
01467       goto drop;
01468 #if UIP_ACTIVE_OPEN
01469    case UIP_SYN_SENT:
01470       /* В состоянии SYN_SENT, мы ждем SYNACK, который отправляется в ответ
01471          на наш SYN. Переменная rcv_nxt установлена в номер последовательности
01472          SYNACK плюс один, и мы посылаем ACK. Перейдем в состояние ESTABLISHED. */
01473       if((uip_flags & UIP_ACKDATA) &&
01474          (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
01475          /* Парсинг опции TCP MSS, если она представлена. */
01476          if((BUF->tcpoffset & 0xf0) > 0x50) {
01477             for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
01478                opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
01479                if(opt == TCP_OPT_END) {
01480                   /* Конец опций. */
01481                   break;
01482                } else if(opt == TCP_OPT_NOOP) {
01483                   ++c;
01484                   /* Опция NOP. */
01485                } else if(opt == TCP_OPT_MSS &&
01486                   uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
01487                   /* Опция MSS с правильной длиной опции. */
01488                   tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
01489                   uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
01490                   uip_connr->initialmss =
01491                      uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
01492    
01493                   /* Имы закончили обработку опций. */
01494                   break;
01495                } else {
01496                   /* Все другие опции имеют поле длины, так что их можно
01497                      проще пропустить. */
01498                   if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
01499                      /* Если поле длины 0, то опция сформирована ошибочно
01500                         и мы дальше не обрабатываем их далее. */
01501                      break;
01502                   }
01503                   c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
01504                }
01505             }
01506          }
01507          uip_connr->tcpstateflags = UIP_ESTABLISHED;
01508          uip_connr->rcv_nxt[0] = BUF->seqno[0];
01509          uip_connr->rcv_nxt[1] = BUF->seqno[1];
01510          uip_connr->rcv_nxt[2] = BUF->seqno[2];
01511          uip_connr->rcv_nxt[3] = BUF->seqno[3];
01512          uip_add_rcv_nxt(1);
01513          uip_flags = UIP_CONNECTED | UIP_NEWDATA;
01514          uip_connr->len = 0;
01515          uip_len = 0;
01516          uip_slen = 0;
01517          UIP_APPCALL();
01518          goto appsend;
01519       }
01520       /* Сообщаем приложению, что соединение потерпело ошибку */
01521       uip_flags = UIP_ABORT;
01522       UIP_APPCALL();
01523       /* Соединение было завершено после того как мы послали RST */
01524       uip_conn->tcpstateflags = UIP_CLOSED;
01525       goto reset;
01526 #endif /* UIP_ACTIVE_OPEN */
01527    case UIP_ESTABLISHED:
01528       /* В состоянии ESTABLISHED вызовем приложение, чтобы подать данные
01529          в uip_buf. Если флаг UIP_ACKDATA установлен, приложение должно
01530          поместить новые данные в буфер, иначе мы заново передадим старый
01531          сегмент, и приложение должно поместить данные в буфер.
01532    
01533          Если взодящий пакет FIN, мы должны также закрыть соединение 
01534          на этой стороне, и мы посылаем FIN и входим в состояние LAST_ACK.
01535          Здесь мы требуем, чтобы не было никаких неподтвержденных данных;
01536          иначе будут задействованы номера последовательности. */
01537 
01538       if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
01539          if(uip_outstanding(uip_connr)) {
01540             goto drop;
01541          }
01542          uip_add_rcv_nxt(1 + uip_len);
01543          uip_flags |= UIP_CLOSE;
01544          if(uip_len > 0) {
01545             uip_flags |= UIP_NEWDATA;
01546          }
01547          UIP_APPCALL();
01548          uip_connr->len = 1;
01549          uip_connr->tcpstateflags = UIP_LAST_ACK;
01550          uip_connr->nrtx = 0;
01551  tcp_send_finack:
01552          BUF->flags = TCP_FIN | TCP_ACK;
01553          goto tcp_send_nodata;
01554       }
01555    
01556       /* Проверим флаг URG. Если он установлен, то сегмент несет в себе
01557          urgent data, которые мы должны передать приложению. */
01558       if((BUF->flags & TCP_URG) != 0) {
01559 #if UIP_URGDATA > 0
01560          uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
01561          if(uip_urglen > uip_len) {
01562             /* Есть больше urgent data в следующем сегменте, который
01563                поступит. */
01564             uip_urglen = uip_len;
01565          }
01566          uip_add_rcv_nxt(uip_urglen);
01567          uip_len -= uip_urglen;
01568          uip_urgdata = uip_appdata;
01569          uip_appdata += uip_urglen;
01570       } else {
01571          uip_urglen = 0;
01572 #else /* UIP_URGDATA > 0 */
01573          uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
01574          uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
01575 #endif /* UIP_URGDATA > 0 */
01576       }
01577    
01578       /* Если uip_len > 0, то в пакете есть данные TCP, запомним это
01579          установкой флага UIP_NEWDATA и обновим номер последовательности,
01580          который мы подтверждаем. Если приложение остановило поток данных,
01581          используя uip_stop(), мы не должны принять любые пакеты данных
01582          от remote host. */
01583       if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
01584          uip_flags |= UIP_NEWDATA;
01585          uip_add_rcv_nxt(uip_len);
01586       }
01587 
01588       /* Проверка - меньше ли доступное место в буфере, представленное
01589          дальнему участнику обмена, чем начальное MSS для этого соединения.
01590          Если это так, то мы установим текущее MSS на рамер окна, чтобы
01591          гарантировать, что приложение не отправит данных больше, чем
01592          другая сторона может обработать.
01593 
01594          Если дальний участник обмена представил нулевое окно, то установим
01595          MSS в начальное MSS, так что приложение будет отправлять целое
01596          MSS данных. Эти данные не будут подтверждены приемником,
01597          и приложение будет передавать их повторно. Это назвается
01598          "постоянный таймер" и использует механизм ретрансмиссии.
01599       */
01600       tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
01601       if(tmp16 > uip_connr->initialmss ||
01602          tmp16 == 0) {
01603          tmp16 = uip_connr->initialmss;
01604       }
01605       uip_connr->mss = tmp16;
01606 
01607       /* Если этот пакет составляет ACK для неподтвержденных данных
01608          (помеченных флагом UIP_ACKDATA, мы должны вызвать приложение,
01609          поскольку оно может хотеть отправить больше данных. Если
01610          в пришедшем пакете были данные от дальнего участника обмена
01611          (помеченные флагом UIP_NEWDATA), то приложение также должно
01612          быть оповещено об этом.
01613 
01614          Когда вызывается приложение, глобальная переменная uip_len
01615          содержит длину пришедших данных. Приложение может получить
01616          доступ к пришедшим данным через глобальный указатель
01617          uip_appdata, который обычно указывает на 
01618          UIP_IPTCPH_LEN + UIP_LLH_LEN байт в буфере uip_buf.
01619 
01620          Если приложение хочет отправить данные, то они должны быть
01621          помещены в буфер uip_appdata и длина данных должна быть
01622          помещена в uip_len. Если у приложения нет данных для
01623          отправки, то uip_len должна быть сброшена в 0. */
01624       if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
01625          uip_slen = 0;
01626          UIP_APPCALL();
01627 
01628     appsend:
01629          if(uip_flags & UIP_ABORT) {
01630             uip_slen = 0;
01631             uip_connr->tcpstateflags = UIP_CLOSED;
01632             BUF->flags = TCP_RST | TCP_ACK;
01633             goto tcp_send_nodata;
01634          }
01635 
01636          if(uip_flags & UIP_CLOSE) {
01637             uip_slen = 0;
01638             uip_connr->len = 1;
01639             uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
01640             uip_connr->nrtx = 0;
01641             BUF->flags = TCP_FIN | TCP_ACK;
01642             goto tcp_send_nodata;
01643          }
01644 
01645          /* Если uip_slen > 0, то у приложения есть данные для отправки. */
01646          if(uip_slen > 0) {
01647             /* Если соединение имеет подтвержденные данные, то содержимое
01648                переменной ->len должно быть отброшено. */
01649             if((uip_flags & UIP_ACKDATA) != 0) {
01650                uip_connr->len = 0;
01651             }
01652 
01653             /* Если переменная ->len не 0, то соединение уже имеет данные
01654                в пути и не сейчас имеет права отправить больше. */
01655             if(uip_connr->len == 0) {
01656                /* Приложение не может отправить больше, чем это разрешено
01657                   mss (минимум MSS и доспупное окно). */
01658                if(uip_slen > uip_connr->mss) {
01659                uip_slen = uip_connr->mss;
01660                }
01661 
01662                /* Запомним, сколько данных мы теперь отсылаем, чтобы мы знали,
01663                   когда все будет подтверждено. */
01664                uip_connr->len = uip_slen;
01665             } else {
01666                /* Если у приложения уже есть неподтвержденные данные, убедимся,
01667                   что приложение не передает (например ретрансмиссию) больше,
01668                   чем отправило ранее. */
01669                uip_slen = uip_connr->len;
01670             }
01671          }
01672          uip_connr->nrtx = 0;
01673     apprexmit:
01674          uip_appdata = uip_sappdata;
01675    
01676          /* Если у приложения есть данные для отправки, или если в пришедшем
01677             пакете есть новые данные, мы должны отправить пакет. */
01678          if(uip_slen > 0 && uip_connr->len > 0) {
01679             /* Добавление длины заголовков IP и TCP. */
01680             uip_len = uip_connr->len + UIP_TCPIP_HLEN;
01681             /* Мы всегда установим флаг ACK в пакетах ответа. */
01682             BUF->flags = TCP_ACK | TCP_PSH;
01683             /* Отправим пакет. */
01684             goto tcp_send_noopts;
01685          }
01686          /* Если здесь нет данных для отправки, просто отправим чистый ACK,
01687             если здесь новые данные. */
01688          if(uip_flags & UIP_NEWDATA) {
01689             uip_len = UIP_TCPIP_HLEN;
01690             BUF->flags = TCP_ACK;
01691             goto tcp_send_noopts;
01692          }
01693       }
01694       goto drop;
01695    case UIP_LAST_ACK:
01696       /* Мы можем закрыть это соединение, если участник обмена подтвердил
01697          наш FIN. Это показывается флагом UIP_ACKDATA. */
01698       if(uip_flags & UIP_ACKDATA) {
01699          uip_connr->tcpstateflags = UIP_CLOSED;
01700          uip_flags = UIP_CLOSE;
01701          UIP_APPCALL();
01702       }
01703       break;
01704     
01705    case UIP_FIN_WAIT_1:
01706       /* Приложение имеет закрытое соединение, но remote host его еще
01707          не закрыл. Тут мы ничего не делаем, но ждем FIN с дальней стороны. */
01708       if(uip_len > 0) {
01709          uip_add_rcv_nxt(uip_len);
01710       }
01711       if(BUF->flags & TCP_FIN) {
01712          if(uip_flags & UIP_ACKDATA) {
01713             uip_connr->tcpstateflags = UIP_TIME_WAIT;
01714             uip_connr->timer = 0;
01715             uip_connr->len = 0;
01716          } else {
01717             uip_connr->tcpstateflags = UIP_CLOSING;
01718          }
01719          uip_add_rcv_nxt(1);
01720          uip_flags = UIP_CLOSE;
01721          UIP_APPCALL();
01722          goto tcp_send_ack;
01723       } else if(uip_flags & UIP_ACKDATA) {
01724          uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
01725          uip_connr->len = 0;
01726          goto drop;
01727       }
01728       if(uip_len > 0) {
01729          goto tcp_send_ack;
01730       }
01731       goto drop;
01732    
01733   case UIP_FIN_WAIT_2:
01734       if(uip_len > 0) {
01735          uip_add_rcv_nxt(uip_len);
01736       }
01737       if(BUF->flags & TCP_FIN) {
01738          uip_connr->tcpstateflags = UIP_TIME_WAIT;
01739          uip_connr->timer = 0;
01740          uip_add_rcv_nxt(1);
01741          uip_flags = UIP_CLOSE;
01742          UIP_APPCALL();
01743          goto tcp_send_ack;
01744       }
01745       if(uip_len > 0) {
01746          goto tcp_send_ack;
01747       }
01748       goto drop;
01749 
01750    case UIP_TIME_WAIT:
01751       goto tcp_send_ack;
01752     
01753    case UIP_CLOSING:
01754       if(uip_flags & UIP_ACKDATA) {
01755          uip_connr->tcpstateflags = UIP_TIME_WAIT;
01756          uip_connr->timer = 0;
01757       }
01758    }
01759    goto drop;
01760   
01761    /* Мы перепрыгнули сюда, когда готоыв к отправке пакета, и просто
01762       хотим установить подходящие номера последовательности
01763       в заголовке TCP. */
01764  tcp_send_ack:
01765    BUF->flags = TCP_ACK;
01766    tcp_send_nodata:
01767    uip_len = UIP_IPTCPH_LEN;
01768  tcp_send_noopts:
01769    BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
01770  tcp_send:
01771    /* Мы завершили входную обработку. Теперь все готово к отправке
01772       ответа. Наша работа заключается в заполнении всех полей заголовков
01773       TCP и IP перед вычислением контрольной суммы и завершающей отправкой
01774       пакета. */
01775    BUF->ackno[0] = uip_connr->rcv_nxt[0];
01776    BUF->ackno[1] = uip_connr->rcv_nxt[1];
01777    BUF->ackno[2] = uip_connr->rcv_nxt[2];
01778    BUF->ackno[3] = uip_connr->rcv_nxt[3];
01779   
01780    BUF->seqno[0] = uip_connr->snd_nxt[0];
01781    BUF->seqno[1] = uip_connr->snd_nxt[1];
01782    BUF->seqno[2] = uip_connr->snd_nxt[2];
01783    BUF->seqno[3] = uip_connr->snd_nxt[3];
01784    
01785    BUF->proto = UIP_PROTO_TCP;
01786   
01787    BUF->srcport  = uip_connr->lport;
01788    BUF->destport = uip_connr->rport;
01789    
01790    uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
01791    uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
01792 
01793    if(uip_connr->tcpstateflags & UIP_STOPPED) {
01794       /* Если соединение выдало uip_stop(), мы представляем нулевое
01795          окно, чтобы remote host прекратил посылать данные. */
01796       BUF->wnd[0] = BUF->wnd[1] = 0;
01797    } else {
01798       BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
01799       BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
01800    }
01801 
01802  tcp_send_noconn:
01803    BUF->ttl = UIP_TTL;
01804 #if UIP_CONF_IPV6
01805    /* Для IPv6, поле длины IP не включает длину IP заголовка IPv6. */
01806    BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
01807    BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
01808 #else /* UIP_CONF_IPV6 */
01809    BUF->len[0] = (uip_len >> 8);
01810    BUF->len[1] = (uip_len & 0xff);
01811 #endif /* UIP_CONF_IPV6 */
01812 
01813    BUF->urgp[0] = BUF->urgp[1] = 0;
01814   
01815    /* Вычисление контрольной суммы TCP. */
01816    BUF->tcpchksum = 0;
01817    BUF->tcpchksum = ~(uip_tcpchksum());
01818   
01819 ip_send_nolen:
01820 
01821 #if UIP_CONF_IPV6
01822    BUF->vtc = 0x60;
01823    BUF->tcflow = 0x00;
01824    BUF->flow = 0x00;
01825 #else /* UIP_CONF_IPV6 */
01826    BUF->vhl = 0x45;
01827    BUF->tos = 0;
01828    BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
01829    ++ipid;
01830    BUF->ipid[0] = ipid >> 8;
01831    BUF->ipid[1] = ipid & 0xff;
01832    /* Вычисление контрольной суммы IP. */
01833    BUF->ipchksum = 0;
01834    BUF->ipchksum = ~(uip_ipchksum());
01835    DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
01836 #endif /* UIP_CONF_IPV6 */
01837    
01838    UIP_STAT(++uip_stat.tcp.sent);
01839  send:
01840    DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
01841                 (BUF->len[0] << 8) | BUF->len[1]);
01842   
01843    UIP_STAT(++uip_stat.ip.sent);
01844    /* Возврат, чтобы дать возможность вызвавшему сделать реальную
01845       отправку данных. */
01846    uip_flags = 0;
01847    return;
01848  drop:
01849    uip_len = 0;
01850    uip_flags = 0;
01851    return;
01852 }
01853 /*---------------------------------------------------------------------------*/
01854 u16_t
01855 htons(u16_t val)
01856 {
01857   return HTONS(val);
01858 }
01859 /*---------------------------------------------------------------------------*/
01860 void
01861 uip_send(const void *data, int len)
01862 {
01863    if(len > 0) {
01864       uip_slen = len;
01865       if(data != uip_sappdata) {
01866          memcpy(uip_sappdata, (data), uip_slen);
01867       }
01868    }
01869 }
01870 /** @} */