Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
tcp.c
00001 /* 00002 * Copyright (c) 2013-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "nsconfig.h" 00019 #include "string.h" 00020 #include "ns_types.h" 00021 #include "ns_trace.h" 00022 #include "eventOS_event.h" 00023 #include "Core/include/socket.h" 00024 #include "nsdynmemLIB.h" 00025 #include "ip_fsc.h" 00026 #include "ns_sha256.h" 00027 #include "NWK_INTERFACE/Include/protocol.h" 00028 #include "NWK_INTERFACE/Include/protocol_timer.h" 00029 #include "randLIB.h" 00030 #include "Common_Protocols/ipv6_constants.h" 00031 #include "Common_Protocols/ipv6_flow.h" 00032 #include "Common_Protocols/tcp.h" 00033 #include "NWK_INTERFACE/Include/protocol_stats.h" 00034 #include "common_functions.h" 00035 #include "net_interface.h" 00036 00037 #ifndef NO_TCP 00038 #define TRACE_GROUP "tcp" 00039 00040 /* Standard flags for outgoing packets in each state, with FIN applying 00041 * only if there is no more data in queue (because the state is entered 00042 * while queue not empty). 00043 */ 00044 static const uint8_t state_flag[TCP_STATES] = 00045 { 00046 [TCP_STATE_CLOSED] = TCP_FLAG_RST | TCP_FLAG_ACK, 00047 [TCP_STATE_SYN_SENT] = TCP_FLAG_SYN, 00048 [TCP_STATE_SYN_RECEIVED] = TCP_FLAG_SYN | TCP_FLAG_ACK, 00049 [TCP_STATE_ESTABLISHED] = TCP_FLAG_ACK, 00050 [TCP_STATE_FIN_WAIT_1] = TCP_FLAG_FIN | TCP_FLAG_ACK, 00051 [TCP_STATE_FIN_WAIT_2] = TCP_FLAG_ACK, 00052 [TCP_STATE_CLOSE_WAIT] = TCP_FLAG_ACK, 00053 [TCP_STATE_LAST_ACK] = TCP_FLAG_FIN | TCP_FLAG_ACK, 00054 [TCP_STATE_CLOSING] = TCP_FLAG_FIN | TCP_FLAG_ACK, 00055 [TCP_STATE_TIME_WAIT] = TCP_FLAG_ACK 00056 }; 00057 00058 #ifdef TCP_TEST 00059 static uint8_t rx_drops[TCP_STATES]; 00060 static uint8_t tx_drops[TCP_STATES]; 00061 00062 /*Test - functions*/ 00063 int8_t tcp_test_drop_tx(int state, uint8_t count) { 00064 00065 tx_drops[state] = count; 00066 return 0; 00067 } 00068 00069 int8_t tcp_test_drop_rx(int state, uint8_t count) { 00070 00071 rx_drops[state] = count; 00072 return 0; 00073 } 00074 00075 void tcp_test_drop_reset() { 00076 00077 memset(rx_drops, 0, sizeof rx_drops); 00078 memset(tx_drops, 0, sizeof tx_drops); 00079 00080 } 00081 #endif 00082 00083 #ifdef FEA_TRACE_SUPPORT 00084 static const char *trace_tcp_flags(uint16_t flags) 00085 { 00086 static char buf[9]; 00087 buf[0] = flags & TCP_FLAG_CWR ? 'C' : '-'; 00088 buf[1] = flags & TCP_FLAG_ECE ? 'E' : '-'; 00089 buf[2] = flags & TCP_FLAG_URG ? 'U' : '-'; 00090 buf[3] = flags & TCP_FLAG_ACK ? 'A' : '-'; 00091 buf[4] = flags & TCP_FLAG_PSH ? 'P' : '-'; 00092 buf[5] = flags & TCP_FLAG_RST ? 'R' : '-'; 00093 buf[6] = flags & TCP_FLAG_SYN ? 'S' : '-'; 00094 buf[7] = flags & TCP_FLAG_FIN ? 'F' : '-'; 00095 return buf; 00096 } 00097 #endif 00098 00099 static void tcp_timer_handle(uint16_t ticksUpdate); 00100 static void tcp_segment_start(tcp_session_t *tcp_info, bool timeout); 00101 static void tcp_uack_segment(buffer_t *buf, tcp_session_t *tcp_info, uint16_t header_length); 00102 static buffer_t *tcp_ack_buffer(tcp_session_t *tcp_info, uint16_t new_ack); 00103 static void tcp_ack_segment(uint32_t ack, tcp_session_t *tcp_info); 00104 static buffer_t *tcp_build_reset_packet(const sockaddr_t *dst_addr, const sockaddr_t *src_addr, uint32_t seq, uint32_t ack, uint8_t flag); 00105 static void tcp_session_established(protocol_interface_info_entry_t *cur, tcp_session_t *tcp_info); 00106 static void tcp_build(buffer_t *buf, tcp_session_t *tcp_info); 00107 00108 static uint16_t tcp_session_count; 00109 00110 #define TCP_FUNC_ENTRY_TRACE 00111 #ifdef TCP_FUNC_ENTRY_TRACE 00112 #define FUNC_ENTRY_TRACE tr_debug 00113 #else 00114 #define FUNC_ENTRY_TRACE(...) 00115 #endif 00116 00117 /* Returns true if min <= val <= max */ 00118 static bool tcp_seq_in_range(uint32_t min, uint32_t val, uint32_t max) 00119 { 00120 if (min <= max) { 00121 return min <= val && val <= max; 00122 } else { 00123 return min <= val || val <= max; 00124 } 00125 } 00126 /* Returns true if val > low */ 00127 static bool tcp_seq_gt(uint32_t val, uint32_t low) 00128 { 00129 return common_serial_number_greater_32(val, low); 00130 } 00131 00132 /* Returns true if val < high */ 00133 static bool tcp_seq_lt(uint32_t val, uint32_t high) 00134 { 00135 return common_serial_number_greater_32(high, val); 00136 } 00137 00138 /* Returns true if val >= min */ 00139 static bool tcp_seq_ge(uint32_t val, uint32_t min) 00140 { 00141 return val == min || common_serial_number_greater_32(val, min); 00142 } 00143 00144 #if 0 00145 /* Returns true if val <= max */ 00146 static bool tcp_seq_le(uint32_t val, uint32_t max) 00147 { 00148 return val == max || common_serial_number_greater_32(max, val); 00149 } 00150 #endif 00151 00152 /* Delete TCP session (optionally with error) */ 00153 static tcp_session_t *tcp_session_delete_with_error(tcp_session_t *tcp_info, uint8_t error) 00154 { 00155 socket_t *socket = tcp_info->inet_pcb ->socket; 00156 FUNC_ENTRY_TRACE("tcp_session_delete_with_error(), s=%d", socket->id ); 00157 socket_connection_abandoned(socket, tcp_info->interface->id , error); 00158 return tcp_session_ptr_free(tcp_info); 00159 } 00160 00161 static tcp_session_t *tcp_session_delete(tcp_session_t *tcp_info) 00162 { 00163 return tcp_session_delete_with_error(tcp_info, 0); 00164 } 00165 00166 /* Socket released by application */ 00167 void tcp_socket_released(tcp_session_t *cur) 00168 { 00169 FUNC_ENTRY_TRACE("tcp_socket_released() s=%d", cur->inet_pcb->socket->id); 00170 00171 /* Most clear-up already done, including tcp_session_close */ 00172 00173 /* Only thing to do is start "orphaned session" timer for FIN-WAIT-2 */ 00174 00175 if (cur->state == TCP_STATE_FIN_WAIT_2) { 00176 cur->timer = TCP_FIN_WAIT_2_TIMEOUT; 00177 } 00178 } 00179 00180 /* RFC 6528 Initial Sequence Number generation */ 00181 static uint32_t tcp_generate_isn(const uint8_t local_ip[static 16], uint16_t local_port, 00182 const uint8_t remote_ip[static 16], uint16_t remote_port) 00183 { 00184 static struct { 00185 uint8_t key[16]; 00186 bool initialised; 00187 } secret; 00188 static uint32_t fudge; 00189 00190 tr_debug("isn [%s]:%u -> [%s]:%u", trace_ipv6(local_ip), local_port, trace_ipv6(remote_ip), remote_port); 00191 00192 if (!secret.initialised) { 00193 /* randLIB should do - we're not after total cryptographic security, and 00194 * it should have been seeded from true randomness. An alternative would 00195 * be the secret given to addr_opaque_iid_key_set, but that would have 00196 * the effect of restarting with the same ISN after reboot. Random secret 00197 * means we start with a random ISN after reboot. 00198 */ 00199 randLIB_get_n_bytes_random(secret.key, sizeof secret.key); 00200 secret.initialised = true; 00201 tr_debug("secret init"); 00202 } 00203 00204 ns_sha256_context ctx; 00205 uint32_t F; 00206 ns_sha256_init(&ctx); 00207 ns_sha256_starts(&ctx); 00208 ns_sha256_update(&ctx, local_ip, 16); 00209 ns_sha256_update(&ctx, &local_port, sizeof local_port); 00210 ns_sha256_update(&ctx, remote_ip, 16); 00211 ns_sha256_update(&ctx, &remote_port, sizeof remote_port); 00212 ns_sha256_update(&ctx, secret.key, sizeof secret.key); 00213 ns_sha256_finish_nbits(&ctx, &F, 32); 00214 ns_sha256_free(&ctx); 00215 00216 /* Want to make sure we're always going up in successive connects, so 00217 * add a positive fraction of a tick every time. 00218 */ 00219 fudge += randLIB_get_8bit() + 1; 00220 00221 /* Monotonic time is 100ms ticks, so *25000 converts to 4us ticks */ 00222 uint32_t M = 25000 * protocol_core_monotonic_time + fudge; 00223 tr_debug("ISN=%"PRIx32" M=%"PRIx32" F=%"PRIx32" fudge=%"PRIx32, M + F, M, F, fudge); 00224 00225 return M + F; 00226 } 00227 00228 static void tcp_set_metadata(const inet_pcb_t *inet_pcb, buffer_t *buf) 00229 { 00230 /* Fill in metadata from inet_pcb. Everything used here should be cloned into 00231 * new PCBs created by incoming connections from the listening PCB, so that it's 00232 * possible to set options for the first transactions prior to accept(). 00233 */ 00234 buf->options .traffic_class = inet_pcb->tclass; 00235 buf->options .flow_label = inet_pcb->flow_label; 00236 buf->options .ll_security_bypass_tx = (inet_pcb->link_layer_security == 0); 00237 buf->options .ipv6_dontfrag = true; // Sanity-checking - if doing MTU work right, fragmentation should never be needed 00238 socket_inet_pcb_set_buffer_hop_limit(inet_pcb, buf, NULL); 00239 } 00240 00241 static void tcp_rethink_mss(tcp_session_t *tcp_info) 00242 { 00243 tcp_info->send_mss_eff = tcp_info->send_mss_peer; 00244 if (tcp_info->interface->nwk_id == IF_6LoWPAN) { 00245 // This conservatism also covers up worries about extension headers, 00246 // RPL tunnelling... 00247 if (tcp_info->send_mss_eff > TCP_LOWPAN_MSS_LIMIT) { 00248 tcp_info->send_mss_eff = TCP_LOWPAN_MSS_LIMIT; 00249 } 00250 } 00251 /* No proper PMTUD at the minute... */ 00252 if (tcp_info->send_mss_eff > IPV6_MIN_LINK_MTU - 20 - 40) { 00253 tcp_info->send_mss_eff = IPV6_MIN_LINK_MTU - 20 - 40; 00254 } 00255 00256 /* Don't get totally silly */ 00257 if (tcp_info->send_mss_eff < 64) { 00258 tcp_info->send_mss_eff = 64; 00259 } 00260 } 00261 00262 /* Allocate new TCP socket data structure */ 00263 tcp_session_t *tcp_session_ptr_allocate(inet_pcb_t *inet_pcb, tcp_session_t *from_time_wait) 00264 { 00265 tcp_session_t *cur = NULL; 00266 FUNC_ENTRY_TRACE("tcp_session_ptr_allocate() s=%d", inet_pcb->socket->id ); 00267 00268 cur = ns_dyn_mem_alloc(sizeof(tcp_session_t)); 00269 if (cur) { 00270 if (++tcp_session_count == 1) { 00271 protocol_timer_start(PROTOCOL_TIMER_TCP_TIM, tcp_timer_handle, TCP_TIMER_PERIOD); 00272 } 00273 cur->passive_open = false; 00274 cur->interface = 0; 00275 cur->busy = false; 00276 cur->persist = false; 00277 cur->sent_fin = false; 00278 cur->receive_next = 0; 00279 cur->receive_adv = 0; 00280 cur->send_window = 0; 00281 if (from_time_wait) { 00282 cur->send_next = from_time_wait->send_next + UINT32_C(250000) + randLIB_get_16bit(); 00283 tcp_session_delete(from_time_wait); 00284 } else { 00285 cur->send_next = tcp_generate_isn(inet_pcb->local_address , inet_pcb->local_port , inet_pcb->remote_address , inet_pcb->remote_port ); 00286 } 00287 cur->send_unacknowledged = cur->send_next; 00288 cur->state = TCP_STATE_CLOSED; 00289 cur->timer = 0; 00290 cur->retry = 0; 00291 cur->inet_pcb = inet_pcb; 00292 cur->srtt8 = INT16_MAX; // indicates no sample yet 00293 cur->srttvar4 = INT16_MAX; 00294 cur->rto = TCP_INITIAL_RTO; 00295 cur->receive_mss = IPV6_MIN_LINK_MTU - 20 - 40; 00296 cur->send_mss_eff = 536; 00297 cur->send_mss_peer = 536; 00298 inet_pcb->session = cur; 00299 socket_reference(inet_pcb->socket); 00300 } 00301 return cur; 00302 } 00303 00304 /* Free TCP session pointer */ 00305 tcp_session_t *tcp_session_ptr_free(tcp_session_t *tcp_info) 00306 { 00307 socket_t *so = tcp_info->inet_pcb ->socket; 00308 FUNC_ENTRY_TRACE("tcp_session_ptr_free() s=%d", so->id ); 00309 tcp_info->inet_pcb->session = NULL; 00310 so->flags |= SOCKET_FLAG_CANT_RECV_MORE | SOCKET_FLAG_SHUT_WR; 00311 // This could free both the inet PCB and the socket - do not reference further 00312 socket_dereference(so); 00313 tcp_info->inet_pcb = NULL; 00314 00315 ns_dyn_mem_free(tcp_info); 00316 00317 if (--tcp_session_count == 0) { 00318 protocol_timer_stop(PROTOCOL_TIMER_TCP_TIM); 00319 } 00320 00321 return NULL; 00322 } 00323 00324 tcp_error tcp_session_send(tcp_session_t *tcp_info, buffer_t *buf) 00325 { 00326 FUNC_ENTRY_TRACE("tcp_session_send()"); 00327 00328 if (tcp_info->state != TCP_STATE_ESTABLISHED && tcp_info->state != TCP_STATE_CLOSE_WAIT) { 00329 tr_error("tcp error, bad state %d", tcp_info->state); 00330 return TCP_ERROR_WRONG_STATE; 00331 } 00332 00333 /* Wipe out the socket ID - never having socket ID set on down buffers ensures no callbacks are generated by core layers */ 00334 buffer_socket_set(buf, NULL); 00335 buf->session_ptr = NULL; 00336 sockbuf_append_and_compress(&tcp_info->inet_pcb->socket->sndq, buf); 00337 00338 if (!tcp_info->busy) { 00339 tcp_info->timer = 0; 00340 tcp_info->retry = 0; 00341 tcp_info->busy = true; 00342 tcp_segment_start(tcp_info, false); 00343 } 00344 00345 return TCP_ERROR_NO_ERROR; 00346 } 00347 00348 00349 /* Builds and returns a RST packet; frees incoming buffer; 00350 * if session is provided, deletes session and signals error to user 00351 */ 00352 static buffer_t *tcp_reset_response(tcp_session_t *tcp_info, uint8_t error, buffer_t *incoming_buf, uint32_t seq, uint32_t ack, uint8_t flags) 00353 { 00354 FUNC_ENTRY_TRACE("tcp_reset_response()"); 00355 buffer_t *rst_buffer; 00356 00357 rst_buffer = tcp_build_reset_packet(&incoming_buf->src_sa , &incoming_buf->dst_sa , seq, ack, flags); 00358 if (rst_buffer) { 00359 rst_buffer->interface = incoming_buf->interface ; 00360 if (tcp_info) { 00361 tcp_set_metadata(tcp_info->inet_pcb, rst_buffer); 00362 } 00363 } 00364 buffer_free(incoming_buf); 00365 if (tcp_info) { 00366 tcp_session_delete_with_error(tcp_info, error); 00367 } 00368 00369 return (rst_buffer); 00370 } 00371 00372 static buffer_t *tcp_build_reset_packet(const sockaddr_t *dst_addr, const sockaddr_t *src_addr, uint32_t seq, uint32_t ack, uint8_t flags) 00373 { 00374 buffer_t *buf; 00375 uint8_t *ptr; 00376 00377 FUNC_ENTRY_TRACE("tcp_build_reset_packet()"); 00378 buf = buffer_get(20); 00379 00380 if (!buf) { 00381 return NULL; 00382 } 00383 00384 buf->dst_sa = *dst_addr; 00385 buf->src_sa = *src_addr; 00386 buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_TCP | B_TO_IPV6); 00387 buf->options .type = IPV6_NH_TCP; 00388 00389 ptr = buffer_data_pointer(buf); 00390 ptr = common_write_16_bit(src_addr->port , ptr); 00391 ptr = common_write_16_bit(dst_addr->port , ptr); 00392 ptr = common_write_32_bit(seq, ptr); 00393 ptr = common_write_32_bit(ack, ptr); 00394 *ptr++ = 5 << 4; /* data offset */ 00395 *ptr++ = flags; 00396 ptr = common_write_16_bit(0, ptr); 00397 ptr = common_write_32_bit(0, ptr); /* checksum and URG pointer */ 00398 buffer_data_end_set(buf, ptr); 00399 00400 /* calculate checksum */ 00401 common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_TCP), buffer_data_pointer(buf) + 16); 00402 00403 return (buf); 00404 } 00405 00406 static void tcp_session_send_reset_to_abort_connection(tcp_session_t *tcp_info) { 00407 00408 sockaddr_t dst, src; 00409 memcpy(&dst.address , tcp_info->inet_pcb->remote_address, 16); 00410 memcpy(&src.address , tcp_info->inet_pcb->local_address, 16); 00411 dst.addr_type = ADDR_IPV6 ; 00412 src.addr_type = ADDR_IPV6 ; 00413 dst.port = tcp_info->inet_pcb->remote_port; 00414 src.port = tcp_info->inet_pcb->local_port; 00415 buffer_t *buf = tcp_build_reset_packet(&dst, &src, tcp_info->send_next, 0, TCP_FLAG_RST); 00416 if (!buf) { 00417 return; 00418 } 00419 00420 buf->interface = tcp_info->interface; 00421 tcp_set_metadata(tcp_info->inet_pcb, buf); 00422 /* Don't fill in socket ID, or app would get a TX DONE callback for this */ 00423 protocol_push(buf); 00424 } 00425 00426 /** 00427 * \brief Function used for starting a TCP connection 00428 * to a remote server. 00429 * 00430 * \param tcp_session pointer to allocated tcp session 00431 * \param dst_address_ptr pointer to connection dstination address 00432 * \param dst_port connection destination port 00433 * 00434 * \return TCP_ERROR_NO_ERROR 00435 * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR 00436 */ 00437 00438 tcp_error tcp_session_open(tcp_session_t *tcp_session) 00439 { 00440 buffer_t *new_buffer; 00441 protocol_interface_info_entry_t *cur_interface; 00442 FUNC_ENTRY_TRACE("tcp_session_open()"); 00443 00444 if (tcp_session->state != TCP_STATE_CLOSED && tcp_session->state != TCP_STATE_LISTEN) { 00445 return TCP_ERROR_WRONG_STATE; 00446 } 00447 00448 new_buffer = buffer_get(127); 00449 if (!new_buffer) { 00450 return TCP_ERROR_BUFFER_ALLOCATION_ERROR; 00451 } 00452 00453 new_buffer->dst_sa .port = tcp_session->inet_pcb->remote_port; 00454 new_buffer->dst_sa .addr_type = ADDR_IPV6 ; 00455 memcpy(new_buffer->dst_sa .address , tcp_session->inet_pcb->remote_address, 16); 00456 00457 cur_interface = socket_interface_determine(tcp_session->inet_pcb->socket, new_buffer); 00458 00459 if (!cur_interface) { 00460 buffer_free(new_buffer); 00461 return TCP_ERROR_BUFFER_ALLOCATION_ERROR; 00462 } 00463 00464 /** 00465 * Save interface id and type 00466 */ 00467 new_buffer->interface = cur_interface; 00468 tcp_session->interface = cur_interface; 00469 00470 new_buffer->interface ->id = cur_interface->id; 00471 tcp_session->interface->id = cur_interface->id; 00472 00473 if (tcp_session->interface->nwk_id == IF_6LoWPAN) { 00474 if (tcp_session->receive_mss > TCP_LOWPAN_MSS_LIMIT) { 00475 tcp_session->receive_mss = TCP_LOWPAN_MSS_LIMIT; 00476 } 00477 } 00478 00479 tcp_session->state = TCP_STATE_SYN_SENT; 00480 new_buffer->options .code = TCP_FLAG_SYN; 00481 00482 tcp_build(new_buffer, tcp_session); 00483 return TCP_ERROR_NO_ERROR; 00484 00485 } 00486 00487 tcp_error tcp_session_shutdown_read(tcp_session_t *tcp_session) 00488 { 00489 FUNC_ENTRY_TRACE("tcp_session_shutdown_read"); 00490 00491 if (tcp_session->inet_pcb->socket->rcvq.data_bytes != 0) { 00492 // Force a reset shutdown (RFC 1122 4.2.2.13, RFC 2525 2.17) 00493 tr_warn("Shutdown read with pending data"); 00494 return tcp_session_abort(tcp_session); 00495 } 00496 00497 return TCP_ERROR_NO_ERROR; 00498 } 00499 00500 /** 00501 * \brief Function used for closing a TCP connection. 00502 * 00503 * If it returns TCP_ERROR_NO_ERROR, TCP session is persisting. 00504 * Any error return means TCP session has been deleted. 00505 * 00506 * \param tcp_session pointer to indicate tcp session 00507 * 00508 * \return TCP_ERROR_NO_ERROR 00509 * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR 00510 */ 00511 00512 tcp_error tcp_session_close(tcp_session_t *tcp_session) 00513 { 00514 FUNC_ENTRY_TRACE("tcp_session_close"); 00515 switch (tcp_session->state) { 00516 case TCP_STATE_CLOSED: 00517 case TCP_STATE_LAST_ACK: 00518 case TCP_STATE_FIN_WAIT_1: 00519 case TCP_STATE_FIN_WAIT_2: 00520 case TCP_STATE_CLOSING: 00521 case TCP_STATE_TIME_WAIT: 00522 return TCP_ERROR_NO_ERROR; 00523 case TCP_STATE_LISTEN: 00524 case TCP_STATE_SYN_SENT: 00525 default: 00526 tcp_session_delete(tcp_session); 00527 return TCP_SESSION_REMOVED; 00528 case TCP_STATE_SYN_RECEIVED: 00529 case TCP_STATE_ESTABLISHED: 00530 case TCP_STATE_CLOSE_WAIT: 00531 // Do the state change immediately, even if data 00532 // pending - this deals with the API changes. Data 00533 // output routines need to set flags appropriately. 00534 if (tcp_session->state == TCP_STATE_CLOSE_WAIT) { 00535 tcp_session->state = TCP_STATE_LAST_ACK; // RFC 1122 00536 tr_debug("sLA"); 00537 } else { 00538 tcp_session->state = TCP_STATE_FIN_WAIT_1; 00539 tr_debug("sFW"); 00540 } 00541 if (!tcp_session->busy) { 00542 tcp_session->busy = true; 00543 tcp_segment_start(tcp_session, false); 00544 } 00545 return TCP_ERROR_NO_ERROR; 00546 } 00547 } 00548 00549 tcp_error tcp_session_abort(tcp_session_t *tcp_session) 00550 { 00551 FUNC_ENTRY_TRACE("tcp_session_abort"); 00552 00553 switch (tcp_session->state) { 00554 case TCP_STATE_CLOSED: 00555 return TCP_ERROR_SOCKET_NOT_FOUND; 00556 case TCP_STATE_SYN_RECEIVED: 00557 case TCP_STATE_ESTABLISHED: 00558 case TCP_STATE_FIN_WAIT_1: 00559 case TCP_STATE_FIN_WAIT_2: 00560 case TCP_STATE_CLOSE_WAIT: 00561 tcp_session_send_reset_to_abort_connection(tcp_session); 00562 /* no break */ 00563 case TCP_STATE_LISTEN: 00564 case TCP_STATE_SYN_SENT: 00565 tcp_session_delete_with_error(tcp_session, SOCKET_CONNECTION_RESET); 00566 return TCP_ERROR_NO_ERROR; 00567 default: 00568 tcp_session_delete(tcp_session); 00569 return TCP_ERROR_NO_ERROR; 00570 } 00571 } 00572 00573 /** 00574 * \brief Function used to send TCP message 00575 * 00576 * Can be either used to send a data segment or FIN in case there 00577 * is no data. When retransmission is made, starts to sent from the 00578 * start of the unacknowledged data. 00579 * 00580 * \param tcp_info pointer to indicate tcp session 00581 * \param timeout triggered from timeout 00582 * 00583 * \return TCP_ERROR_NO_ERROR 00584 * \return TCP_ERROR_BUFFER_ALLOCATION_ERROR 00585 */ 00586 static void tcp_segment_start(tcp_session_t *tcp_info, bool timeout) 00587 { 00588 socket_t *so = tcp_info->inet_pcb ->socket; 00589 buffer_t *tx_data = ns_list_get_first(&so->sndq.bufs); 00590 buffer_t *buf; 00591 00592 FUNC_ENTRY_TRACE("tcp_segment_start() s=%d", so->id ); 00593 00594 if (timeout) { 00595 // If not same means that retransmission is made. Could be either 00596 // partial or full depending on what has been acknowledged. If data 00597 // is to be sent, sends always window size 00598 tcp_info->send_next = tcp_info->send_unacknowledged; 00599 tcp_info->sent_fin = false; 00600 } 00601 00602 uint16_t data_length; 00603 00604 if (!tx_data) { 00605 // Should only be called with no data if needing to send a SYN or FIN 00606 if ((state_flag[tcp_info->state] & TCP_FLAG_SYN) || 00607 ((state_flag[tcp_info->state] & TCP_FLAG_FIN) && !tcp_info->sent_fin)) { 00608 data_length = 0; 00609 tcp_info->persist = false; 00610 goto build; 00611 } else { 00612 tr_warn("unexpected tcp_segment_start"); 00613 return; 00614 } 00615 } 00616 00617 data_length = buffer_data_length(tx_data); 00618 if (data_length > tcp_info->send_mss_eff) { 00619 data_length = tcp_info->send_mss_eff; 00620 } 00621 /* Can transmit up to SND.UNA+SND.WND-1 */ 00622 /* Simplified by SND.UNA==SND.NXT */ 00623 if (data_length > tcp_info->send_window) { 00624 data_length = tcp_info->send_window; 00625 } 00626 00627 if (data_length == 0) { 00628 if (!timeout) { 00629 /* Start timer for probe */ 00630 tcp_info->persist = true; 00631 tcp_info->timer = tcp_info->rto; 00632 tcp_info->retry = 0; 00633 return; 00634 } else { 00635 // Think - why actually 1? Given we don't resegmentise, and end 00636 // up committed to sending a 1-byte segment in this situation, may 00637 // as well just go for send_mss_eff or 64 for our probe. No rule 00638 // against it. 00639 data_length = 1; 00640 } 00641 } else { 00642 tcp_info->persist = false; 00643 } 00644 00645 build: 00646 /* Create buffer for message */ 00647 buf = buffer_get(data_length); 00648 if (buf == NULL) { 00649 goto out; 00650 } 00651 00652 buf->dst_sa .port = tcp_info->inet_pcb->remote_port; 00653 buf->dst_sa .addr_type = ADDR_IPV6 ; 00654 memcpy(buf->dst_sa .address , tcp_info->inet_pcb->remote_address, 16); 00655 buf->src_sa .port = tcp_info->inet_pcb->local_port; 00656 buf->src_sa .addr_type = ADDR_IPV6 ; 00657 memcpy(buf->src_sa .address , tcp_info->inet_pcb->local_address, 16); 00658 00659 // Add data to message buffer, but do not remove it from socket buffer until 00660 // it is acked 00661 if (tx_data) { 00662 buffer_data_add(buf, buffer_data_pointer(tx_data), data_length); 00663 } 00664 00665 buf->interface = tcp_info->interface; 00666 00667 tcp_build(buf, tcp_info); 00668 out: 00669 /* Start retransmit timer (also covers buffer failure) */ 00670 tcp_info->timer = tcp_info->rto; 00671 } 00672 00673 00674 /** 00675 * \brief Function used for resenting segment after timeout. 00676 * 00677 * \param tcp_info identifies the connection 00678 */ 00679 00680 static tcp_session_t *tcp_resend_segment(tcp_session_t *tcp_info) 00681 { 00682 FUNC_ENTRY_TRACE("tcp_resend_segment()"); 00683 00684 if (tcp_info->retry >= (tcp_info->state < TCP_STATE_ESTABLISHED ? TCP_SYN_RETRIES : TCP_MAX_RETRIES)) { 00685 tr_debug("Too many retries"); 00686 return tcp_session_delete_with_error(tcp_info, SOCKET_TX_FAIL); 00687 } 00688 00689 if (++tcp_info->retry == TCP_PROBLEM_RETRIES) { 00690 socket_event_push(SOCKET_CONNECTION_PROBLEM, tcp_info->inet_pcb->socket, tcp_info->interface->id, NULL, 0); 00691 ipv6_neighbour_reachability_problem(tcp_info->inet_pcb->remote_address, tcp_info->interface->id); 00692 } 00693 00694 tcp_segment_start(tcp_info, true); 00695 00696 tr_debug("RE-TX, timer %d", tcp_info->timer); 00697 return tcp_info; 00698 } 00699 00700 static uint16_t tcp_compute_window_incr(tcp_session_t *tcp_info) 00701 { 00702 // Careful window adjustment (RFC 1122 et al) - don't move right edge 00703 // leftwards, and don't jump up in small steps 00704 int32_t window = sockbuf_space(&tcp_info->inet_pcb->socket->rcvq); 00705 if (window < 0) { 00706 window = 0; 00707 } 00708 if (window > 0xffff) { 00709 window = 0xffff; 00710 } 00711 if (window < (int32_t) (tcp_info->receive_adv - tcp_info->receive_next)) { 00712 // Don't move left 00713 return 0; 00714 } 00715 00716 // Don't make small increments (avoid Silly Window Syndrome) 00717 uint16_t incr = tcp_info->receive_next + window - tcp_info->receive_adv; 00718 if (incr > 0) { 00719 if (incr < tcp_info->inet_pcb->socket->rcvq.data_byte_limit / 2 && 00720 incr < tcp_info->send_mss_eff) { 00721 incr = 0; 00722 } else { 00723 tcp_info->receive_adv += incr; 00724 } 00725 } 00726 00727 return incr; 00728 } 00729 00730 void tcp_session_data_received(tcp_session_t *tcp_info) 00731 { 00732 // If this read nudges up the window, send an ack 00733 // Layering all a little wonky here, but this should roughly work. 00734 // Revisit when delayed ack infrastructure in place. 00735 if (tcp_compute_window_incr(tcp_info)) { 00736 buffer_t *buf = tcp_ack_buffer(tcp_info, 0); 00737 tcp_build(buf, tcp_info); 00738 } 00739 } 00740 00741 /** 00742 * \brief Function used for allocating buffer for ack segment. 00743 * 00744 * \param tcp_info identifies the connection 00745 * \param new_ack new bytes to be acknowledged 00746 * 00747 * \return allocated buffer on success 00748 * \return 0 pointer indicates an error 00749 */ 00750 00751 static buffer_t *tcp_ack_buffer(tcp_session_t *tcp_info, uint16_t new_ack) 00752 { 00753 /* make ack segment */ 00754 00755 buffer_t *new_buffer; 00756 FUNC_ENTRY_TRACE("tcp_ack_buffer() s=%d, new_ack=%d", tcp_info->inet_pcb->socket->id, new_ack); 00757 00758 new_buffer = buffer_get(0); 00759 if (!new_buffer) { 00760 return NULL; 00761 } 00762 00763 new_buffer->dst_sa .port = tcp_info->inet_pcb->remote_port; 00764 new_buffer->dst_sa .addr_type = ADDR_IPV6 ; 00765 memcpy(new_buffer->dst_sa .address , tcp_info->inet_pcb->remote_address, 16); 00766 new_buffer->src_sa .port = tcp_info->inet_pcb->local_port; 00767 new_buffer->src_sa .addr_type = ADDR_IPV6 ; 00768 memcpy(new_buffer->src_sa .address , tcp_info->inet_pcb->local_address, 16); 00769 00770 new_buffer->interface = tcp_info->interface; 00771 new_buffer->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_TCP); 00772 new_buffer->options .code = 0xff; 00773 tcp_info->receive_next += new_ack; 00774 00775 return new_buffer; 00776 } 00777 00778 /** 00779 * \brief Function used for saving segments needing to be acknowledged. 00780 * 00781 * \param buf buffer to be acknowledged 00782 * \param tcp_info identifies the connection 00783 */ 00784 00785 static void tcp_uack_segment(buffer_t *buf, tcp_session_t *tcp_info, uint16_t header_length) 00786 { 00787 FUNC_ENTRY_TRACE("tcp_uack_segment() s=%d", tcp_info->inet_pcb->socket->id); 00788 00789 uint16_t seg_size = buffer_data_length(buf) - header_length; 00790 if (buf->options .code & TCP_FLAG_SYN) { 00791 seg_size++; 00792 } 00793 if (buf->options .code & TCP_FLAG_FIN) { 00794 seg_size++; 00795 if (tcp_info->sent_fin) { 00796 tr_err("sent 2 FINs"); 00797 } 00798 tcp_info->sent_fin = true; 00799 } 00800 00801 if (seg_size == 0) { 00802 return; 00803 } 00804 00805 tcp_info->send_next += seg_size; 00806 if (tcp_info->timer == 0) { 00807 tcp_info->timer = tcp_info->rto; 00808 } 00809 00810 tcp_info->busy = true; 00811 } 00812 00813 00814 /** 00815 * \brief Peer has acknowledged data. 00816 * 00817 * \param ack sequence being acknowledged 00818 * \param tcp_info identifies the connection 00819 * 00820 */ 00821 00822 static void tcp_ack_segment(uint32_t ack, tcp_session_t *tcp_info) 00823 { 00824 FUNC_ENTRY_TRACE("tcp_ack_segment() s=%d", (int)tcp_info->inet_pcb->socket->id); 00825 00826 socket_t *so = tcp_info->inet_pcb ->socket; 00827 00828 uint32_t acked_bytes; 00829 acked_bytes = ack - tcp_info->send_unacknowledged; 00830 00831 tr_debug("tcp_ack_segment() acked %"PRIu32, acked_bytes); 00832 00833 // Do not allow to remove more than sent data from buffer 00834 if (acked_bytes > so->sndq.data_bytes) { 00835 acked_bytes = so->sndq.data_bytes; 00836 } 00837 sockbuf_drop(&so->sndq, acked_bytes); 00838 tr_debug("tcp_ack_segment() socket remove from buffer %"PRIu32" data to be sent %"PRIu32, acked_bytes, so->sndq.data_bytes); 00839 00840 tcp_info->send_unacknowledged = ack; 00841 00842 ipv6_neighbour_reachability_confirmation(tcp_info->inet_pcb->remote_address, tcp_info->interface->id); 00843 00844 uint32_t remaining_bytes = so->sndq.data_bytes; 00845 00846 if (tcp_info->state >= TCP_STATE_ESTABLISHED) { 00847 // Could consider not sending event if space below low water? 00848 socket_event_push(SOCKET_TX_DONE, so, tcp_info->interface->id , tcp_info, remaining_bytes); 00849 } 00850 00851 // All data that has been send is acked so sent next segment 00852 if (ack == tcp_info->send_next) { 00853 00854 // Made when all data has been acked 00855 // Could do this only periodically, based on a timer, for speed 00856 // Or, as RFC 4861 suggests, once per RTT. Which RTO calculation is, 00857 // so keep this with the RTO recalculation code. 00858 if (tcp_info->retry == 0 && !tcp_info->persist) { 00859 /* Update RTT - RFC 6298, using tricks in Van Jacoben's 1988 paper */ 00860 /* Most variables held as scaled 16-bit positive signed integers */ 00861 int16_t R = (int16_t) tcp_info->rto - (int16_t)tcp_info->timer; 00862 if (R < 0) { 00863 tr_err("R=%"PRId16, R); 00864 R = 0; 00865 } 00866 if (tcp_info->srtt8 == INT16_MAX) { 00867 tcp_info->srtt8 = R << 3; // srtt := R 00868 tcp_info->srttvar4 = R << (2-1); // rttvar := R / 2 00869 } else { 00870 /* 1/8 gain and scaling on smoothed RTT measurement */ 00871 int16_t R_diff = R - (tcp_info->srtt8 >> 3); 00872 tcp_info->srtt8 += R_diff; 00873 if (R_diff < 0) { 00874 R_diff = -R_diff; 00875 } 00876 /* 1/4 gain and scaling on smoothed RTTVAR measurement */ 00877 int16_t V_diff = R_diff - (tcp_info->srttvar4 >> 2); 00878 tcp_info->srttvar4 += V_diff; 00879 } 00880 /* RTO = RTT + 4 * RTTVAR - rounds nicely as described by Van Jacobsen */ 00881 tcp_info->rto = (tcp_info->srtt8 >> 3) + tcp_info->srttvar4; 00882 if (tcp_info->rto < TCP_MINIMUM_RTO) { 00883 tcp_info->rto = TCP_MINIMUM_RTO; 00884 } 00885 //tr_debug("R=%"PRId16" rto=%"PRIu16" srtt8=%"PRId16" rttvar4=%"PRId16, R, tcp_info->rto, tcp_info->srtt8, tcp_info->srttvar4); 00886 //tr_debug("R=%.2f rto=%.2f srtt=%.2f rttvar=%.2f", R * .150F, tcp_info->rto * .150F, tcp_info->srtt8 * (.15F/8), tcp_info->srttvar4 * (.15F/4)); 00887 } 00888 tcp_info->retry = 0; 00889 tcp_info->timer = 0; 00890 00891 if (remaining_bytes || 00892 ((state_flag[tcp_info->state] & TCP_FLAG_FIN) && !tcp_info->sent_fin)) { 00893 tcp_segment_start(tcp_info, false); 00894 } else { 00895 tcp_info->busy = false; 00896 } 00897 } 00898 } 00899 00900 00901 /** 00902 * \brief Function called every time timer ticks. 00903 */ 00904 00905 static void tcp_timer_handle(uint16_t ticksUpdate) 00906 { 00907 arm_event_s event = { 00908 .receiver = socket_event_handler_id_get(), 00909 .sender = 0, 00910 .event_type = ARM_SOCKET_TCP_TIMER_CB, 00911 .event_data = ticksUpdate, 00912 .data_ptr = NULL, 00913 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00914 }; 00915 if (eventOS_event_send(&event) != 0) { 00916 tr_error("tcp_timer_handle(): event send failed"); 00917 } 00918 } 00919 00920 /** 00921 * \brief Function used for handling time events. 00922 */ 00923 00924 void tcp_handle_time_event(uint16_t tickUpdate) 00925 { 00926 if (tcp_session_count == 0) { 00927 return; 00928 } 00929 00930 ns_list_foreach_safe(socket_t, socket, &socket_list) { 00931 if (!socket_is_ipv6(socket) || socket->type != SOCKET_TYPE_STREAM) { 00932 continue; 00933 } 00934 inet_pcb_t *inet_pcb = socket->inet_pcb ; 00935 tcp_session_t *cur = inet_pcb->session ; 00936 if (cur && cur->timer) { 00937 if (cur->timer > tickUpdate) { 00938 cur->timer -= tickUpdate; 00939 } else { 00940 cur->timer = 0; 00941 if (inet_pcb->socket->flags & SOCKET_LISTEN_STATE) { 00942 //shouldn't happen 00943 } else if (cur->state == TCP_STATE_CLOSED) { 00944 //tcp_timers_active &= ~the_bit; 00945 } else if (cur->state == TCP_STATE_TIME_WAIT) { 00946 //tr_debug("Timewait --> Close"); 00947 tcp_session_delete(cur); 00948 } else { 00949 if (cur->busy) { 00950 cur->rto *= 2; 00951 if (cur->rto > TCP_MAXIMUM_RTO) { 00952 cur->rto = TCP_MAXIMUM_RTO; 00953 } 00954 cur = tcp_resend_segment(cur); 00955 } else if (cur->state == TCP_STATE_FIN_WAIT_2) { 00956 if (inet_pcb->socket->flags & SOCKET_FLAG_CLOSED) { 00957 tr_debug("sTW No Fin from host yet"); // Timeout shouldn't happen if socket is still open, so logically no event needed 00958 cur->state = TCP_STATE_TIME_WAIT; 00959 cur->timer = TCP_TIME_WAIT_TO_CLOSE; 00960 } else { 00961 tr_err("FW2 timeout with socket open"); 00962 } 00963 } 00964 } 00965 } 00966 } 00967 } 00968 00969 // XXX is this right? Surely should check current session list. 00970 // Guess we just get one more tick though, as we won't re-set next time. 00971 protocol_timer_start(PROTOCOL_TIMER_TCP_TIM, tcp_timer_handle, TCP_TIMER_PERIOD); 00972 } 00973 00974 /* find listen socket from socket instances */ 00975 static socket_t *tcp_find_listen_socket(const uint8_t addr[static 16], uint16_t port) 00976 { 00977 FUNC_ENTRY_TRACE("tcp_find_listen_socket() %d", port); 00978 ns_list_foreach(socket_t, so, &socket_list) { 00979 if ((so->flags & SOCKET_LISTEN_STATE) && 00980 socket_is_ipv6(so) && 00981 so->inet_pcb ->local_port == port && 00982 (addr_ipv6_equal(so->inet_pcb ->local_address , ns_in6addr_any) || 00983 addr_ipv6_equal(so->inet_pcb ->local_address , addr)) 00984 ) { 00985 return so; 00986 } 00987 } 00988 00989 return NULL; 00990 } 00991 00992 /** 00993 * \brief Function used for sending data through TCP. 00994 * 00995 * \param buf buffer to be sent 00996 * \param tcp_info points to TCP session 00997 * 00998 * Input: data = TCP payload 00999 * options.code = TCP flags (or 0 meaning "normal data from socket" or 0xFF meaning "ACK-only segment") 01000 * src_sa and dst_sa need not be set 01001 * Output to IP down: 01002 * data = IP payload 01003 * src_sa and dst_sa addresses and ports filled in from session 01004 * options.type = IPV6_NH_TCP 01005 * 01006 */ 01007 01008 static void tcp_build(buffer_t *buf, tcp_session_t *tcp_info) 01009 { 01010 uint16_t header_length = 20; 01011 uint8_t *ptr; 01012 01013 if (!buf) { 01014 return; 01015 } 01016 01017 if (!tcp_info) { 01018 buffer_free(buf); 01019 return; 01020 } 01021 01022 FUNC_ENTRY_TRACE("tcp_build() s=%d", tcp_info->inet_pcb->socket->id); 01023 01024 if (!tcp_info) { 01025 tr_error("DW No Session: dst: %s, src port: %d, dst port: %d", tr_ipv6(buf->dst_sa .address ), buf->src_sa .port , 01026 buf->dst_sa .port ); 01027 buffer_free(buf); 01028 return; 01029 } 01030 01031 if (buffer_data_length(buf) != 0 && tcp_info->sent_fin) { 01032 tr_error("TCP:DW send fail by state %02x", tcp_info->state); 01033 buffer_free(buf); 01034 return; 01035 } 01036 01037 //Set Flags 01038 if (buf->options .code ) { 01039 /* options.code contains TCP flags when used with TCP */ 01040 if (buf->options .code == 0xff) { 01041 /* code == 0xff if ACK only */ 01042 buf->options .code = TCP_FLAG_ACK; 01043 } 01044 //tr_debug("options from icmp"); 01045 } else { 01046 /* data send request from socket */ 01047 buf->options .code = state_flag[tcp_info->state]; 01048 uint16_t buf_len = buffer_data_length(buf); 01049 if (tcp_info->inet_pcb->socket->sndq.data_bytes <= buf_len) { 01050 /* push data if we have no more (RFC 1122 4.2.2.2) */ 01051 if (buffer_data_length(buf) != 0) { 01052 buf->options .code |= TCP_FLAG_PSH; 01053 } 01054 } else { 01055 /* Close advances state even while outstanding data (more like BSD 01056 * than RFC 793), so make sure FIN flag only actually sent when no 01057 * more data */ 01058 buf->options .code &= ~TCP_FLAG_FIN; 01059 } 01060 } 01061 01062 if (buf->options .code != 0xff) { 01063 if (buf->options .code & TCP_FLAG_SYN) { 01064 header_length += 4; 01065 } 01066 } 01067 01068 buf = buffer_headroom(buf, header_length); 01069 01070 if (!buf) { 01071 tr_error("TCP_DW:HeadROOM Fail"); 01072 return; 01073 } 01074 01075 ptr = buffer_data_reserve_header(buf, header_length); 01076 01077 ptr = common_write_16_bit(tcp_info->inet_pcb->local_port, ptr); 01078 ptr = common_write_16_bit(tcp_info->inet_pcb->remote_port, ptr); 01079 01080 ptr = common_write_32_bit(tcp_info->send_next, ptr); 01081 ptr = common_write_32_bit(tcp_info->receive_next, ptr); 01082 01083 *ptr++ = header_length << 2; /* data offset */ 01084 01085 *ptr++ = buf->options .code ; 01086 01087 tcp_compute_window_incr(tcp_info); 01088 01089 ptr = common_write_16_bit(tcp_info->receive_adv - tcp_info->receive_next, ptr); 01090 01091 ptr = common_write_32_bit(0, ptr); /* checksum and URG pointer */ 01092 01093 /* Advertise a minimal MSS based on minimum IPv6 MTU; keeping it simple for 01094 * now, rather than actually looking at the real link MTUs. See RFC 6991, 01095 * RFC 1191, etc. 01096 */ 01097 if (buf->options .code & TCP_FLAG_SYN) { 01098 *ptr++ = TCP_OPTION_MSS; 01099 *ptr++ = 4; // option length 01100 ptr = common_write_16_bit(tcp_info->receive_mss, ptr); 01101 } 01102 01103 memcpy(buf->dst_sa .address , tcp_info->inet_pcb->remote_address, 16); 01104 buf->dst_sa .port = tcp_info->inet_pcb->remote_port; 01105 buf->dst_sa .addr_type = ADDR_IPV6 ; 01106 memcpy(buf->src_sa .address , tcp_info->inet_pcb->local_address, 16); 01107 buf->src_sa .port = tcp_info->inet_pcb->local_port; 01108 buf->src_sa .addr_type = ADDR_IPV6 ; 01109 01110 /* calculate checksum */ 01111 common_write_16_bit(buffer_ipv6_fcf(buf, IPV6_NH_TCP), buffer_data_pointer(buf) + 16); 01112 01113 tcp_uack_segment(buf, tcp_info, header_length); 01114 01115 buf->info = (buffer_info_t)(B_FROM_TCP | B_TO_IPV6 | B_DIR_DOWN); 01116 buf->options .type = IPV6_NH_TCP; 01117 buf->options .code = 0; 01118 01119 tcp_set_metadata(tcp_info->inet_pcb, buf); 01120 01121 #ifdef TCP_TEST 01122 if (tx_drops[tcp_info->state]) { 01123 tx_drops[tcp_info->state]--; 01124 tr_info("TX drop %s", tcp_state_name(tcp_info)); 01125 socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL); 01126 return; 01127 } 01128 #endif 01129 01130 //tr_debug("DW buf_len=%d", buffer_data_length(buf)); 01131 protocol_push(buf); 01132 } 01133 01134 static void tcp_session_established(protocol_interface_info_entry_t *cur, tcp_session_t *tcp_info) 01135 { 01136 tr_debug("UP:sES"); 01137 socket_t *so = tcp_info->inet_pcb ->socket; 01138 socket_connection_complete(so, cur->id ); 01139 tcp_info->state = TCP_STATE_ESTABLISHED; 01140 /* RFC 6298 - if timed out during connection, revert to conservative initial RTO for data */ 01141 /* (What's the point - Karn's algorithm would cover this?) */ 01142 if (tcp_info->retry > 0 && tcp_info->rto < TCP_INITIAL_CONSERVATIVE_RTO) { 01143 tcp_info->rto = TCP_INITIAL_CONSERVATIVE_RTO; 01144 } 01145 } 01146 /** 01147 * \brief Function that handles data coming from lower level to TCP. 01148 * 01149 * \param buf buffer received 01150 * 01151 * \return allocated pointer if acknowledgment needs to be sent 01152 * \return zero pointer, no further action required 01153 */ 01154 01155 buffer_t *tcp_up(buffer_t *buf) 01156 { 01157 uint8_t *ptr; 01158 protocol_interface_info_entry_t *cur; 01159 uint16_t data_offset; 01160 uint16_t mss_option = 536; 01161 uint16_t window_size; 01162 inet_pcb_t *inet_pcb; 01163 tcp_session_t *tcp_info; 01164 buffer_t *segment_ack = NULL; 01165 uint32_t ack_no; 01166 uint32_t seq_no; 01167 uint16_t seg_len; 01168 uint8_t flags; 01169 01170 cur = buf->interface ; 01171 01172 /* Multicast source or link-layer destination already handled by IP */ 01173 if (!cur || addr_is_ipv6_multicast(buf->dst_sa .address ) || buf->options .ll_security_bypass_rx ) { 01174 tr_error("TCP UP:Invalid"); 01175 return buffer_free(buf); 01176 } 01177 01178 if (buffer_data_length(buf) < 20) { 01179 tr_error("TCP UP:Too short"); 01180 return buffer_free(buf); 01181 } 01182 01183 if (buffer_ipv6_fcf(buf, IPV6_NH_TCP)) { 01184 tr_warn("TCP CKSUM ERROR!!!: src: %s, dst: %s", tr_ipv6(buf->src_sa .address ), tr_ipv6(buf->dst_sa .address )); 01185 protocol_stats_update(STATS_IP_CKSUM_ERROR, 1); 01186 return buffer_free(buf); 01187 } 01188 01189 // save received port(s), seq_no and ack_no, data_offset, flags, window_size, 01190 ptr = buffer_data_pointer(buf); 01191 buf->src_sa .port = common_read_16_bit(ptr); 01192 ptr += 2; 01193 buf->dst_sa .port = common_read_16_bit(ptr); 01194 ptr += 2; 01195 seq_no = common_read_32_bit(ptr); 01196 ptr += 4; 01197 ack_no = common_read_32_bit(ptr); 01198 ptr += 4; 01199 01200 data_offset = (*ptr++ >> 4) << 2; 01201 if (data_offset > buffer_data_length(buf)) { 01202 tr_error("TCP UP:Offset length fail"); 01203 return buffer_free(buf); 01204 } 01205 01206 buffer_data_strip_header(buf, data_offset); 01207 01208 flags = *ptr++; 01209 window_size = common_read_16_bit(ptr); 01210 ptr += 2; 01211 01212 // Skip over Checksum (already checked) and Urgent Pointer (ignored) 01213 ptr += 4; 01214 01215 seg_len = buffer_data_length(buf); 01216 if (flags & TCP_FLAG_SYN) { 01217 seg_len++; 01218 } 01219 if (flags & TCP_FLAG_FIN) { 01220 seg_len++; 01221 } 01222 01223 tr_debug("TCP_UP: dst_p=%d, src_p=%d, flags=%s", buf->dst_sa .port , buf->src_sa .port , trace_tcp_flags(flags)); 01224 /* clear flags that will be ignored */ 01225 flags &= ~(TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG); 01226 01227 // Parse options 01228 bool malformed_options = false; 01229 if (data_offset > 20) { 01230 uint16_t options_len = data_offset - 20; 01231 while (options_len > 0) { 01232 uint8_t type = ptr[0]; 01233 uint8_t len; 01234 if (type == TCP_OPTION_END) { 01235 break; 01236 } else if (type == TCP_OPTION_NOP) { 01237 len = 1; 01238 } else { 01239 if (options_len < 2) { 01240 goto bad_opts; 01241 } 01242 len = ptr[1]; 01243 if (len < 2) { 01244 goto bad_opts; 01245 } 01246 } 01247 01248 if (len > options_len) { 01249 bad_opts: 01250 malformed_options = true; 01251 tr_err("Malformed options"); 01252 break; 01253 } 01254 01255 if (type == TCP_OPTION_MSS && len == 4) { 01256 mss_option = common_read_16_bit(ptr + 2); 01257 tr_debug("MSS %"PRIu16, mss_option); 01258 } else if (type != TCP_OPTION_NOP){ 01259 tr_info("Unsupported option %d", type); 01260 } 01261 ptr += len; 01262 options_len -= len; 01263 } 01264 } 01265 01266 // find socket from existing connections based on local and remote addresses 01267 socket_t *so = socket_lookup_ipv6(IPV6_NH_TCP, &buf->dst_sa , &buf->src_sa , false); 01268 inet_pcb = so ? so->inet_pcb : NULL; 01269 tcp_info = inet_pcb ? inet_pcb->session : NULL; 01270 // if not found, and it's a SYN, look for a listening socket 01271 if (tcp_info == NULL && !malformed_options) find_listen: { // Can jump here from TIME-WAIT, with tcp_info set 01272 socket_t *listen_socket = tcp_find_listen_socket(buf->dst_sa .address , buf->dst_sa .port ); 01273 if (listen_socket) { 01274 tr_debug("UP: Packet for LISTEN socket %d", listen_socket->id ); 01275 #ifdef TCP_TEST 01276 if (rx_drops[TCP_STATE_LISTEN]) { 01277 tr_info("RX drop LISTEN"); 01278 rx_drops[TCP_STATE_LISTEN]--; 01279 return buffer_free(buf); 01280 } 01281 #endif 01282 if (flags & TCP_FLAG_RST) { 01283 tr_warn("UP, RST to LISTEN"); 01284 return buffer_free(buf); 01285 } 01286 if (flags & TCP_FLAG_ACK) { 01287 tr_warn("UP, ACK to LISTEN"); 01288 return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST); 01289 } 01290 if (flags & TCP_FLAG_SYN) { 01291 socket_t *new_socket = socket_new_incoming_connection(listen_socket); 01292 if (!new_socket) { 01293 tr_error("Couldn't allocate socket"); 01294 return buffer_free(buf); 01295 } 01296 inet_pcb = new_socket->inet_pcb ; 01297 /* new socket has an inet PCB cloned from the listening one - lock down addresses+ports */ 01298 memcpy(inet_pcb->remote_address , buf->src_sa .address , 16); 01299 memcpy(inet_pcb->local_address , buf->dst_sa .address , 16); 01300 inet_pcb->local_port = buf->dst_sa .port ; 01301 inet_pcb->remote_port = buf->src_sa .port ; 01302 tr_debug("remote=[%s]:%u", trace_ipv6(inet_pcb->remote_address ), inet_pcb->remote_port ); 01303 tr_debug("local=[%s]:%u", trace_ipv6(inet_pcb->local_address ), inet_pcb->local_port ); 01304 /* If someone sets a fixed (non-0) flow label on a listening socket, all incoming 01305 * connections will end up using the same flow label, which is dumb, but user's fault. */ 01306 /* Same logic as connect(). */ 01307 if (inet_pcb->flow_label == IPV6_FLOW_AUTOGENERATE || 01308 (inet_pcb->flow_label == IPV6_FLOW_UNSPECIFIED && ipv6_flow_auto_label)) { 01309 inet_pcb->flow_label = ipv6_flow_random(); 01310 } 01311 tcp_info = tcp_session_ptr_allocate(inet_pcb, tcp_info); 01312 if (!tcp_info) { 01313 tr_error("Couldn't allocate TCP session"); 01314 socket_release(new_socket); 01315 return buffer_free(buf); 01316 } 01317 // save source port and address to tcp session data 01318 tcp_info->interface = cur; 01319 01320 if (tcp_info->interface->nwk_id == IF_6LoWPAN) { 01321 if (tcp_info->receive_mss > TCP_LOWPAN_MSS_LIMIT) { 01322 tcp_info->receive_mss = TCP_LOWPAN_MSS_LIMIT; 01323 } 01324 } 01325 01326 tcp_info->receive_next = seq_no; 01327 tcp_info->receive_adv = seq_no; 01328 tcp_info->send_window = window_size; 01329 tcp_info->send_mss_peer = mss_option; 01330 tcp_rethink_mss(tcp_info); 01331 buffer_free(buf); 01332 // Acknowledge 1 byte (the SYN) - ignore anything further 01333 buf = tcp_ack_buffer(tcp_info, 1); 01334 if (!buf) { 01335 tr_error("Couldn't create SYN-ACK"); 01336 tcp_session_delete(tcp_info); 01337 socket_release(new_socket); 01338 return NULL; 01339 } 01340 buf->options .code = TCP_FLAG_SYN | TCP_FLAG_ACK; 01341 01342 tr_debug("UP:sSR"); 01343 tcp_info->state = TCP_STATE_SYN_RECEIVED; 01344 tcp_info->passive_open = true; 01345 tcp_build(buf, tcp_info); 01346 return NULL; 01347 } // SYN 01348 // Not RST, ACK or SYN 01349 tr_warn("UP, no flags to LISTEN"); 01350 return buffer_free(buf); 01351 } // Listening socket found 01352 01353 // Wipe out tcp_info, for the case where we jumped into this block from TIME-WAIT, so we send 01354 // a reset (for this new connection attempt, with a higher sequence number, for which 01355 // we have no listening socket). 01356 tcp_info = NULL; 01357 } // No existing session 01358 01359 if (tcp_info == NULL || tcp_info->state == TCP_STATE_CLOSED || malformed_options) { 01360 tr_info("No tcp_info for port=%d from %s", buf->dst_sa .port , trace_ipv6(buf->src_sa .address )); 01361 if (flags & TCP_FLAG_RST) { 01362 tr_debug("RST to CLOSED"); 01363 return buffer_free(buf); 01364 } 01365 if (!(flags & TCP_FLAG_ACK)) { 01366 return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, 0, seq_no + seg_len, TCP_FLAG_RST|TCP_FLAG_ACK); 01367 } 01368 return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST); 01369 } 01370 01371 #ifdef TCP_TEST 01372 if (rx_drops[tcp_info->state]) { 01373 tr_info("RX drop %s", tcp_state_name(tcp_info)); 01374 rx_drops[tcp_info->state]--; 01375 return buffer_free(buf); 01376 } 01377 #endif 01378 01379 buffer_socket_set(buf, so); 01380 01381 tr_debug("UP: sock=%d: state=%s", so->id , tcp_state_name(tcp_info)); 01382 01383 if (tcp_info->state == TCP_STATE_SYN_SENT) { 01384 if (flags & TCP_FLAG_ACK) { 01385 if (ack_no != tcp_info->send_next) { 01386 if (flags & TCP_FLAG_RST) { 01387 return buffer_free(buf); 01388 } 01389 return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST); 01390 } 01391 } 01392 if (flags & TCP_FLAG_RST) { 01393 if (flags & TCP_FLAG_ACK) { 01394 tcp_session_delete_with_error(tcp_info, SOCKET_CONNECT_FAIL); 01395 } 01396 return buffer_free(buf); 01397 } 01398 if (flags & TCP_FLAG_SYN) { 01399 tcp_info->receive_next = seq_no; 01400 tcp_info->receive_adv = seq_no; 01401 tcp_info->send_mss_peer = mss_option; 01402 tcp_rethink_mss(tcp_info); 01403 if (flags & TCP_FLAG_ACK) { 01404 tcp_ack_segment(ack_no, tcp_info); 01405 tcp_info->send_wl1 = seq_no; // RFC 1122 4.2.2.20(c) 01406 tcp_info->send_wl2 = ack_no; 01407 tcp_info->send_window = window_size; 01408 tcp_session_established(cur, tcp_info); 01409 goto syn_sent_to_established; 01410 } else { 01411 tr_debug("UP:sSR"); 01412 tcp_info->state = TCP_STATE_SYN_RECEIVED; 01413 segment_ack = tcp_ack_buffer(tcp_info, 1); 01414 if (segment_ack) { 01415 buffer_socket_set(segment_ack, buf->socket ); 01416 segment_ack->options .code = TCP_FLAG_SYN | TCP_FLAG_ACK; 01417 tcp_build(segment_ack, tcp_info); 01418 } 01419 buffer_free(buf); 01420 return NULL; 01421 } 01422 } 01423 } // state == TCP_STATE_SYN_SENT 01424 01425 // Early escape from TIME-WAIT: processing of SYN segments as per RFC 6191 01426 // (simple non-timestamp case) 01427 if ((flags & (TCP_FLAG_SYN|TCP_FLAG_FIN|TCP_FLAG_ACK|TCP_FLAG_RST)) == TCP_FLAG_SYN && tcp_info->state == TCP_STATE_TIME_WAIT) { 01428 if (tcp_seq_ge(seq_no, tcp_info->receive_next)) { 01429 goto find_listen; 01430 } else { 01431 return buffer_free(buf); 01432 } 01433 } 01434 01435 // Window checks 01436 int32_t receive_window = sockbuf_space(&so->rcvq); 01437 if (receive_window < 0) { 01438 receive_window = 0; 01439 } 01440 if (receive_window < (int32_t) (tcp_info->receive_adv - tcp_info->receive_next)) { 01441 receive_window = tcp_info->receive_adv - tcp_info->receive_next; 01442 } 01443 01444 bool seq_ok = false; 01445 if (receive_window == 0) { 01446 if (seg_len == 0 && seq_no == tcp_info->receive_next) { 01447 seq_ok = true; 01448 } 01449 } else { 01450 if (tcp_seq_in_range(tcp_info->receive_next, seq_no, tcp_info->receive_next + receive_window - 1)) { 01451 seq_ok = true; 01452 } else if (seg_len > 0 && tcp_seq_in_range(tcp_info->receive_next, seq_no + seg_len - 1, tcp_info->receive_next + receive_window - 1)) { 01453 seq_ok = true; 01454 } 01455 } 01456 01457 if (!seq_ok) { 01458 tr_debug("Out-of-window seq_no=%"PRIu32", seg_len=%"PRIu16", window [%"PRIu32" - %"PRIu32")", seq_no, seg_len, tcp_info->receive_next, tcp_info->receive_next + receive_window); 01459 buffer_free(buf); 01460 buf = tcp_ack_buffer(tcp_info, 0); 01461 tcp_build(buf, tcp_info); 01462 return NULL; 01463 } 01464 01465 /* Strip data preceding the window */ 01466 if (tcp_seq_lt(seq_no, tcp_info->receive_next)) { 01467 uint16_t excess = tcp_info->receive_next - seq_no; 01468 tr_debug("Strip preceding excess %d", excess); 01469 /* Strip SYN "byte" */ 01470 if (flags & TCP_FLAG_SYN) { 01471 flags &= ~TCP_FLAG_SYN; 01472 seg_len--; 01473 excess--; 01474 seq_no++; 01475 } 01476 if (excess) { 01477 buffer_data_strip_header(buf, excess); 01478 seg_len -= excess; 01479 seq_no += excess; 01480 } 01481 } 01482 01483 /* Strip data following the window */ 01484 if (tcp_seq_gt(seq_no + buffer_data_length(buf), tcp_info->receive_next + receive_window)) { 01485 uint16_t excess = (seq_no + buffer_data_length(buf)) - (tcp_info->receive_next + receive_window); 01486 tr_debug("Strip trailing excess %d", excess); 01487 /* Strip FIN "byte" */ 01488 if (flags & TCP_FLAG_FIN) { 01489 flags &= ~TCP_FLAG_FIN; 01490 seg_len--; 01491 } 01492 buf->buf_end -= excess; 01493 seg_len -= excess; 01494 } 01495 01496 if (flags & TCP_FLAG_RST) { 01497 switch (tcp_info->state) { 01498 case TCP_STATE_SYN_RECEIVED: 01499 if (tcp_info->passive_open) { 01500 tcp_session_delete_with_error(tcp_info, 0); 01501 } else { 01502 tcp_session_delete_with_error(tcp_info, SOCKET_CONNECT_FAIL); 01503 } 01504 break; 01505 case TCP_STATE_ESTABLISHED: 01506 case TCP_STATE_FIN_WAIT_1: 01507 case TCP_STATE_FIN_WAIT_2: 01508 case TCP_STATE_CLOSE_WAIT: 01509 tcp_session_delete_with_error(tcp_info, SOCKET_CONNECTION_RESET); 01510 break; 01511 case TCP_STATE_CLOSING: 01512 case TCP_STATE_LAST_ACK: 01513 tcp_session_delete(tcp_info); 01514 break; 01515 case TCP_STATE_TIME_WAIT: // RFC 1337 01516 default: 01517 break; 01518 } 01519 return buffer_free(buf); 01520 } 01521 01522 if (flags & TCP_FLAG_SYN) { 01523 tr_debug("unexpected SYN"); 01524 if (tcp_info->state == TCP_STATE_SYN_RECEIVED && tcp_info->passive_open) { 01525 // RFC 1122 4.2.2.20(e) 01526 tcp_session_delete_with_error(tcp_info, 0); // really no reset sent? 01527 return buffer_free(buf); 01528 } 01529 if (!(flags & TCP_FLAG_ACK)) { 01530 return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, 0, seq_no + seg_len, TCP_FLAG_RST|TCP_FLAG_ACK); 01531 } 01532 return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST); 01533 } 01534 01535 if (!(flags & TCP_FLAG_ACK)) { 01536 tr_debug("ACK not set"); 01537 return buffer_free(buf); 01538 } 01539 01540 if (tcp_info->state == TCP_STATE_SYN_RECEIVED) { 01541 if (ack_no == tcp_info->send_next) { 01542 tcp_info->send_wl1 = seq_no; // RFC 1122 4.2.2.20(f) 01543 tcp_info->send_wl2 = ack_no; 01544 tcp_info->send_window = window_size; 01545 tcp_session_established(cur, tcp_info); 01546 } else { 01547 return tcp_reset_response(NULL, 0, buf, ack_no, 0, TCP_FLAG_RST); 01548 } 01549 } 01550 01551 if (tcp_seq_lt(ack_no, tcp_info->send_unacknowledged)) { 01552 tr_debug("Already acked ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next); 01553 } else if (tcp_seq_gt(ack_no, tcp_info->send_next)) { 01554 tr_debug("Future ack ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next); 01555 buffer_free(buf); 01556 // Generating this ack can lead to an ack storm if we're somehow out of sync... 01557 // Seems to be a TCP flaw... 01558 buf = tcp_ack_buffer(tcp_info, 0); 01559 tcp_build(buf, tcp_info); 01560 return NULL; 01561 } else /* SND.UNA <= SEG.ACK <= SND.NXT */ { 01562 /* Update window, if packet not older than last window information */ 01563 if (tcp_seq_gt(seq_no, tcp_info->send_wl1) || 01564 (seq_no == tcp_info->send_wl1 && tcp_seq_ge(ack_no, tcp_info->send_wl2))) { 01565 if (tcp_info->send_window != window_size) { 01566 tr_debug("Send window update %"PRIu16"->%"PRIu16, tcp_info->send_window, window_size); 01567 } 01568 tcp_info->send_wl1 = seq_no; 01569 tcp_info->send_wl2 = ack_no; 01570 tcp_info->send_window = window_size; 01571 // Watch out for shrinking right edge 01572 if (window_size == 0 && ack_no != tcp_info->send_next) { 01573 tcp_info->persist = true; 01574 } 01575 } 01576 if (ack_no != tcp_info->send_unacknowledged) { 01577 tr_debug("New ack_no=%"PRIu32", in-flight [%"PRIu32" - %"PRIu32")", ack_no, tcp_info->send_unacknowledged, tcp_info->send_next); 01578 tcp_ack_segment(ack_no, tcp_info); 01579 } else if (tcp_info->persist) { 01580 tcp_info->retry = 0; 01581 if (window_size != 0) { 01582 tcp_info->persist = false; 01583 // Got a pure window update. (Re)transmit now 01584 tcp_resend_segment(tcp_info); 01585 } else { 01586 // Let the retransmit timer keep on running, which will trigger 01587 // another persist probe at RTO after the last one (effectively 01588 // ignoring this ack for timing purposes), but reset the retry 01589 // count so we don't give up in resend_segment. 01590 } 01591 } 01592 01593 bool fin_acknowledged = tcp_info->sent_fin && tcp_info->send_unacknowledged == tcp_info->send_next; 01594 switch (tcp_info->state) { 01595 case TCP_STATE_FIN_WAIT_1: 01596 if (fin_acknowledged) { 01597 tcp_info->state = TCP_STATE_FIN_WAIT_2; 01598 // Only time out FIN_WAIT_2 if no longer have a socket 01599 if (so->flags & SOCKET_FLAG_CLOSED) { 01600 tcp_info->timer = TCP_FIN_WAIT_2_TIMEOUT; 01601 } else { 01602 tcp_info->timer = 0; 01603 } 01604 tr_debug("UP:sF2"); 01605 } 01606 break; 01607 case TCP_STATE_CLOSING: 01608 if (fin_acknowledged) { 01609 tcp_info->state = TCP_STATE_TIME_WAIT; 01610 tr_debug("UP:sTW"); 01611 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE; 01612 } 01613 break; 01614 case TCP_STATE_LAST_ACK: 01615 if (fin_acknowledged) { 01616 socket_event_push(SOCKET_CONNECT_CLOSED, so, cur->id , NULL, 0); 01617 tr_debug("Last ACK remove Session"); 01618 tcp_session_delete(tcp_info); 01619 return buffer_free(buf); 01620 } 01621 break; 01622 case TCP_STATE_TIME_WAIT: 01623 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE; 01624 break; 01625 } 01626 } 01627 01628 syn_sent_to_established: 01629 if (flags & TCP_FLAG_URG) { 01630 /* No handling of urgent */ 01631 } 01632 01633 /* This is the point we're actually processing incoming text or FINs. All of the 01634 * above is done as long as in-window, but from here on we need the correct sequence. 01635 * seg_len is length including FIN marker. 01636 */ 01637 if (seg_len > 0 && seq_no != tcp_info->receive_next) { 01638 tr_debug("Out-of-order data"); 01639 buffer_t *ack_buf = tcp_ack_buffer(tcp_info, 0); 01640 tcp_build(ack_buf, tcp_info); 01641 return buffer_free(buf); 01642 } 01643 01644 /* Data only processed in some states - other states silently ignore */ 01645 if (buffer_data_length(buf) && 01646 (tcp_info->state == TCP_STATE_ESTABLISHED || tcp_info->state == TCP_STATE_FIN_WAIT_1 || tcp_info->state == TCP_STATE_FIN_WAIT_2)) { 01647 // This handles closed sockets (see RFC 1122 4.2.2.13 and RFC2525 2.16) 01648 // and also extends it to read shutdown (like Windows, apparently, but not Linux or BSD) 01649 if (so->flags & SOCKET_FLAG_CANT_RECV_MORE) { 01650 tr_warn("Excess data we can't receive - resetting"); 01651 return tcp_reset_response(tcp_info, SOCKET_CONNECTION_RESET, buf, ack_no, 0, TCP_FLAG_RST); 01652 } 01653 buf->info = (buffer_info_t)(B_FROM_TCP | B_TO_NONE | B_DIR_UP); 01654 01655 //tr_debug("data up"); 01656 sockbuf_append_and_compress(&so->rcvq, buf); 01657 buf = NULL; 01658 if ((flags & (TCP_FLAG_FIN|TCP_FLAG_PSH)) || sockbuf_space(&so->rcvq) <= (int32_t) (so->rcvq.data_byte_limit / 2)) { 01659 socket_data_queued_event_push(so); 01660 } 01661 } 01662 01663 // Original buffer no longer required 01664 if (buf) { 01665 buf = buffer_free(buf); 01666 } 01667 01668 if (flags & TCP_FLAG_FIN) { 01669 tr_debug("fin"); 01670 switch (tcp_info->state) { 01671 case TCP_STATE_SYN_RECEIVED: // can't happen? 01672 case TCP_STATE_ESTABLISHED: 01673 tcp_info->state = TCP_STATE_CLOSE_WAIT; 01674 tcp_info->timer = 0; 01675 tr_debug("UP:sCW"); 01676 socket_cant_recv_more(so, cur->id ); 01677 break; 01678 case TCP_STATE_FIN_WAIT_1: 01679 if (tcp_info->send_unacknowledged == tcp_info->send_next) { 01680 tcp_info->state = TCP_STATE_TIME_WAIT; 01681 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE; 01682 tr_debug("UP:sTW"); 01683 } else { 01684 tcp_info->state = TCP_STATE_CLOSING; 01685 tr_debug("UP:sCl"); 01686 } 01687 socket_cant_recv_more(so, cur->id ); 01688 break; 01689 case TCP_STATE_FIN_WAIT_2: 01690 tcp_info->state = TCP_STATE_TIME_WAIT; 01691 tr_debug("UP:sTW"); 01692 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE; 01693 socket_cant_recv_more(so, cur->id ); 01694 socket_event_push(SOCKET_CONNECT_CLOSED, so, cur->id , 0, 0); 01695 break; 01696 case TCP_STATE_TIME_WAIT: 01697 tcp_info->timer = TCP_TIME_WAIT_TO_CLOSE; 01698 break; 01699 default: 01700 tr_debug("UP:fin, other state"); 01701 // No action 01702 break; 01703 } 01704 } 01705 01706 // if there is new data to be acknowledged then send ack 01707 if (seg_len > 0) { 01708 segment_ack = tcp_ack_buffer(tcp_info, seg_len); 01709 tcp_build(segment_ack, tcp_info); 01710 } 01711 return buf; 01712 } 01713 01714 const char *tcp_state_name(const tcp_session_t *tcp_info) 01715 { 01716 switch (tcp_info->state) { 01717 case TCP_STATE_LISTEN: 01718 return "LISTEN"; 01719 case TCP_STATE_SYN_SENT: 01720 return "SYN-SENT"; 01721 case TCP_STATE_SYN_RECEIVED: 01722 return "SYN-RECEIVED"; 01723 case TCP_STATE_ESTABLISHED: 01724 return "ESTABLISHED"; 01725 case TCP_STATE_CLOSE_WAIT: 01726 return "CLOSE-WAIT"; 01727 case TCP_STATE_LAST_ACK: 01728 return "LAST-ACK"; 01729 case TCP_STATE_FIN_WAIT_1: 01730 return "FIN-WAIT-1"; 01731 case TCP_STATE_FIN_WAIT_2: 01732 return "FIN-WAIT-2"; 01733 case TCP_STATE_CLOSING: 01734 return "CLOSING"; 01735 case TCP_STATE_TIME_WAIT: 01736 return "TIME-WAIT"; 01737 default: 01738 return "?"; 01739 } 01740 } 01741 #endif /*NO_TCP*/ 01742 /* end of file tcp.c */
Generated on Tue Jul 12 2022 13:03:18 by
