uIP 1.0
|
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 /** @} */