Changeset 00aece0 in mainline for uspace/srv/net/tl/tcp/tcp.c
- Timestamp:
- 2012-02-18T16:47:38Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/tcp/tcp.c
rbd5f3b7 r00aece0 1 1 /* 2 * Copyright (c) 20 08 Lukas Mejdrech2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 33 /** @file 34 * TCP module implementation. 35 * @see tcp.h 33 /** 34 * @file TCP (Transmission Control Protocol) network module 36 35 */ 37 36 38 #include <assert.h>39 37 #include <async.h> 40 #include <fibril_synch.h> 41 #include <malloc.h> 42 /* TODO remove stdio */ 38 #include <bitops.h> 39 #include <byteorder.h> 40 #include <errno.h> 41 #include <io/log.h> 43 42 #include <stdio.h> 44 #include <errno.h> 45 43 #include <task.h> 44 45 #include <icmp_remote.h> 46 #include <ip_client.h> 47 #include <ip_interface.h> 46 48 #include <ipc/services.h> 47 #include <ipc/net.h>48 49 #include <ipc/tl.h> 49 #include <ipc/socket.h> 50 51 #include <net/socket_codes.h> 52 #include <net/ip_protocols.h> 53 #include <net/in.h> 54 #include <net/in6.h> 55 #include <net/inet.h> 56 #include <net/modules.h> 57 58 #include <adt/dynamic_fifo.h> 50 #include <tl_common.h> 51 #include <tl_skel.h> 59 52 #include <packet_client.h> 60 53 #include <packet_remote.h> 61 #include <net_checksum.h> 62 #include <ip_client.h> 63 #include <ip_interface.h> 64 #include <icmp_client.h> 65 #include <icmp_remote.h> 66 #include <net_interface.h> 67 #include <socket_core.h> 68 #include <tl_common.h> 69 #include <tl_remote.h> 70 #include <tl_skel.h> 71 54 55 #include "ncsim.h" 56 #include "pdu.h" 57 #include "rqueue.h" 58 #include "sock.h" 59 #include "std.h" 72 60 #include "tcp.h" 73 #include "tcp_header.h" 74 75 /** TCP module name. */ 76 #define NAME "tcp" 77 78 /** The TCP window default value. */ 79 #define NET_DEFAULT_TCP_WINDOW 10240 80 81 /** Initial timeout for new connections. */ 82 #define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L 83 84 /** Default timeout for closing. */ 85 #define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L 86 87 /** The initial outgoing sequence number. */ 88 #define TCP_INITIAL_SEQUENCE_NUMBER 2999 89 90 /** Maximum TCP fragment size. */ 91 #define MAX_TCP_FRAGMENT_SIZE 65535 92 93 /** Free ports pool start. */ 94 #define TCP_FREE_PORTS_START 1025 95 96 /** Free ports pool end. */ 97 #define TCP_FREE_PORTS_END 65535 98 99 /** Timeout for connection initialization, SYN sent. */ 100 #define TCP_SYN_SENT_TIMEOUT 1000000L 101 102 /** The maximum number of timeouts in a row before singaling connection lost. */ 103 #define TCP_MAX_TIMEOUTS 8 104 105 /** The number of acknowledgements before retransmit. */ 106 #define TCP_FAST_RETRANSMIT_COUNT 3 107 108 /** Returns a value indicating whether the value is in the interval respecting 109 * the possible overflow. 110 * 111 * The high end and/or the value may overflow, be lower than the low value. 112 * 113 * @param[in] lower The last value before the interval. 114 * @param[in] value The value to be checked. 115 * @param[in] higher_equal The last value in the interval. 116 */ 117 #define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \ 118 ((((lower) < (value)) && (((value) <= (higher_equal)) || \ 119 ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && \ 120 ((higher_equal) < (lower)))) 121 122 /** Type definition of the TCP timeout. 123 * @see tcp_timeout 124 */ 125 typedef struct tcp_timeout tcp_timeout_t; 126 127 /** TCP reply timeout data. 128 * Used as a timeouting fibril argument. 129 * @see tcp_timeout() 130 */ 131 struct tcp_timeout { 132 /** TCP global data are going to be read only. */ 133 int globals_read_only; 134 135 /** Socket port. */ 136 int port; 137 138 /** Local sockets. */ 139 socket_cores_t *local_sockets; 140 141 /** Socket identifier. */ 142 int socket_id; 143 144 /** Socket state. */ 145 tcp_socket_state_t state; 146 147 /** Sent packet sequence number. */ 148 int sequence_number; 149 150 /** Timeout in microseconds. */ 151 suseconds_t timeout; 152 153 /** Port map key. */ 154 uint8_t *key; 155 156 /** Port map key length. */ 157 size_t key_length; 158 }; 159 160 static int tcp_release_and_return(packet_t *, int); 161 static void tcp_prepare_operation_header(socket_core_t *, tcp_socket_data_t *, 162 tcp_header_t *, int synchronize, int); 163 static int tcp_prepare_timeout(int (*)(void *), socket_core_t *, 164 tcp_socket_data_t *, size_t, tcp_socket_state_t, suseconds_t, int); 165 static void tcp_free_socket_data(socket_core_t *); 166 167 static int tcp_timeout(void *); 168 169 static int tcp_release_after_timeout(void *); 170 171 static int tcp_process_packet(device_id_t, packet_t *, services_t); 172 static int tcp_connect_core(socket_core_t *, socket_cores_t *, 173 struct sockaddr *, socklen_t); 174 static int tcp_queue_prepare_packet(socket_core_t *, tcp_socket_data_t *, 175 packet_t *, size_t); 176 static int tcp_queue_packet(socket_core_t *, tcp_socket_data_t *, packet_t *, 177 size_t); 178 static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *); 179 static void tcp_send_packets(device_id_t, packet_t *); 180 181 static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *, 182 tcp_header_t *); 183 static packet_t *tcp_send_prepare_packet(socket_core_t *, tcp_socket_data_t *, 184 packet_t *, size_t, size_t); 185 static packet_t *tcp_prepare_copy(socket_core_t *, tcp_socket_data_t *, 186 packet_t *, size_t, size_t); 187 /* static */ void tcp_retransmit_packet(socket_core_t *, tcp_socket_data_t *, 188 size_t); 189 static int tcp_create_notification_packet(packet_t **, socket_core_t *, 190 tcp_socket_data_t *, int, int); 191 static void tcp_refresh_socket_data(tcp_socket_data_t *); 192 193 static void tcp_initialize_socket_data(tcp_socket_data_t *); 194 195 static int tcp_process_listen(socket_core_t *, tcp_socket_data_t *, 196 tcp_header_t *, packet_t *, struct sockaddr *, struct sockaddr *, size_t); 197 static int tcp_process_syn_sent(socket_core_t *, tcp_socket_data_t *, 198 tcp_header_t *, packet_t *); 199 static int tcp_process_syn_received(socket_core_t *, tcp_socket_data_t *, 200 tcp_header_t *, packet_t *); 201 static int tcp_process_established(socket_core_t *, tcp_socket_data_t *, 202 tcp_header_t *, packet_t *, int, size_t); 203 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *, 204 packet_t *, int, size_t); 205 static void tcp_queue_received_end_of_data(socket_core_t *socket); 206 207 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t); 208 static int tcp_process_client_messages(async_sess_t *, ipc_callid_t, 209 ipc_call_t); 210 211 static int tcp_listen_message(socket_cores_t *, int, int); 212 static int tcp_connect_message(socket_cores_t *, int, struct sockaddr *, 213 socklen_t); 214 static int tcp_recvfrom_message(socket_cores_t *, int, int, size_t *); 215 static int tcp_send_message(socket_cores_t *, int, int, size_t *, int); 216 static int tcp_accept_message(socket_cores_t *, int, int, size_t *, size_t *); 217 static int tcp_close_message(socket_cores_t *, int); 218 219 /** TCP global data. */ 220 tcp_globals_t tcp_globals; 221 222 int tcp_received_msg(device_id_t device_id, packet_t *packet, 223 services_t receiver, services_t error) 61 #include "test.h" 62 63 #define NAME "tcp" 64 65 async_sess_t *net_sess; 66 static async_sess_t *icmp_sess; 67 async_sess_t *ip_sess; 68 packet_dimensions_t pkt_dims; 69 70 static void tcp_received_pdu(tcp_pdu_t *pdu); 71 72 /* Pull up packets into a single memory block. */ 73 static int pq_pullup(packet_t *packet, void **data, size_t *dsize) 74 { 75 packet_t *npacket; 76 size_t tot_len; 77 int length; 78 79 npacket = packet; 80 tot_len = 0; 81 do { 82 length = packet_get_data_length(packet); 83 if (length <= 0) 84 return EINVAL; 85 86 tot_len += length; 87 } while ((npacket = pq_next(npacket)) != NULL); 88 89 uint8_t *buf; 90 uint8_t *dp; 91 92 buf = calloc(tot_len, 1); 93 if (buf == NULL) { 94 free(buf); 95 return ENOMEM; 96 } 97 98 npacket = packet; 99 dp = buf; 100 do { 101 length = packet_get_data_length(packet); 102 if (length <= 0) { 103 free(buf); 104 return EINVAL; 105 } 106 107 memcpy(dp, packet_get_data(packet), length); 108 dp += length; 109 } while ((npacket = pq_next(npacket)) != NULL); 110 111 *data = buf; 112 *dsize = tot_len; 113 return EOK; 114 } 115 116 /** Process packet received from network layer. */ 117 static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet, 118 services_t error) 224 119 { 225 120 int rc; 226 227 if (receiver != SERVICE_TCP)228 return EREFUSED;229 230 fibril_rwlock_write_lock(&tcp_globals.lock);231 rc = tcp_process_packet(device_id, packet, error);232 if (rc != EOK)233 fibril_rwlock_write_unlock(&tcp_globals.lock);234 235 printf("receive %d \n", rc);236 237 return rc;238 }239 240 int tcp_process_packet(device_id_t device_id, packet_t *packet, services_t error)241 {242 size_t length;243 121 size_t offset; 244 int result; 245 tcp_header_t *header; 246 socket_core_t *socket; 247 tcp_socket_data_t *socket_data; 248 packet_t *next_packet; 249 size_t total_length; 250 uint32_t checksum; 251 int fragments; 252 icmp_type_t type; 253 icmp_code_t code; 254 struct sockaddr *src; 255 struct sockaddr *dest; 256 size_t addrlen; 257 int rc; 122 int length; 123 struct sockaddr_in *src_addr; 124 struct sockaddr_in *dest_addr; 125 size_t addr_len; 126 127 log_msg(LVL_DEBUG, "tcp_received_msg()"); 258 128 259 129 switch (error) { … … 261 131 break; 262 132 case SERVICE_ICMP: 263 /* Process error */264 result = icmp_client_process_packet(packet, &type, &code, NULL,265 NULL);266 if (result < 0)267 return tcp_release_and_return(packet, result);268 269 length = (size_t) result;270 rc = packet_trim(packet, length, 0);271 if (rc != EOK)272 return tcp_release_and_return(packet, rc);273 break;274 133 default: 275 return tcp_release_and_return(packet, ENOTSUP); 276 } 277 278 /* TODO process received ipopts? */ 279 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 280 if (result < 0) 281 return tcp_release_and_return(packet, result); 282 283 offset = (size_t) result; 284 134 log_msg(LVL_WARN, "Unsupported service number %u", 135 (unsigned)error); 136 pq_release_remote(net_sess, packet_get_id(packet)); 137 return ENOTSUP; 138 } 139 140 /* Process and trim off IP header */ 141 log_msg(LVL_DEBUG, "tcp_received_msg() - IP header"); 142 143 rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 144 if (rc < 0) { 145 log_msg(LVL_WARN, "ip_client_process_packet() failed"); 146 pq_release_remote(net_sess, packet_get_id(packet)); 147 return rc; 148 } 149 150 offset = (size_t)rc; 285 151 length = packet_get_data_length(packet); 286 if (length <= 0) 287 return tcp_release_and_return(packet, EINVAL); 288 289 if (length < TCP_HEADER_SIZE + offset) 290 return tcp_release_and_return(packet, NO_DATA); 291 292 /* Trim all but TCP header */ 152 153 if (length < 0 || (size_t)length < offset) { 154 log_msg(LVL_WARN, "length=%d, dropping.", length); 155 pq_release_remote(net_sess, packet_get_id(packet)); 156 return EINVAL; 157 } 158 159 addr_len = packet_get_addr(packet, (uint8_t **)&src_addr, 160 (uint8_t **)&dest_addr); 161 if (addr_len <= 0) { 162 log_msg(LVL_WARN, "Failed to get packet address."); 163 pq_release_remote(net_sess, packet_get_id(packet)); 164 return EINVAL; 165 } 166 167 if (addr_len != sizeof(struct sockaddr_in)) { 168 log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)", 169 addr_len, sizeof(struct sockaddr_in)); 170 pq_release_remote(net_sess, packet_get_id(packet)); 171 return EINVAL; 172 } 173 293 174 rc = packet_trim(packet, offset, 0); 294 if (rc != EOK) 295 return tcp_release_and_return(packet, rc); 296 297 /* Get tcp header */ 298 header = (tcp_header_t *) packet_get_data(packet); 299 if (!header) 300 return tcp_release_and_return(packet, NO_DATA); 301 302 #if 0 303 printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header), 304 ntohs(header->destination_port)); 305 #endif 306 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 307 if (result <= 0) 308 return tcp_release_and_return(packet, result); 309 310 addrlen = (size_t) result; 311 312 rc = tl_set_address_port(src, addrlen, ntohs(header->source_port)); 313 if (rc != EOK) 314 return tcp_release_and_return(packet, rc); 315 316 /* Find the destination socket */ 317 socket = socket_port_find(&tcp_globals.sockets, 318 ntohs(header->destination_port), (uint8_t *) src, addrlen); 319 if (!socket) { 320 /* Find the listening destination socket */ 321 socket = socket_port_find(&tcp_globals.sockets, 322 ntohs(header->destination_port), 323 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 324 } 325 326 if (!socket) { 327 if (tl_prepare_icmp_packet(tcp_globals.net_sess, 328 tcp_globals.icmp_sess, packet, error) == EOK) { 329 icmp_destination_unreachable_msg(tcp_globals.icmp_sess, 330 ICMP_PORT_UNREACH, 0, packet); 331 } 332 return EADDRNOTAVAIL; 333 } 334 335 printf("socket id %d\n", socket->socket_id); 336 socket_data = (tcp_socket_data_t *) socket->specific_data; 337 assert(socket_data); 338 339 /* Some data received, clear the timeout counter */ 340 socket_data->timeout_count = 0; 341 342 /* Count the received packet fragments */ 343 next_packet = packet; 344 fragments = 0; 345 checksum = 0; 346 total_length = 0; 347 do { 348 fragments++; 349 length = packet_get_data_length(next_packet); 350 if (length <= 0) 351 return tcp_release_and_return(packet, NO_DATA); 352 353 total_length += length; 354 355 /* Add partial checksum if set */ 356 if (!error) { 357 checksum = compute_checksum(checksum, 358 packet_get_data(packet), 359 packet_get_data_length(packet)); 360 } 361 362 } while ((next_packet = pq_next(next_packet))); 363 364 fibril_rwlock_write_lock(socket_data->local_lock); 365 366 if (error) 367 goto has_error_service; 368 369 if (socket_data->state == TCP_SOCKET_LISTEN) { 370 if (socket_data->pseudo_header) { 371 free(socket_data->pseudo_header); 372 socket_data->pseudo_header = NULL; 373 socket_data->headerlen = 0; 374 } 375 376 rc = ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen, 377 dest, addrlen, total_length, &socket_data->pseudo_header, 378 &socket_data->headerlen); 379 if (rc != EOK) { 380 fibril_rwlock_write_unlock(socket_data->local_lock); 381 return tcp_release_and_return(packet, rc); 382 } 383 } else { 384 rc = ip_client_set_pseudo_header_data_length( 385 socket_data->pseudo_header, socket_data->headerlen, 386 total_length); 387 if (rc != EOK) { 388 fibril_rwlock_write_unlock(socket_data->local_lock); 389 return tcp_release_and_return(packet, rc); 390 } 391 } 392 393 checksum = compute_checksum(checksum, socket_data->pseudo_header, 394 socket_data->headerlen); 395 if (flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO) { 396 printf("checksum err %x -> %x\n", header->checksum, 397 flip_checksum(compact_checksum(checksum))); 398 fibril_rwlock_write_unlock(socket_data->local_lock); 399 400 rc = tl_prepare_icmp_packet(tcp_globals.net_sess, 401 tcp_globals.icmp_sess, packet, error); 402 if (rc == EOK) { 403 /* Checksum error ICMP */ 404 icmp_parameter_problem_msg(tcp_globals.icmp_sess, 405 ICMP_PARAM_POINTER, 406 ((size_t) ((void *) &header->checksum)) - 407 ((size_t) ((void *) header)), packet); 408 } 409 410 return EINVAL; 411 } 412 413 has_error_service: 414 fibril_rwlock_write_unlock(&tcp_globals.lock); 415 416 /* TODO error reporting/handling */ 417 switch (socket_data->state) { 418 case TCP_SOCKET_LISTEN: 419 rc = tcp_process_listen(socket, socket_data, header, packet, 420 src, dest, addrlen); 421 break; 422 case TCP_SOCKET_SYN_RECEIVED: 423 rc = tcp_process_syn_received(socket, socket_data, header, 424 packet); 425 break; 426 case TCP_SOCKET_SYN_SENT: 427 rc = tcp_process_syn_sent(socket, socket_data, header, packet); 428 break; 429 case TCP_SOCKET_FIN_WAIT_1: 430 /* ack changing the state to FIN_WAIT_2 gets processed later */ 431 case TCP_SOCKET_FIN_WAIT_2: 432 /* fin changing state to LAST_ACK gets processed later */ 433 case TCP_SOCKET_LAST_ACK: 434 /* ack releasing the socket get processed later */ 435 case TCP_SOCKET_CLOSING: 436 /* ack releasing the socket gets processed later */ 437 case TCP_SOCKET_ESTABLISHED: 438 rc = tcp_process_established(socket, socket_data, header, 439 packet, fragments, total_length); 440 break; 441 default: 442 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 443 } 444 445 if (rc != EOK) { 446 fibril_rwlock_write_unlock(socket_data->local_lock); 447 printf("process %d\n", rc); 448 } 175 if (rc != EOK) { 176 log_msg(LVL_WARN, "Failed to trim packet."); 177 pq_release_remote(net_sess, packet_get_id(packet)); 178 return rc; 179 } 180 181 /* Pull up packets into a single memory block, pdu_raw. */ 182 log_msg(LVL_DEBUG, "tcp_received_msg() - pull up"); 183 uint8_t *pdu_raw; 184 size_t pdu_raw_size = 0; 185 186 pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size); 187 188 /* Split into header and payload. */ 189 190 log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload"); 191 192 tcp_pdu_t *pdu; 193 size_t hdr_size; 194 tcp_header_t *hdr; 195 uint32_t data_offset; 196 197 if (pdu_raw_size < sizeof(tcp_header_t)) { 198 log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu", 199 pdu_raw_size, sizeof(tcp_header_t)); 200 pq_release_remote(net_sess, packet_get_id(packet)); 201 return EINVAL; 202 } 203 204 hdr = (tcp_header_t *)pdu_raw; 205 data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l, 206 uint16_t_be2host(hdr->doff_flags)); 207 208 hdr_size = sizeof(uint32_t) * data_offset; 209 210 if (pdu_raw_size < hdr_size) { 211 log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu", 212 pdu_raw_size, hdr_size); 213 pq_release_remote(net_sess, packet_get_id(packet)); 214 return EINVAL; 215 } 216 217 if (hdr_size < sizeof(tcp_header_t)) { 218 log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu", 219 hdr_size, sizeof(tcp_header_t)); 220 pq_release_remote(net_sess, packet_get_id(packet)); 221 return EINVAL; 222 } 223 224 log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu", 225 pdu_raw_size, hdr_size); 226 pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size, 227 pdu_raw_size - hdr_size); 228 if (pdu == NULL) { 229 log_msg(LVL_WARN, "Failed creating PDU. Dropped."); 230 return ENOMEM; 231 } 232 233 free(pdu_raw); 234 235 pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr); 236 pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr); 237 log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x", 238 pdu->src_addr.ipv4, pdu->dest_addr.ipv4); 239 240 tcp_received_pdu(pdu); 241 tcp_pdu_delete(pdu); 449 242 450 243 return EOK; 451 244 } 452 245 453 int tcp_process_established(socket_core_t *socket, tcp_socket_data_t * 454 socket_data, tcp_header_t *header, packet_t *packet, int fragments, 455 size_t total_length) 456 { 457 packet_t *next_packet; 458 packet_t *tmp_packet; 459 uint32_t old_incoming; 460 size_t order; 461 uint32_t sequence_number; 462 size_t length; 463 size_t offset; 464 uint32_t new_sequence_number; 465 bool forced_ack; 466 int rc; 467 468 assert(socket); 469 assert(socket_data); 470 assert(socket->specific_data == socket_data); 471 assert(header); 472 assert(packet); 473 474 forced_ack = false; 475 476 new_sequence_number = ntohl(header->sequence_number); 477 old_incoming = socket_data->next_incoming; 478 479 if (GET_TCP_HEADER_FINALIZE(header)) { 480 socket_data->fin_incoming = new_sequence_number + 481 total_length - TCP_HEADER_LENGTH(header); 482 } 483 484 /* Trim begining if containing expected data */ 485 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number, 486 socket_data->next_incoming, new_sequence_number + total_length)) { 487 488 /* Get the acknowledged offset */ 489 if (socket_data->next_incoming < new_sequence_number) { 490 offset = new_sequence_number - 491 socket_data->next_incoming; 492 } else { 493 offset = socket_data->next_incoming - 494 new_sequence_number; 495 } 496 497 new_sequence_number += offset; 498 total_length -= offset; 499 length = packet_get_data_length(packet); 500 501 /* Trim the acknowledged data */ 502 while (length <= offset) { 503 /* Release the acknowledged packets */ 504 next_packet = pq_next(packet); 505 pq_release_remote(tcp_globals.net_sess, 506 packet_get_id(packet)); 507 packet = next_packet; 508 offset -= length; 509 length = packet_get_data_length(packet); 510 } 511 512 if (offset > 0) { 513 rc = packet_trim(packet, offset, 0); 514 if (rc != EOK) 515 return tcp_release_and_return(packet, rc); 516 } 517 518 assert(new_sequence_number == socket_data->next_incoming); 519 } 520 521 /* Release if overflowing the window */ 522 /* 523 if (IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming + 524 socket_data->window, new_sequence_number, new_sequence_number + 525 total_length)) { 526 return tcp_release_and_return(packet, EOVERFLOW); 527 } 528 529 // trim end if overflowing the window 530 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number, 531 socket_data->next_incoming + socket_data->window, 532 new_sequence_number + total_length)) { 533 // get the allowed data length 534 if (socket_data->next_incoming + socket_data->window < 535 new_sequence_number) { 536 offset = new_sequence_number - 537 socket_data->next_incoming + socket_data->window; 538 } else { 539 offset = socket_data->next_incoming + 540 socket_data->window - new_sequence_number; 541 } 542 next_packet = packet; 543 // trim the overflowing data 544 while (next_packet && (offset > 0)) { 545 length = packet_get_data_length(packet); 546 if (length <= offset) 547 next_packet = pq_next(next_packet); 548 else { 549 rc = packet_trim(next_packet, 0, 550 length - offset)); 551 if (rc != EOK) 552 return tcp_release_and_return(packet, 553 rc); 554 } 555 offset -= length; 556 total_length -= length - offset; 557 } 558 // release the overflowing packets 559 next_packet = pq_next(next_packet); 560 if (next_packet) { 561 tmp_packet = next_packet; 562 next_packet = pq_next(next_packet); 563 pq_insert_after(tmp_packet, next_packet); 564 pq_release_remote(tcp_globals.net_sess, 565 packet_get_id(tmp_packet)); 566 } 567 assert(new_sequence_number + total_length == 568 socket_data->next_incoming + socket_data->window); 569 } 570 */ 571 /* The expected one arrived? */ 572 if (new_sequence_number == socket_data->next_incoming) { 573 printf("expected\n"); 574 /* Process acknowledgement */ 575 tcp_process_acknowledgement(socket, socket_data, header); 576 577 /* Remove the header */ 578 total_length -= TCP_HEADER_LENGTH(header); 579 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); 580 if (rc != EOK) 581 return tcp_release_and_return(packet, rc); 582 583 if (total_length) { 584 rc = tcp_queue_received_packet(socket, socket_data, 585 packet, fragments, total_length); 586 if (rc != EOK) 587 return rc; 588 } else { 589 total_length = 1; 590 } 591 592 socket_data->next_incoming = old_incoming + total_length; 593 packet = socket_data->incoming; 594 while (packet) { 595 rc = pq_get_order(socket_data->incoming, &order, NULL); 596 if (rc != EOK) { 597 /* Remove the corrupted packet */ 598 next_packet = pq_detach(packet); 599 if (packet == socket_data->incoming) 600 socket_data->incoming = next_packet; 601 pq_release_remote(tcp_globals.net_sess, 602 packet_get_id(packet)); 603 packet = next_packet; 604 continue; 605 } 606 607 sequence_number = (uint32_t) order; 608 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 609 old_incoming, socket_data->next_incoming)) { 610 /* Move to the next */ 611 packet = pq_next(packet); 612 /* Coninual data? */ 613 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming, 614 sequence_number, socket_data->next_incoming)) { 615 /* Detach the packet */ 616 next_packet = pq_detach(packet); 617 if (packet == socket_data->incoming) 618 socket_data->incoming = next_packet; 619 /* Get data length */ 620 length = packet_get_data_length(packet); 621 new_sequence_number = sequence_number + length; 622 if (length <= 0) { 623 /* Remove the empty packet */ 624 pq_release_remote(tcp_globals.net_sess, 625 packet_get_id(packet)); 626 packet = next_packet; 627 continue; 628 } 629 /* Exactly following */ 630 if (sequence_number == 631 socket_data->next_incoming) { 632 /* Queue received data */ 633 rc = tcp_queue_received_packet(socket, 634 socket_data, packet, 1, 635 packet_get_data_length(packet)); 636 if (rc != EOK) 637 return rc; 638 socket_data->next_incoming = 639 new_sequence_number; 640 packet = next_packet; 641 continue; 642 /* At least partly following data? */ 643 } 644 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 645 socket_data->next_incoming, new_sequence_number)) { 646 if (socket_data->next_incoming < 647 new_sequence_number) { 648 length = new_sequence_number - 649 socket_data->next_incoming; 650 } else { 651 length = 652 socket_data->next_incoming - 653 new_sequence_number; 654 } 655 rc = packet_trim(packet,length, 0); 656 if (rc == EOK) { 657 /* Queue received data */ 658 rc = tcp_queue_received_packet( 659 socket, socket_data, packet, 660 1, packet_get_data_length( 661 packet)); 662 if (rc != EOK) 663 return rc; 664 socket_data->next_incoming = 665 new_sequence_number; 666 packet = next_packet; 667 continue; 668 } 669 } 670 /* Remove the duplicit or corrupted packet */ 671 pq_release_remote(tcp_globals.net_sess, 672 packet_get_id(packet)); 673 packet = next_packet; 674 continue; 675 } else { 676 break; 677 } 678 } 679 } else if (IS_IN_INTERVAL(socket_data->next_incoming, 680 new_sequence_number, 681 socket_data->next_incoming + socket_data->window)) { 682 printf("in window\n"); 683 /* Process acknowledgement */ 684 tcp_process_acknowledgement(socket, socket_data, header); 685 686 /* Remove the header */ 687 total_length -= TCP_HEADER_LENGTH(header); 688 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); 689 if (rc != EOK) 690 return tcp_release_and_return(packet, rc); 691 692 next_packet = pq_detach(packet); 693 length = packet_get_data_length(packet); 694 rc = pq_add(&socket_data->incoming, packet, new_sequence_number, 695 length); 696 if (rc != EOK) { 697 /* Remove the corrupted packets */ 698 pq_release_remote(tcp_globals.net_sess, 699 packet_get_id(packet)); 700 pq_release_remote(tcp_globals.net_sess, 701 packet_get_id(next_packet)); 702 } else { 703 while (next_packet) { 704 new_sequence_number += length; 705 tmp_packet = pq_detach(next_packet); 706 length = packet_get_data_length(next_packet); 707 708 rc = pq_set_order(next_packet, 709 new_sequence_number, length); 710 if (rc != EOK) { 711 pq_release_remote(tcp_globals.net_sess, 712 packet_get_id(next_packet)); 713 } 714 rc = pq_insert_after(packet, next_packet); 715 if (rc != EOK) { 716 pq_release_remote(tcp_globals.net_sess, 717 packet_get_id(next_packet)); 718 } 719 next_packet = tmp_packet; 720 } 721 } 722 } else { 723 printf("unexpected\n"); 724 /* Release duplicite or restricted */ 725 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 726 forced_ack = true; 727 } 728 729 /* If next in sequence is an incoming FIN */ 730 if (socket_data->next_incoming == socket_data->fin_incoming) { 731 /* Advance sequence number */ 732 socket_data->next_incoming += 1; 733 734 /* Handle FIN */ 735 switch (socket_data->state) { 736 case TCP_SOCKET_FIN_WAIT_1: 737 case TCP_SOCKET_FIN_WAIT_2: 738 case TCP_SOCKET_CLOSING: 739 socket_data->state = TCP_SOCKET_CLOSING; 740 break; 741 case TCP_SOCKET_ESTABLISHED: 742 /* Queue end-of-data marker on the socket. */ 743 tcp_queue_received_end_of_data(socket); 744 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 745 break; 746 default: 747 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 748 break; 749 } 750 } 751 752 packet = tcp_get_packets_to_send(socket, socket_data); 753 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) { 754 /* Create the notification packet */ 755 rc = tcp_create_notification_packet(&packet, socket, 756 socket_data, 0, 0); 757 if (rc != EOK) 758 return rc; 759 rc = tcp_queue_prepare_packet(socket, socket_data, packet, 1); 760 if (rc != EOK) 761 return rc; 762 packet = tcp_send_prepare_packet(socket, socket_data, packet, 1, 763 socket_data->last_outgoing + 1); 764 } 765 766 fibril_rwlock_write_unlock(socket_data->local_lock); 767 768 /* Send the packet */ 769 tcp_send_packets(socket_data->device_id, packet); 770 771 return EOK; 772 } 773 774 int tcp_queue_received_packet(socket_core_t *socket, 775 tcp_socket_data_t *socket_data, packet_t *packet, int fragments, 776 size_t total_length) 777 { 778 packet_dimension_t *packet_dimension; 779 int rc; 780 781 assert(socket); 782 assert(socket_data); 783 assert(socket->specific_data == socket_data); 784 assert(packet); 785 assert(fragments >= 1); 786 assert(socket_data->window > total_length); 787 788 /* Queue the received packet */ 789 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 790 SOCKET_MAX_RECEIVED_SIZE); 791 if (rc != EOK) 792 return tcp_release_and_return(packet, rc); 793 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 794 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 795 if (rc != EOK) 796 return tcp_release_and_return(packet, rc); 797 798 /* Decrease the window size */ 799 socket_data->window -= total_length; 800 801 /* Notify the destination socket */ 802 async_exch_t *exch = async_exchange_begin(socket->sess); 803 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id, 804 ((packet_dimension->content < socket_data->data_fragment_size) ? 805 packet_dimension->content : socket_data->data_fragment_size), 0, 0, 806 (sysarg_t) fragments); 807 async_exchange_end(exch); 808 809 return EOK; 810 } 811 812 /** Queue end-of-data marker on the socket. 813 * 814 * Next element in the sequence space is FIN. Queue end-of-data marker 815 * on the socket. 816 * 817 * @param socket Socket 818 */ 819 static void tcp_queue_received_end_of_data(socket_core_t *socket) 820 { 821 assert(socket != NULL); 822 823 /* Notify the destination socket */ 824 async_exch_t *exch = async_exchange_begin(socket->sess); 825 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id, 826 0, 0, 0, (sysarg_t) 0 /* 0 fragments == no more data */); 827 async_exchange_end(exch); 828 } 829 830 int tcp_process_syn_sent(socket_core_t *socket, tcp_socket_data_t * 831 socket_data, tcp_header_t *header, packet_t *packet) 832 { 833 packet_t *next_packet; 834 int rc; 835 836 assert(socket); 837 assert(socket_data); 838 assert(socket->specific_data == socket_data); 839 assert(header); 840 assert(packet); 841 842 if (!GET_TCP_HEADER_SYNCHRONIZE(header)) 843 return tcp_release_and_return(packet, EINVAL); 844 845 /* Process acknowledgement */ 846 tcp_process_acknowledgement(socket, socket_data, header); 847 848 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 849 850 /* Release additional packets */ 851 next_packet = pq_detach(packet); 852 if (next_packet) { 853 pq_release_remote(tcp_globals.net_sess, 854 packet_get_id(next_packet)); 855 } 856 857 /* Trim if longer than the header */ 858 if (packet_get_data_length(packet) > sizeof(*header)) { 859 rc = packet_trim(packet, 0, 860 packet_get_data_length(packet) - sizeof(*header)); 861 if (rc != EOK) 862 return tcp_release_and_return(packet, rc); 863 } 864 865 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 866 fibril_mutex_lock(&socket_data->operation.mutex); 867 socket_data->operation.result = tcp_queue_packet(socket, socket_data, 868 packet, 1); 869 870 if (socket_data->operation.result == EOK) { 871 socket_data->state = TCP_SOCKET_ESTABLISHED; 872 packet = tcp_get_packets_to_send(socket, socket_data); 873 if (packet) { 874 fibril_rwlock_write_unlock( socket_data->local_lock); 875 /* Send the packet */ 876 tcp_send_packets(socket_data->device_id, packet); 877 /* Signal the result */ 878 fibril_condvar_signal( &socket_data->operation.condvar); 879 fibril_mutex_unlock( &socket_data->operation.mutex); 880 return EOK; 881 } 882 } 883 884 fibril_mutex_unlock(&socket_data->operation.mutex); 885 return tcp_release_and_return(packet, EINVAL); 886 } 887 888 int tcp_process_listen(socket_core_t *listening_socket, 889 tcp_socket_data_t *listening_socket_data, tcp_header_t *header, 890 packet_t *packet, struct sockaddr *src, struct sockaddr *dest, 891 size_t addrlen) 892 { 893 packet_t *next_packet; 894 socket_core_t *socket; 895 tcp_socket_data_t *socket_data; 896 int socket_id; 897 int listening_socket_id = listening_socket->socket_id; 898 int listening_port = listening_socket->port; 899 int rc; 900 901 assert(listening_socket); 902 assert(listening_socket_data); 903 assert(listening_socket->specific_data == listening_socket_data); 904 assert(header); 905 assert(packet); 906 907 if (!GET_TCP_HEADER_SYNCHRONIZE(header)) 908 return tcp_release_and_return(packet, EINVAL); 909 910 socket_data = (tcp_socket_data_t *) malloc(sizeof(*socket_data)); 911 if (!socket_data) 912 return tcp_release_and_return(packet, ENOMEM); 913 914 tcp_initialize_socket_data(socket_data); 915 socket_data->local_lock = listening_socket_data->local_lock; 916 socket_data->local_sockets = listening_socket_data->local_sockets; 917 socket_data->listening_socket_id = listening_socket->socket_id; 918 socket_data->next_incoming = ntohl(header->sequence_number); 919 socket_data->treshold = socket_data->next_incoming + 920 ntohs(header->window); 921 socket_data->addrlen = addrlen; 922 socket_data->addr = malloc(socket_data->addrlen); 923 if (!socket_data->addr) { 924 free(socket_data); 925 return tcp_release_and_return(packet, ENOMEM); 926 } 927 928 memcpy(socket_data->addr, src, socket_data->addrlen); 929 socket_data->dest_port = ntohs(header->source_port); 930 rc = tl_set_address_port(socket_data->addr, socket_data->addrlen, 931 socket_data->dest_port); 932 if (rc != EOK) { 933 free(socket_data->addr); 934 free(socket_data); 935 return tcp_release_and_return(packet, rc); 936 } 937 938 /* Create a socket */ 939 socket_id = -1; 940 rc = socket_create(socket_data->local_sockets, listening_socket->sess, 941 socket_data, &socket_id); 942 if (rc != EOK) { 943 free(socket_data->addr); 944 free(socket_data); 945 return tcp_release_and_return(packet, rc); 946 } 947 948 printf("new_sock %d\n", socket_id); 949 socket_data->pseudo_header = listening_socket_data->pseudo_header; 950 socket_data->headerlen = listening_socket_data->headerlen; 951 listening_socket_data->pseudo_header = NULL; 952 listening_socket_data->headerlen = 0; 953 954 fibril_rwlock_write_unlock(socket_data->local_lock); 955 fibril_rwlock_write_lock(&tcp_globals.lock); 956 957 /* Find the destination socket */ 958 listening_socket = socket_port_find(&tcp_globals.sockets, 959 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 960 if (!listening_socket || 961 (listening_socket->socket_id != listening_socket_id)) { 962 fibril_rwlock_write_unlock(&tcp_globals.lock); 963 /* A shadow may remain until app hangs up */ 964 return tcp_release_and_return(packet, EOK /*ENOTSOCK*/); 965 } 966 listening_socket_data = 967 (tcp_socket_data_t *) listening_socket->specific_data; 968 assert(listening_socket_data); 969 970 fibril_rwlock_write_lock(listening_socket_data->local_lock); 971 972 socket = socket_cores_find(listening_socket_data->local_sockets, 973 socket_id); 974 if (!socket) { 975 /* Where is the socket?!? */ 976 fibril_rwlock_write_unlock(&tcp_globals.lock); 977 return ENOTSOCK; 978 } 979 socket_data = (tcp_socket_data_t *) socket->specific_data; 980 assert(socket_data); 981 982 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket, 983 (uint8_t *) socket_data->addr, socket_data->addrlen); 984 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port, 985 (uint8_t *) socket_data->addr, socket_data->addrlen)); 986 987 // rc = socket_bind_free_port(&tcp_globals.sockets, socket, 988 // TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 989 // tcp_globals.last_used_port); 990 // tcp_globals.last_used_port = socket->port; 991 fibril_rwlock_write_unlock(&tcp_globals.lock); 992 if (rc != EOK) { 993 socket_destroy(tcp_globals.net_sess, socket->socket_id, 994 socket_data->local_sockets, &tcp_globals.sockets, 995 tcp_free_socket_data); 996 return tcp_release_and_return(packet, rc); 997 } 998 999 socket_data->state = TCP_SOCKET_LISTEN; 1000 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 1001 1002 /* Release additional packets */ 1003 next_packet = pq_detach(packet); 1004 if (next_packet) { 1005 pq_release_remote(tcp_globals.net_sess, 1006 packet_get_id(next_packet)); 1007 } 1008 1009 /* Trim if longer than the header */ 1010 if (packet_get_data_length(packet) > sizeof(*header)) { 1011 rc = packet_trim(packet, 0, 1012 packet_get_data_length(packet) - sizeof(*header)); 1013 if (rc != EOK) { 1014 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1015 socket_data->local_sockets, &tcp_globals.sockets, 1016 tcp_free_socket_data); 1017 return tcp_release_and_return(packet, rc); 1018 } 1019 } 1020 1021 tcp_prepare_operation_header(socket, socket_data, header, 1, 0); 1022 1023 rc = tcp_queue_packet(socket, socket_data, packet, 1); 1024 if (rc != EOK) { 1025 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1026 socket_data->local_sockets, &tcp_globals.sockets, 1027 tcp_free_socket_data); 1028 return rc; 1029 } 1030 1031 packet = tcp_get_packets_to_send(socket, socket_data); 1032 if (!packet) { 1033 socket_destroy(tcp_globals.net_sess, socket->socket_id, 1034 socket_data->local_sockets, &tcp_globals.sockets, 1035 tcp_free_socket_data); 1036 return EINVAL; 1037 } 1038 1039 socket_data->state = TCP_SOCKET_SYN_RECEIVED; 1040 fibril_rwlock_write_unlock(socket_data->local_lock); 1041 1042 /* Send the packet */ 1043 tcp_send_packets(socket_data->device_id, packet); 1044 1045 return EOK; 1046 } 1047 1048 int tcp_process_syn_received(socket_core_t *socket, 1049 tcp_socket_data_t *socket_data, tcp_header_t *header, packet_t *packet) 1050 { 1051 socket_core_t *listening_socket; 1052 tcp_socket_data_t *listening_socket_data; 1053 int rc; 1054 1055 assert(socket); 1056 assert(socket_data); 1057 assert(socket->specific_data == socket_data); 1058 assert(header); 1059 assert(packet); 1060 1061 if (!GET_TCP_HEADER_ACKNOWLEDGE(header)) 1062 return tcp_release_and_return(packet, EINVAL); 1063 1064 /* Process acknowledgement */ 1065 tcp_process_acknowledgement(socket, socket_data, header); 1066 1067 socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */ 1068 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1069 socket_data->state = TCP_SOCKET_ESTABLISHED; 1070 listening_socket = socket_cores_find(socket_data->local_sockets, 1071 socket_data->listening_socket_id); 1072 if (listening_socket) { 1073 listening_socket_data = 1074 (tcp_socket_data_t *) listening_socket->specific_data; 1075 assert(listening_socket_data); 1076 1077 /* Queue the received packet */ 1078 rc = dyn_fifo_push(&listening_socket->accepted, 1079 (-1 * socket->socket_id), listening_socket_data->backlog); 1080 if (rc == EOK) { 1081 /* Notify the destination socket */ 1082 async_exch_t *exch = async_exchange_begin(socket->sess); 1083 async_msg_5(exch, NET_SOCKET_ACCEPTED, 1084 (sysarg_t) listening_socket->socket_id, 1085 socket_data->data_fragment_size, TCP_HEADER_SIZE, 1086 0, (sysarg_t) socket->socket_id); 1087 async_exchange_end(exch); 1088 1089 fibril_rwlock_write_unlock(socket_data->local_lock); 1090 return EOK; 1091 } 1092 } 1093 /* Send FIN */ 1094 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 1095 1096 /* Create the notification packet */ 1097 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 1098 if (rc != EOK) 1099 return rc; 1100 1101 /* Send the packet */ 1102 rc = tcp_queue_packet(socket, socket_data, packet, 1); 1103 if (rc != EOK) 1104 return rc; 1105 1106 /* Flush packets */ 1107 packet = tcp_get_packets_to_send(socket, socket_data); 1108 fibril_rwlock_write_unlock(socket_data->local_lock); 1109 if (packet) { 1110 /* Send the packet */ 1111 tcp_send_packets(socket_data->device_id, packet); 1112 } 1113 1114 return EOK; 1115 } 1116 1117 void tcp_process_acknowledgement(socket_core_t *socket, 1118 tcp_socket_data_t *socket_data, tcp_header_t *header) 1119 { 1120 size_t number; 1121 size_t length; 1122 packet_t *packet; 1123 packet_t *next; 1124 packet_t *acknowledged = NULL; 1125 uint32_t old; 1126 1127 assert(socket); 1128 assert(socket_data); 1129 assert(socket->specific_data == socket_data); 1130 assert(header); 1131 1132 if (!GET_TCP_HEADER_ACKNOWLEDGE(header)) 1133 return; 1134 1135 number = ntohl(header->acknowledgement_number); 1136 1137 /* If more data acknowledged */ 1138 if (number != socket_data->expected) { 1139 old = socket_data->expected; 1140 if (IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing, 1141 number)) { 1142 switch (socket_data->state) { 1143 case TCP_SOCKET_FIN_WAIT_1: 1144 socket_data->state = TCP_SOCKET_FIN_WAIT_2; 1145 break; 1146 case TCP_SOCKET_LAST_ACK: 1147 case TCP_SOCKET_CLOSING: 1148 /* 1149 * FIN acknowledged - release the socket in 1150 * another fibril. 1151 */ 1152 tcp_prepare_timeout(tcp_release_after_timeout, 1153 socket, socket_data, 0, 1154 TCP_SOCKET_TIME_WAIT, 1155 NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true); 1156 break; 1157 default: 1158 break; 1159 } 1160 } 1161 1162 /* Update the treshold if higher than set */ 1163 if (number + ntohs(header->window) > 1164 socket_data->expected + socket_data->treshold) { 1165 socket_data->treshold = number + ntohs(header->window) - 1166 socket_data->expected; 1167 } 1168 1169 /* Set new expected sequence number */ 1170 socket_data->expected = number; 1171 socket_data->expected_count = 1; 1172 packet = socket_data->outgoing; 1173 while (pq_get_order(packet, &number, &length) == EOK) { 1174 if (IS_IN_INTERVAL_OVERFLOW((uint32_t) old, 1175 (uint32_t) (number + length), 1176 (uint32_t) socket_data->expected)) { 1177 next = pq_detach(packet); 1178 if (packet == socket_data->outgoing) 1179 socket_data->outgoing = next; 1180 1181 /* Add to acknowledged or release */ 1182 if (pq_add(&acknowledged, packet, 0, 0) != EOK) 1183 pq_release_remote(tcp_globals.net_sess, 1184 packet_get_id(packet)); 1185 packet = next; 1186 } else if (old < socket_data->expected) 1187 break; 1188 } 1189 1190 /* Release acknowledged */ 1191 if (acknowledged) { 1192 pq_release_remote(tcp_globals.net_sess, 1193 packet_get_id(acknowledged)); 1194 } 1195 return; 1196 /* If the same as the previous time */ 1197 } 1198 1199 if (number == socket_data->expected) { 1200 /* Increase the counter */ 1201 socket_data->expected_count++; 1202 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) { 1203 socket_data->expected_count = 1; 1204 /* TODO retransmit lock */ 1205 //tcp_retransmit_packet(socket, socket_data, number); 1206 } 1207 } 1208 } 1209 1210 /** Per-connection initialization 1211 * 1212 */ 1213 void tl_connection(void) 1214 { 1215 } 1216 1217 /** Processes the TCP message. 1218 * 1219 * @param[in] callid The message identifier. 1220 * @param[in] call The message parameters. 1221 * @param[out] answer The message answer parameters. 1222 * @param[out] answer_count The last parameter for the actual answer in the 1223 * answer parameter. 1224 * @return EOK on success. 1225 * @return ENOTSUP if the message is not known. 1226 * 1227 * @see tcp_interface.h 1228 * @see IS_NET_TCP_MESSAGE() 1229 */ 1230 int tl_message(ipc_callid_t callid, ipc_call_t *call, 1231 ipc_call_t *answer, size_t *answer_count) 1232 { 1233 assert(call); 1234 assert(answer); 1235 assert(answer_count); 1236 1237 *answer_count = 0; 1238 1239 async_sess_t *callback = 1240 async_callback_receive_start(EXCHANGE_SERIALIZE, call); 1241 if (callback) 1242 return tcp_process_client_messages(callback, callid, *call); 1243 1244 return ENOTSUP; 1245 } 1246 1247 void tcp_refresh_socket_data(tcp_socket_data_t *socket_data) 1248 { 1249 assert(socket_data); 1250 1251 bzero(socket_data, sizeof(*socket_data)); 1252 socket_data->state = TCP_SOCKET_INITIAL; 1253 socket_data->device_id = DEVICE_INVALID_ID; 1254 socket_data->window = NET_DEFAULT_TCP_WINDOW; 1255 socket_data->treshold = socket_data->window; 1256 socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER; 1257 socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT; 1258 socket_data->acknowledged = socket_data->last_outgoing; 1259 socket_data->next_outgoing = socket_data->last_outgoing + 1; 1260 socket_data->expected = socket_data->next_outgoing; 1261 } 1262 1263 void tcp_initialize_socket_data(tcp_socket_data_t *socket_data) 1264 { 1265 assert(socket_data); 1266 1267 tcp_refresh_socket_data(socket_data); 1268 fibril_mutex_initialize(&socket_data->operation.mutex); 1269 fibril_condvar_initialize(&socket_data->operation.condvar); 1270 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE; 1271 } 1272 1273 int tcp_process_client_messages(async_sess_t *sess, ipc_callid_t callid, 1274 ipc_call_t call) 1275 { 1276 int res; 1277 socket_cores_t local_sockets; 1278 struct sockaddr *addr; 1279 int socket_id; 1280 size_t addrlen; 1281 size_t size; 1282 fibril_rwlock_t lock; 1283 ipc_call_t answer; 1284 size_t answer_count; 1285 tcp_socket_data_t *socket_data; 1286 socket_core_t *socket; 1287 packet_dimension_t *packet_dimension; 1288 1289 /* 1290 * Accept the connection 1291 * - Answer the first IPC_M_CONNECT_ME_TO call. 1292 */ 1293 res = EOK; 1294 answer_count = 0; 1295 1296 socket_cores_initialize(&local_sockets); 1297 fibril_rwlock_initialize(&lock); 1298 1299 while (true) { 1300 1301 /* Answer the call */ 1302 answer_call(callid, res, &answer, answer_count); 1303 /* Refresh data */ 1304 refresh_answer(&answer, &answer_count); 1305 /* Get the next call */ 1306 callid = async_get_call(&call); 1307 1308 if (!IPC_GET_IMETHOD(call)) { 1309 res = EHANGUP; 1310 break; 1311 } 1312 1313 /* Process the call */ 1314 switch (IPC_GET_IMETHOD(call)) { 1315 case NET_SOCKET: 1316 socket_data = 1317 (tcp_socket_data_t *) malloc(sizeof(*socket_data)); 1318 if (!socket_data) { 1319 res = ENOMEM; 1320 break; 1321 } 1322 1323 tcp_initialize_socket_data(socket_data); 1324 socket_data->local_lock = &lock; 1325 socket_data->local_sockets = &local_sockets; 1326 fibril_rwlock_write_lock(&lock); 1327 socket_id = SOCKET_GET_SOCKET_ID(call); 1328 res = socket_create(&local_sockets, sess, 1329 socket_data, &socket_id); 1330 SOCKET_SET_SOCKET_ID(answer, socket_id); 1331 fibril_rwlock_write_unlock(&lock); 1332 if (res != EOK) { 1333 free(socket_data); 1334 break; 1335 } 1336 if (tl_get_ip_packet_dimension(tcp_globals.ip_sess, 1337 &tcp_globals.dimensions, DEVICE_INVALID_ID, 1338 &packet_dimension) == EOK) { 1339 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 1340 ((packet_dimension->content < 1341 socket_data->data_fragment_size) ? 1342 packet_dimension->content : 1343 socket_data->data_fragment_size)); 1344 } 1345 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE); 1346 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE); 1347 answer_count = 3; 1348 break; 1349 1350 case NET_SOCKET_BIND: 1351 res = async_data_write_accept((void **) &addr, false, 1352 0, 0, 0, &addrlen); 1353 if (res != EOK) 1354 break; 1355 fibril_rwlock_write_lock(&tcp_globals.lock); 1356 fibril_rwlock_write_lock(&lock); 1357 res = socket_bind(&local_sockets, &tcp_globals.sockets, 1358 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 1359 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 1360 tcp_globals.last_used_port); 1361 if (res == EOK) { 1362 socket = socket_cores_find(&local_sockets, 1363 SOCKET_GET_SOCKET_ID(call)); 1364 if (socket) { 1365 socket_data = (tcp_socket_data_t *) 1366 socket->specific_data; 1367 assert(socket_data); 1368 socket_data->state = TCP_SOCKET_LISTEN; 1369 } 1370 } 1371 fibril_rwlock_write_unlock(&lock); 1372 fibril_rwlock_write_unlock(&tcp_globals.lock); 1373 free(addr); 1374 break; 1375 1376 case NET_SOCKET_LISTEN: 1377 fibril_rwlock_read_lock(&tcp_globals.lock); 1378 // fibril_rwlock_write_lock(&tcp_globals.lock); 1379 fibril_rwlock_write_lock(&lock); 1380 res = tcp_listen_message(&local_sockets, 1381 SOCKET_GET_SOCKET_ID(call), 1382 SOCKET_GET_BACKLOG(call)); 1383 fibril_rwlock_write_unlock(&lock); 1384 // fibril_rwlock_write_unlock(&tcp_globals.lock); 1385 fibril_rwlock_read_unlock(&tcp_globals.lock); 1386 break; 1387 1388 case NET_SOCKET_CONNECT: 1389 res = async_data_write_accept((void **) &addr, false, 1390 0, 0, 0, &addrlen); 1391 if (res != EOK) 1392 break; 1393 /* 1394 * The global lock may be released in the 1395 * tcp_connect_message() function. 1396 */ 1397 fibril_rwlock_write_lock(&tcp_globals.lock); 1398 fibril_rwlock_write_lock(&lock); 1399 res = tcp_connect_message(&local_sockets, 1400 SOCKET_GET_SOCKET_ID(call), addr, addrlen); 1401 if (res != EOK) { 1402 fibril_rwlock_write_unlock(&lock); 1403 fibril_rwlock_write_unlock(&tcp_globals.lock); 1404 free(addr); 1405 } 1406 break; 1407 1408 case NET_SOCKET_ACCEPT: 1409 fibril_rwlock_read_lock(&tcp_globals.lock); 1410 fibril_rwlock_write_lock(&lock); 1411 res = tcp_accept_message(&local_sockets, 1412 SOCKET_GET_SOCKET_ID(call), 1413 SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen); 1414 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1415 fibril_rwlock_write_unlock(&lock); 1416 fibril_rwlock_read_unlock(&tcp_globals.lock); 1417 if (res > 0) { 1418 SOCKET_SET_SOCKET_ID(answer, res); 1419 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 1420 answer_count = 3; 1421 } 1422 break; 1423 1424 case NET_SOCKET_SEND: 1425 fibril_rwlock_read_lock(&tcp_globals.lock); 1426 fibril_rwlock_write_lock(&lock); 1427 res = tcp_send_message(&local_sockets, 1428 SOCKET_GET_SOCKET_ID(call), 1429 SOCKET_GET_DATA_FRAGMENTS(call), &size, 1430 SOCKET_GET_FLAGS(call)); 1431 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1432 if (res != EOK) { 1433 fibril_rwlock_write_unlock(&lock); 1434 fibril_rwlock_read_unlock(&tcp_globals.lock); 1435 } else { 1436 answer_count = 2; 1437 } 1438 break; 1439 1440 case NET_SOCKET_SENDTO: 1441 res = async_data_write_accept((void **) &addr, false, 1442 0, 0, 0, &addrlen); 1443 if (res != EOK) 1444 break; 1445 fibril_rwlock_read_lock(&tcp_globals.lock); 1446 fibril_rwlock_write_lock(&lock); 1447 res = tcp_send_message(&local_sockets, 1448 SOCKET_GET_SOCKET_ID(call), 1449 SOCKET_GET_DATA_FRAGMENTS(call), &size, 1450 SOCKET_GET_FLAGS(call)); 1451 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 1452 if (res != EOK) { 1453 fibril_rwlock_write_unlock(&lock); 1454 fibril_rwlock_read_unlock(&tcp_globals.lock); 1455 } else { 1456 answer_count = 2; 1457 } 1458 free(addr); 1459 break; 1460 1461 case NET_SOCKET_RECV: 1462 fibril_rwlock_read_lock(&tcp_globals.lock); 1463 fibril_rwlock_write_lock(&lock); 1464 res = tcp_recvfrom_message(&local_sockets, 1465 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 1466 NULL); 1467 fibril_rwlock_write_unlock(&lock); 1468 fibril_rwlock_read_unlock(&tcp_globals.lock); 1469 if (res > 0) { 1470 SOCKET_SET_READ_DATA_LENGTH(answer, res); 1471 answer_count = 1; 1472 res = EOK; 1473 } 1474 break; 1475 1476 case NET_SOCKET_RECVFROM: 1477 fibril_rwlock_read_lock(&tcp_globals.lock); 1478 fibril_rwlock_write_lock(&lock); 1479 res = tcp_recvfrom_message(&local_sockets, 1480 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 1481 &addrlen); 1482 fibril_rwlock_write_unlock(&lock); 1483 fibril_rwlock_read_unlock(&tcp_globals.lock); 1484 if (res > 0) { 1485 SOCKET_SET_READ_DATA_LENGTH(answer, res); 1486 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 1487 answer_count = 3; 1488 res = EOK; 1489 } 1490 break; 1491 1492 case NET_SOCKET_CLOSE: 1493 fibril_rwlock_write_lock(&tcp_globals.lock); 1494 fibril_rwlock_write_lock(&lock); 1495 res = tcp_close_message(&local_sockets, 1496 SOCKET_GET_SOCKET_ID(call)); 1497 if (res != EOK) { 1498 fibril_rwlock_write_unlock(&lock); 1499 fibril_rwlock_write_unlock(&tcp_globals.lock); 1500 } 1501 break; 1502 1503 case NET_SOCKET_GETSOCKOPT: 1504 case NET_SOCKET_SETSOCKOPT: 1505 default: 1506 res = ENOTSUP; 1507 break; 1508 } 1509 } 1510 1511 /* Release the application session */ 1512 async_hangup(sess); 1513 1514 printf("release\n"); 1515 /* Release all local sockets */ 1516 socket_cores_release(tcp_globals.net_sess, &local_sockets, 1517 &tcp_globals.sockets, tcp_free_socket_data); 1518 1519 return EOK; 1520 } 1521 1522 int tcp_timeout(void *data) 1523 { 1524 tcp_timeout_t *timeout = data; 1525 int keep_write_lock = false; 1526 socket_core_t *socket; 1527 tcp_socket_data_t *socket_data; 1528 1529 assert(timeout); 1530 1531 /* Sleep the given timeout */ 1532 async_usleep(timeout->timeout); 1533 /* Lock the globals */ 1534 if (timeout->globals_read_only) 1535 fibril_rwlock_read_lock(&tcp_globals.lock); 1536 else 1537 fibril_rwlock_write_lock(&tcp_globals.lock); 1538 1539 /* Find the pending operation socket */ 1540 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1541 timeout->key, timeout->key_length); 1542 if (!socket || (socket->socket_id != timeout->socket_id)) 1543 goto out; 1544 1545 socket_data = (tcp_socket_data_t *) socket->specific_data; 1546 assert(socket_data); 1547 if (socket_data->local_sockets != timeout->local_sockets) 1548 goto out; 1549 1550 fibril_rwlock_write_lock(socket_data->local_lock); 1551 if (timeout->sequence_number) { 1552 /* Increase the timeout counter */ 1553 socket_data->timeout_count++; 1554 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) { 1555 /* TODO release as connection lost */ 1556 //tcp_refresh_socket_data(socket_data); 1557 fibril_rwlock_write_unlock(socket_data->local_lock); 1558 } else { 1559 /* Retransmit */ 1560 // tcp_retransmit_packet(socket, 1561 // socket_data, timeout->sequence_number); 1562 fibril_rwlock_write_unlock(socket_data->local_lock); 1563 } 1564 } else { 1565 fibril_mutex_lock(&socket_data->operation.mutex); 1566 /* Set the timeout operation result if state not changed */ 1567 if (socket_data->state == timeout->state) { 1568 socket_data->operation.result = ETIMEOUT; 1569 1570 /* Notify the main fibril */ 1571 fibril_condvar_signal(&socket_data->operation.condvar); 1572 1573 /* Keep the global write lock */ 1574 keep_write_lock = true; 1575 } else { 1576 /* 1577 * Operation is ok, do nothing. 1578 * Unlocking from now on, so the unlocking 1579 * order does not matter. 1580 */ 1581 fibril_rwlock_write_unlock(socket_data->local_lock); 1582 } 1583 fibril_mutex_unlock(&socket_data->operation.mutex); 1584 } 1585 1586 out: 1587 /* Unlock only if no socket */ 1588 if (timeout->globals_read_only) 1589 fibril_rwlock_read_unlock(&tcp_globals.lock); 1590 else if (!keep_write_lock) 1591 /* Release if not desired */ 1592 fibril_rwlock_write_unlock(&tcp_globals.lock); 1593 1594 /* Release the timeout structure */ 1595 free(timeout); 1596 return EOK; 1597 } 1598 1599 int tcp_release_after_timeout(void *data) 1600 { 1601 tcp_timeout_t *timeout = data; 1602 socket_core_t *socket; 1603 tcp_socket_data_t *socket_data; 1604 fibril_rwlock_t *local_lock; 1605 1606 assert(timeout); 1607 1608 /* Sleep the given timeout */ 1609 async_usleep(timeout->timeout); 1610 1611 /* Lock the globals */ 1612 fibril_rwlock_write_lock(&tcp_globals.lock); 1613 1614 /* Find the pending operation socket */ 1615 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1616 timeout->key, timeout->key_length); 1617 1618 if (socket && (socket->socket_id == timeout->socket_id)) { 1619 socket_data = (tcp_socket_data_t *) socket->specific_data; 1620 assert(socket_data); 1621 if (socket_data->local_sockets == timeout->local_sockets) { 1622 local_lock = socket_data->local_lock; 1623 fibril_rwlock_write_lock(local_lock); 1624 socket_destroy(tcp_globals.net_sess, 1625 timeout->socket_id, timeout->local_sockets, 1626 &tcp_globals.sockets, tcp_free_socket_data); 1627 fibril_rwlock_write_unlock(local_lock); 1628 } 1629 } 1630 1631 /* Unlock the globals */ 1632 fibril_rwlock_write_unlock(&tcp_globals.lock); 1633 1634 /* Release the timeout structure */ 1635 free(timeout); 1636 1637 return EOK; 1638 } 1639 1640 void tcp_retransmit_packet(socket_core_t *socket, tcp_socket_data_t * 1641 socket_data, size_t sequence_number) 1642 { 1643 packet_t *packet; 1644 packet_t *copy; 1645 size_t data_length; 1646 1647 assert(socket); 1648 assert(socket_data); 1649 assert(socket->specific_data == socket_data); 1650 1651 /* Sent packet? */ 1652 packet = pq_find(socket_data->outgoing, sequence_number); 1653 printf("retransmit %d\n", packet_get_id(packet)); 1654 if (packet) { 1655 pq_get_order(packet, NULL, &data_length); 1656 copy = tcp_prepare_copy(socket, socket_data, packet, 1657 data_length, sequence_number); 1658 fibril_rwlock_write_unlock(socket_data->local_lock); 1659 // printf("r send %d\n", packet_get_id(packet)); 1660 if (copy) 1661 tcp_send_packets(socket_data->device_id, copy); 1662 } else { 1663 fibril_rwlock_write_unlock(socket_data->local_lock); 1664 } 1665 } 1666 1667 int tcp_listen_message(socket_cores_t *local_sockets, int socket_id, 1668 int backlog) 1669 { 1670 socket_core_t *socket; 1671 tcp_socket_data_t *socket_data; 1672 1673 assert(local_sockets); 1674 1675 if (backlog < 0) 1676 return EINVAL; 1677 1678 /* Find the socket */ 1679 socket = socket_cores_find(local_sockets, socket_id); 1680 if (!socket) 1681 return ENOTSOCK; 1682 1683 /* Get the socket specific data */ 1684 socket_data = (tcp_socket_data_t *) socket->specific_data; 1685 assert(socket_data); 1686 1687 /* Set the backlog */ 1688 socket_data->backlog = backlog; 1689 1690 return EOK; 1691 } 1692 1693 int tcp_connect_message(socket_cores_t *local_sockets, int socket_id, 1694 struct sockaddr *addr, socklen_t addrlen) 1695 { 1696 socket_core_t *socket; 1697 int rc; 1698 1699 assert(local_sockets); 1700 assert(addr); 1701 assert(addrlen > 0); 1702 1703 /* Find the socket */ 1704 socket = socket_cores_find(local_sockets, socket_id); 1705 if (!socket) 1706 return ENOTSOCK; 1707 1708 rc = tcp_connect_core(socket, local_sockets, addr, addrlen); 1709 if (rc != EOK) { 1710 tcp_free_socket_data(socket); 1711 /* Unbind if bound */ 1712 if (socket->port > 0) { 1713 socket_ports_exclude(&tcp_globals.sockets, 1714 socket->port, free); 1715 socket->port = 0; 1716 } 1717 } 1718 return rc; 1719 } 1720 1721 int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets, 1722 struct sockaddr *addr, socklen_t addrlen) 1723 { 1724 tcp_socket_data_t *socket_data; 246 /** Receive packets from network layer. */ 247 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 248 { 1725 249 packet_t *packet; 1726 250 int rc; 1727 251 1728 assert(socket); 1729 assert(addr); 1730 assert(addrlen > 0); 1731 1732 /* Get the socket specific data */ 1733 socket_data = (tcp_socket_data_t *) socket->specific_data; 1734 assert(socket_data); 1735 assert(socket->specific_data == socket_data); 1736 if ((socket_data->state != TCP_SOCKET_INITIAL) && 1737 ((socket_data->state != TCP_SOCKET_LISTEN) || 1738 (socket->port <= 0))) 1739 return EINVAL; 1740 1741 /* Get the destination port */ 1742 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port); 1743 if (rc != EOK) 1744 return rc; 1745 1746 if (socket->port <= 0) { 1747 /* Try to find a free port */ 1748 rc = socket_bind_free_port(&tcp_globals.sockets, socket, 1749 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 1750 tcp_globals.last_used_port); 1751 if (rc != EOK) 1752 return rc; 1753 /* Set the next port as the search starting port number */ 1754 tcp_globals.last_used_port = socket->port; 1755 } 1756 1757 rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP, 1758 addr, addrlen, &socket_data->device_id, 1759 &socket_data->pseudo_header, &socket_data->headerlen); 1760 if (rc != EOK) 1761 return rc; 1762 1763 /* Create the notification packet */ 1764 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0); 1765 if (rc != EOK) 1766 return rc; 1767 1768 /* Unlock the globals and wait for an operation */ 1769 fibril_rwlock_write_unlock(&tcp_globals.lock); 1770 1771 socket_data->addr = addr; 1772 socket_data->addrlen = addrlen; 1773 1774 /* Send the packet */ 1775 1776 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) || 1777 ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, 1778 TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) != 1779 EOK)) { 1780 socket_data->addr = NULL; 1781 socket_data->addrlen = 0; 1782 fibril_rwlock_write_lock(&tcp_globals.lock); 1783 } else { 1784 packet = tcp_get_packets_to_send(socket, socket_data); 1785 if (packet) { 1786 fibril_mutex_lock(&socket_data->operation.mutex); 1787 fibril_rwlock_write_unlock(socket_data->local_lock); 1788 1789 socket_data->state = TCP_SOCKET_SYN_SENT; 1790 1791 /* Send the packet */ 1792 printf("connecting %d\n", packet_get_id(packet)); 1793 tcp_send_packets(socket_data->device_id, packet); 1794 1795 /* Wait for a reply */ 1796 fibril_condvar_wait(&socket_data->operation.condvar, 1797 &socket_data->operation.mutex); 1798 rc = socket_data->operation.result; 1799 if (rc != EOK) { 1800 socket_data->addr = NULL; 1801 socket_data->addrlen = 0; 1802 } 1803 } else { 1804 socket_data->addr = NULL; 1805 socket_data->addrlen = 0; 1806 rc = EINTR; 1807 } 1808 } 1809 1810 fibril_mutex_unlock(&socket_data->operation.mutex); 1811 return rc; 1812 } 1813 1814 int tcp_queue_prepare_packet(socket_core_t *socket, 1815 tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length) 1816 { 1817 tcp_header_t *header; 1818 int rc; 1819 1820 assert(socket); 1821 assert(socket_data); 1822 assert(socket->specific_data == socket_data); 1823 1824 /* Get TCP header */ 1825 header = (tcp_header_t *) packet_get_data(packet); 1826 if (!header) 1827 return NO_DATA; 1828 1829 header->destination_port = htons(socket_data->dest_port); 1830 header->source_port = htons(socket->port); 1831 header->sequence_number = htonl(socket_data->next_outgoing); 1832 1833 rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, 1834 socket_data->addrlen); 1835 if (rc != EOK) 1836 return tcp_release_and_return(packet, EINVAL); 1837 1838 /* Remember the outgoing FIN */ 1839 if (GET_TCP_HEADER_FINALIZE(header)) 1840 socket_data->fin_outgoing = socket_data->next_outgoing; 1841 1842 return EOK; 1843 } 1844 1845 int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data, 1846 packet_t *packet, size_t data_length) 1847 { 1848 int rc; 1849 1850 assert(socket); 1851 assert(socket_data); 1852 assert(socket->specific_data == socket_data); 1853 1854 rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length); 1855 if (rc != EOK) 1856 return rc; 1857 1858 rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, 1859 data_length); 1860 if (rc != EOK) 1861 return tcp_release_and_return(packet, rc); 1862 1863 socket_data->next_outgoing += data_length; 1864 return EOK; 1865 } 1866 1867 packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t * 1868 socket_data) 1869 { 1870 packet_t *packet; 1871 packet_t *copy; 1872 packet_t *sending = NULL; 1873 packet_t *previous = NULL; 1874 size_t data_length; 1875 int rc; 1876 1877 assert(socket); 1878 assert(socket_data); 1879 assert(socket->specific_data == socket_data); 1880 1881 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1); 1882 while (packet) { 1883 pq_get_order(packet, NULL, &data_length); 1884 1885 /* 1886 * Send only if fits into the window, respecting the possible 1887 * overflow. 1888 */ 1889 if (!IS_IN_INTERVAL_OVERFLOW( 1890 (uint32_t) socket_data->last_outgoing, 1891 (uint32_t) (socket_data->last_outgoing + data_length), 1892 (uint32_t) (socket_data->expected + socket_data->treshold))) 1893 break; 1894 1895 copy = tcp_prepare_copy(socket, socket_data, packet, 1896 data_length, socket_data->last_outgoing + 1); 1897 if (!copy) 1898 return sending; 1899 1900 if (!sending) { 1901 sending = copy; 1902 } else { 1903 rc = pq_insert_after(previous, copy); 1904 if (rc != EOK) { 1905 pq_release_remote(tcp_globals.net_sess, 1906 packet_get_id(copy)); 1907 return sending; 1908 } 1909 } 1910 1911 previous = copy; 1912 packet = pq_next(packet); 1913 1914 /* Overflow occurred? */ 1915 if (!packet && 1916 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1917 printf("gpts overflow\n"); 1918 /* Continue from the beginning */ 1919 packet = socket_data->outgoing; 1920 } 1921 socket_data->last_outgoing += data_length; 1922 } 1923 1924 return sending; 1925 } 1926 1927 packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t * 1928 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1929 { 1930 tcp_header_t *header; 1931 uint32_t checksum; 1932 int rc; 1933 1934 assert(socket); 1935 assert(socket_data); 1936 assert(socket->specific_data == socket_data); 1937 1938 /* Adjust the pseudo header */ 1939 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, 1940 socket_data->headerlen, packet_get_data_length(packet)); 1941 if (rc != EOK) { 1942 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1943 return NULL; 1944 } 1945 1946 /* Get the header */ 1947 header = (tcp_header_t *) packet_get_data(packet); 1948 if (!header) { 1949 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1950 return NULL; 1951 } 1952 assert(ntohl(header->sequence_number) == sequence_number); 1953 1954 /* Adjust the header */ 1955 if (socket_data->next_incoming) { 1956 header->acknowledgement_number = 1957 htonl(socket_data->next_incoming); 1958 SET_TCP_HEADER_ACKNOWLEDGE(header, 1); 1959 } 1960 header->window = htons(socket_data->window); 1961 1962 /* Checksum */ 1963 header->checksum = 0; 1964 checksum = compute_checksum(0, socket_data->pseudo_header, 1965 socket_data->headerlen); 1966 checksum = compute_checksum(checksum, 1967 (uint8_t *) packet_get_data(packet), 1968 packet_get_data_length(packet)); 1969 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 1970 1971 /* Prepare the packet */ 1972 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 1973 if (rc != EOK) { 1974 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1975 return NULL; 1976 } 1977 1978 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1979 sequence_number, socket_data->state, socket_data->timeout, true); 1980 if (rc != EOK) { 1981 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1982 return NULL; 1983 } 1984 1985 return packet; 1986 } 1987 1988 packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t * 1989 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1990 { 1991 packet_t *copy; 1992 1993 assert(socket); 1994 assert(socket_data); 1995 assert(socket->specific_data == socket_data); 1996 1997 /* Make a copy of the packet */ 1998 copy = packet_get_copy(tcp_globals.net_sess, packet); 1999 if (!copy) 2000 return NULL; 2001 2002 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, 2003 sequence_number); 2004 } 2005 2006 void tcp_send_packets(device_id_t device_id, packet_t *packet) 2007 { 2008 packet_t *next; 2009 2010 while (packet) { 2011 next = pq_detach(packet); 2012 ip_send_msg(tcp_globals.ip_sess, device_id, packet, 2013 SERVICE_TCP, 0); 2014 packet = next; 2015 } 2016 } 2017 2018 void tcp_prepare_operation_header(socket_core_t *socket, 2019 tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize, 2020 int finalize) 2021 { 2022 assert(socket); 2023 assert(socket_data); 2024 assert(socket->specific_data == socket_data); 2025 assert(header); 2026 2027 bzero(header, sizeof(*header)); 2028 header->source_port = htons(socket->port); 2029 header->source_port = htons(socket_data->dest_port); 2030 SET_TCP_HEADER_LENGTH(header, 2031 TCP_COMPUTE_HEADER_LENGTH(sizeof(*header))); 2032 SET_TCP_HEADER_SYNCHRONIZE(header, synchronize); 2033 SET_TCP_HEADER_FINALIZE(header, finalize); 2034 } 2035 2036 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 2037 socket_core_t *socket, tcp_socket_data_t *socket_data, 2038 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, 2039 int globals_read_only) 2040 { 2041 tcp_timeout_t *operation_timeout; 2042 fid_t fibril; 2043 2044 assert(socket); 2045 assert(socket_data); 2046 assert(socket->specific_data == socket_data); 2047 2048 /* Prepare the timeout with key bundle structure */ 2049 operation_timeout = malloc(sizeof(*operation_timeout) + 2050 socket->key_length + 1); 2051 if (!operation_timeout) 2052 return ENOMEM; 2053 2054 bzero(operation_timeout, sizeof(*operation_timeout)); 2055 operation_timeout->globals_read_only = globals_read_only; 2056 operation_timeout->port = socket->port; 2057 operation_timeout->local_sockets = socket_data->local_sockets; 2058 operation_timeout->socket_id = socket->socket_id; 2059 operation_timeout->timeout = timeout; 2060 operation_timeout->sequence_number = sequence_number; 2061 operation_timeout->state = state; 2062 2063 /* Copy the key */ 2064 operation_timeout->key = ((uint8_t *) operation_timeout) + 2065 sizeof(*operation_timeout); 2066 operation_timeout->key_length = socket->key_length; 2067 memcpy(operation_timeout->key, socket->key, socket->key_length); 2068 operation_timeout->key[operation_timeout->key_length] = '\0'; 2069 2070 /* Prepare the timeouting thread */ 2071 fibril = fibril_create(timeout_function, operation_timeout); 2072 if (!fibril) { 2073 free(operation_timeout); 2074 return ENOMEM; 2075 } 2076 2077 // fibril_mutex_lock(&socket_data->operation.mutex); 2078 /* Start the timeout fibril */ 2079 fibril_add_ready(fibril); 2080 //socket_data->state = state; 2081 return EOK; 2082 } 2083 2084 int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 2085 int flags, size_t *addrlen) 2086 { 2087 socket_core_t *socket; 2088 tcp_socket_data_t *socket_data; 2089 int packet_id; 2090 packet_t *packet; 2091 size_t length; 2092 int rc; 2093 2094 assert(local_sockets); 2095 2096 /* Find the socket */ 2097 socket = socket_cores_find(local_sockets, socket_id); 2098 if (!socket) 2099 return ENOTSOCK; 2100 2101 /* Get the socket specific data */ 2102 if (!socket->specific_data) 2103 return NO_DATA; 2104 2105 socket_data = (tcp_socket_data_t *) socket->specific_data; 2106 2107 /* Check state */ 2108 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2109 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2110 return ENOTCONN; 2111 2112 /* Send the source address if desired */ 2113 if (addrlen) { 2114 rc = data_reply(socket_data->addr, socket_data->addrlen); 2115 if (rc != EOK) 2116 return rc; 2117 *addrlen = socket_data->addrlen; 2118 } 2119 2120 /* Get the next received packet */ 2121 packet_id = dyn_fifo_value(&socket->received); 2122 if (packet_id < 0) 2123 return NO_DATA; 2124 2125 rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id); 2126 if (rc != EOK) 2127 return rc; 2128 2129 /* Reply the packets */ 2130 rc = socket_reply_packets(packet, &length); 2131 if (rc != EOK) 2132 return rc; 2133 2134 /* Release the packet */ 2135 dyn_fifo_pop(&socket->received); 2136 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2137 2138 /* Return the total length */ 2139 return (int) length; 2140 } 2141 2142 int tcp_send_message(socket_cores_t *local_sockets, int socket_id, 2143 int fragments, size_t *data_fragment_size, int flags) 2144 { 2145 socket_core_t *socket; 2146 tcp_socket_data_t *socket_data; 2147 packet_dimension_t *packet_dimension; 2148 packet_t *packet; 2149 size_t total_length; 2150 tcp_header_t *header; 2151 int index; 2152 int result; 2153 int rc; 2154 2155 assert(local_sockets); 2156 assert(data_fragment_size); 2157 2158 /* Find the socket */ 2159 socket = socket_cores_find(local_sockets, socket_id); 2160 if (!socket) 2161 return ENOTSOCK; 2162 2163 /* Get the socket specific data */ 2164 if (!socket->specific_data) 2165 return NO_DATA; 2166 2167 socket_data = (tcp_socket_data_t *) socket->specific_data; 2168 2169 /* Check state */ 2170 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2171 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2172 return ENOTCONN; 2173 2174 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2175 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2176 if (rc != EOK) 2177 return rc; 2178 2179 *data_fragment_size = 2180 ((packet_dimension->content < socket_data->data_fragment_size) ? 2181 packet_dimension->content : socket_data->data_fragment_size); 2182 2183 for (index = 0; index < fragments; index++) { 2184 /* Read the data fragment */ 2185 result = tl_socket_read_packet_data(tcp_globals.net_sess, 2186 &packet, TCP_HEADER_SIZE, packet_dimension, 2187 socket_data->addr, socket_data->addrlen); 2188 if (result < 0) 2189 return result; 2190 2191 total_length = (size_t) result; 2192 2193 /* Prefix the TCP header */ 2194 header = PACKET_PREFIX(packet, tcp_header_t); 2195 if (!header) 2196 return tcp_release_and_return(packet, ENOMEM); 2197 2198 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 2199 rc = tcp_queue_packet(socket, socket_data, packet, total_length); 2200 if (rc != EOK) 2201 return rc; 2202 } 2203 2204 /* Flush packets */ 2205 packet = tcp_get_packets_to_send(socket, socket_data); 2206 fibril_rwlock_write_unlock(socket_data->local_lock); 2207 fibril_rwlock_read_unlock(&tcp_globals.lock); 2208 2209 if (packet) { 2210 /* Send the packet */ 2211 tcp_send_packets(socket_data->device_id, packet); 2212 } 2213 2214 return EOK; 2215 } 2216 2217 int 2218 tcp_close_message(socket_cores_t *local_sockets, int socket_id) 2219 { 2220 socket_core_t *socket; 2221 tcp_socket_data_t *socket_data; 2222 packet_t *packet; 2223 int rc; 2224 2225 /* Find the socket */ 2226 socket = socket_cores_find(local_sockets, socket_id); 2227 if (!socket) 2228 return ENOTSOCK; 2229 2230 /* Get the socket specific data */ 2231 socket_data = (tcp_socket_data_t *) socket->specific_data; 2232 assert(socket_data); 2233 2234 /* Check state */ 2235 switch (socket_data->state) { 2236 case TCP_SOCKET_ESTABLISHED: 2237 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 2238 break; 2239 2240 case TCP_SOCKET_CLOSE_WAIT: 2241 socket_data->state = TCP_SOCKET_LAST_ACK; 2242 break; 2243 2244 // case TCP_SOCKET_LISTEN: 2245 2246 default: 2247 /* Just destroy */ 2248 rc = socket_destroy(tcp_globals.net_sess, socket_id, 2249 local_sockets, &tcp_globals.sockets, 2250 tcp_free_socket_data); 2251 if (rc == EOK) { 2252 fibril_rwlock_write_unlock(socket_data->local_lock); 2253 fibril_rwlock_write_unlock(&tcp_globals.lock); 2254 } 2255 return rc; 2256 } 2257 2258 /* 2259 * Send FIN. 2260 * TODO should I wait to complete? 2261 */ 2262 2263 /* Create the notification packet */ 2264 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 2265 if (rc != EOK) 2266 return rc; 2267 2268 /* Send the packet */ 2269 rc = tcp_queue_packet(socket, socket_data, packet, 1); 2270 if (rc != EOK) 2271 return rc; 2272 2273 /* Flush packets */ 2274 packet = tcp_get_packets_to_send(socket, socket_data); 2275 fibril_rwlock_write_unlock(socket_data->local_lock); 2276 fibril_rwlock_write_unlock(&tcp_globals.lock); 2277 2278 if (packet) { 2279 /* Send the packet */ 2280 tcp_send_packets(socket_data->device_id, packet); 2281 } 2282 2283 return EOK; 2284 } 2285 2286 int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket, 2287 tcp_socket_data_t *socket_data, int synchronize, int finalize) 2288 { 2289 packet_dimension_t *packet_dimension; 2290 tcp_header_t *header; 2291 int rc; 2292 2293 assert(packet); 2294 2295 /* Get the device packet dimension */ 2296 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2297 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2298 if (rc != EOK) 2299 return rc; 2300 2301 /* Get a new packet */ 2302 *packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE, 2303 packet_dimension->addr_len, packet_dimension->prefix, 2304 packet_dimension->suffix); 2305 2306 if (!*packet) 2307 return ENOMEM; 2308 2309 /* Allocate space in the packet */ 2310 header = PACKET_SUFFIX(*packet, tcp_header_t); 2311 if (!header) 2312 tcp_release_and_return(*packet, ENOMEM); 2313 2314 tcp_prepare_operation_header(socket, socket_data, header, synchronize, 2315 finalize); 2316 2317 return EOK; 2318 } 2319 2320 int tcp_accept_message(socket_cores_t *local_sockets, int socket_id, 2321 int new_socket_id, size_t *data_fragment_size, size_t *addrlen) 2322 { 2323 socket_core_t *accepted; 2324 socket_core_t *socket; 2325 tcp_socket_data_t *socket_data; 2326 packet_dimension_t *packet_dimension; 2327 int rc; 2328 2329 assert(local_sockets); 2330 assert(data_fragment_size); 2331 assert(addrlen); 2332 2333 /* Find the socket */ 2334 socket = socket_cores_find(local_sockets, socket_id); 2335 if (!socket) 2336 return ENOTSOCK; 2337 2338 /* Get the socket specific data */ 2339 socket_data = (tcp_socket_data_t *) socket->specific_data; 2340 assert(socket_data); 2341 2342 /* Check state */ 2343 if (socket_data->state != TCP_SOCKET_LISTEN) 2344 return EINVAL; 2345 2346 do { 2347 socket_id = dyn_fifo_value(&socket->accepted); 2348 if (socket_id < 0) 2349 return ENOTSOCK; 2350 socket_id *= -1; 2351 2352 accepted = socket_cores_find(local_sockets, socket_id); 2353 if (!accepted) 2354 return ENOTSOCK; 2355 2356 /* Get the socket specific data */ 2357 socket_data = (tcp_socket_data_t *) accepted->specific_data; 2358 assert(socket_data); 2359 /* TODO can it be in another state? */ 2360 if (socket_data->state == TCP_SOCKET_ESTABLISHED) { 2361 rc = data_reply(socket_data->addr, 2362 socket_data->addrlen); 2363 if (rc != EOK) 2364 return rc; 2365 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2366 &tcp_globals.dimensions, socket_data->device_id, 2367 &packet_dimension); 2368 if (rc != EOK) 2369 return rc; 2370 *addrlen = socket_data->addrlen; 2371 2372 *data_fragment_size = 2373 ((packet_dimension->content < 2374 socket_data->data_fragment_size) ? 2375 packet_dimension->content : 2376 socket_data->data_fragment_size); 2377 2378 if (new_socket_id > 0) { 2379 rc = socket_cores_update(local_sockets, 2380 accepted->socket_id, new_socket_id); 2381 if (rc != EOK) 2382 return rc; 2383 accepted->socket_id = new_socket_id; 2384 } 2385 } 2386 dyn_fifo_pop(&socket->accepted); 2387 } while (socket_data->state != TCP_SOCKET_ESTABLISHED); 2388 2389 printf("ret accept %d\n", accepted->socket_id); 2390 return accepted->socket_id; 2391 } 2392 2393 void tcp_free_socket_data(socket_core_t *socket) 2394 { 2395 tcp_socket_data_t *socket_data; 2396 2397 assert(socket); 2398 2399 printf("destroy_socket %d\n", socket->socket_id); 2400 2401 /* Get the socket specific data */ 2402 socket_data = (tcp_socket_data_t *) socket->specific_data; 2403 assert(socket_data); 2404 2405 /* Free the pseudo header */ 2406 if (socket_data->pseudo_header) { 2407 if (socket_data->headerlen) { 2408 printf("d pseudo\n"); 2409 free(socket_data->pseudo_header); 2410 socket_data->headerlen = 0; 2411 } 2412 socket_data->pseudo_header = NULL; 2413 } 2414 2415 socket_data->headerlen = 0; 2416 2417 /* Free the address */ 2418 if (socket_data->addr) { 2419 if (socket_data->addrlen) { 2420 printf("d addr\n"); 2421 free(socket_data->addr); 2422 socket_data->addrlen = 0; 2423 } 2424 socket_data->addr = NULL; 2425 } 2426 socket_data->addrlen = 0; 2427 } 2428 2429 /** Releases the packet and returns the result. 2430 * 2431 * @param[in] packet The packet queue to be released. 2432 * @param[in] result The result to be returned. 2433 * @return The result parameter. 2434 */ 2435 int tcp_release_and_return(packet_t *packet, int result) 2436 { 2437 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2438 return result; 2439 } 2440 2441 /** Process IPC messages from the IP module 2442 * 2443 * @param[in] iid Message identifier. 2444 * @param[in,out] icall Message parameters. 2445 * @param[in] arg Local argument. 2446 * 2447 */ 2448 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 2449 { 2450 packet_t *packet; 2451 int rc; 2452 252 log_msg(LVL_DEBUG, "tcp_receiver()"); 253 2453 254 while (true) { 2454 255 switch (IPC_GET_IMETHOD(*icall)) { 2455 256 case NET_TL_RECEIVED: 2456 rc = packet_translate_remote(tcp_globals.net_sess, &packet, 257 log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED"); 258 rc = packet_translate_remote(net_sess, &packet, 2457 259 IPC_GET_PACKET(*icall)); 2458 if (rc == EOK) 2459 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 2460 SERVICE_TCP, IPC_GET_ERROR(*icall)); 2461 2462 async_answer_0(iid, (sysarg_t) rc); 260 if (rc != EOK) { 261 log_msg(LVL_DEBUG, "Error %d translating packet.", rc); 262 async_answer_0(iid, (sysarg_t)rc); 263 break; 264 } 265 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 266 IPC_GET_ERROR(*icall)); 267 async_answer_0(iid, (sysarg_t)rc); 2463 268 break; 2464 269 default: 2465 async_answer_0(iid, (sysarg_t) ENOTSUP); 270 log_msg(LVL_DEBUG, "method = %u", 271 (unsigned)IPC_GET_IMETHOD(*icall)); 272 async_answer_0(iid, ENOTSUP); 273 break; 2466 274 } 2467 275 2468 276 iid = async_get_call(icall); 2469 277 } 2470 278 } 2471 279 2472 /** Initialize the TCP module. 2473 * 2474 * @param[in] sess Network module session. 2475 * 2476 * @return EOK on success. 2477 * @return ENOMEM if there is not enough memory left. 2478 * 280 /** Transmit PDU over network layer. */ 281 void tcp_transmit_pdu(tcp_pdu_t *pdu) 282 { 283 struct sockaddr_in dest; 284 nic_device_id_t dev_id; 285 void *phdr; 286 size_t phdr_len; 287 packet_dimension_t *pkt_dim; 288 int rc; 289 packet_t *packet; 290 void *pkt_data; 291 size_t pdu_size; 292 293 dest.sin_family = AF_INET; 294 dest.sin_port = 0; /* not needed */ 295 dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4); 296 297 /* Find route. Obtained pseudo-header is not used. */ 298 rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest, 299 sizeof(dest), &dev_id, &phdr, &phdr_len); 300 if (rc != EOK) { 301 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route."); 302 return; 303 } 304 305 rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim); 306 if (rc != EOK) { 307 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension."); 308 return; 309 } 310 311 pdu_size = pdu->header_size + pdu->text_size; 312 313 packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len, 314 pkt_dim->prefix, pkt_dim->suffix); 315 if (!packet) { 316 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet."); 317 return; 318 } 319 320 pkt_data = packet_suffix(packet, pdu_size); 321 if (!pkt_data) { 322 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr."); 323 pq_release_remote(net_sess, packet_get_id(packet)); 324 return; 325 } 326 327 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 328 if (rc != EOK) { 329 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part."); 330 pq_release_remote(net_sess, packet_get_id(packet)); 331 return; 332 } 333 334 rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest)); 335 if (rc != EOK) { 336 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address."); 337 pq_release_remote(net_sess, packet_get_id(packet)); 338 return; 339 } 340 341 /* Copy PDU data to packet */ 342 memcpy(pkt_data, pdu->header, pdu->header_size); 343 memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text, 344 pdu->text_size); 345 346 /* Transmit packet. XXX Transfers packet ownership to IP? */ 347 ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0); 348 } 349 350 /** Process received PDU. */ 351 static void tcp_received_pdu(tcp_pdu_t *pdu) 352 { 353 tcp_segment_t *dseg; 354 tcp_sockpair_t rident; 355 356 log_msg(LVL_DEBUG, "tcp_received_pdu()"); 357 358 if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) { 359 log_msg(LVL_WARN, "Not enough memory. PDU dropped."); 360 return; 361 } 362 363 /* Insert decoded segment into rqueue */ 364 tcp_rqueue_insert_seg(&rident, dseg); 365 } 366 367 /* Called from libnet */ 368 void tl_connection(void) 369 { 370 log_msg(LVL_DEBUG, "tl_connection()"); 371 } 372 373 /* Called from libnet */ 374 int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 375 size_t *answer_count) 376 { 377 async_sess_t *callback; 378 379 log_msg(LVL_DEBUG, "tl_message()"); 380 381 *answer_count = 0; 382 callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call); 383 if (callback) 384 return tcp_sock_connection(callback, callid, *call); 385 386 return ENOTSUP; 387 } 388 389 /* Called from libnet */ 390 int tl_initialize(async_sess_t *sess) 391 { 392 int rc; 393 394 net_sess = sess; 395 icmp_sess = icmp_connect_module(); 396 397 log_msg(LVL_DEBUG, "tl_initialize()"); 398 399 tcp_sock_init(); 400 401 ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, 402 tcp_receiver); 403 if (ip_sess == NULL) 404 return ENOENT; 405 406 rc = packet_dimensions_initialize(&pkt_dims); 407 if (rc != EOK) 408 return rc; 409 410 return EOK; 411 } 412 413 int main(int argc, char **argv) 414 { 415 int rc; 416 417 printf(NAME ": TCP (Transmission Control Protocol) network module\n"); 418 419 rc = log_init(NAME, LVL_ERROR); 420 if (rc != EOK) { 421 printf(NAME ": Failed to initialize log.\n"); 422 return 1; 423 } 424 425 // printf(NAME ": Accepting connections\n"); 426 // task_retval(0); 427 428 tcp_rqueue_init(); 429 tcp_rqueue_thread_start(); 430 431 tcp_ncsim_init(); 432 tcp_ncsim_thread_start(); 433 434 if (0) tcp_test(); 435 /* 436 async_manager(); 437 */ 438 tl_module_start(SERVICE_TCP); 439 440 /* Not reached */ 441 return 0; 442 } 443 444 /** 445 * @} 2479 446 */ 2480 int tl_initialize(async_sess_t *sess)2481 {2482 fibril_rwlock_initialize(&tcp_globals.lock);2483 fibril_rwlock_write_lock(&tcp_globals.lock);2484 2485 tcp_globals.net_sess = sess;2486 2487 tcp_globals.icmp_sess = icmp_connect_module();2488 tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP,2489 SERVICE_TCP, tcp_receiver);2490 if (tcp_globals.ip_sess == NULL) {2491 fibril_rwlock_write_unlock(&tcp_globals.lock);2492 return ENOENT;2493 }2494 2495 int rc = socket_ports_initialize(&tcp_globals.sockets);2496 if (rc != EOK)2497 goto out;2498 2499 rc = packet_dimensions_initialize(&tcp_globals.dimensions);2500 if (rc != EOK) {2501 socket_ports_destroy(&tcp_globals.sockets, free);2502 goto out;2503 }2504 2505 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;2506 2507 out:2508 fibril_rwlock_write_unlock(&tcp_globals.lock);2509 return rc;2510 }2511 2512 int main(int argc, char *argv[])2513 {2514 return tl_module_start(SERVICE_TCP);2515 }2516 2517 /** @}2518 */
Note:
See TracChangeset
for help on using the changeset viewer.