Changes in uspace/srv/net/tl/tcp/tcp.c [b5eae30:49bd793b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/tcp/tcp.c
rb5eae30 r49bd793b 1 1 /* 2 * Copyright (c) 20 11 Jiri Svoboda2 * Copyright (c) 2008 Lukas Mejdrech 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 33 /** 34 * @file TCP (Transmission Control Protocol) network module 33 /** @file 34 * TCP module implementation. 35 * @see tcp.h 35 36 */ 36 37 38 #include <assert.h> 37 39 #include <async.h> 38 #include <byteorder.h> 40 #include <fibril_synch.h> 41 #include <malloc.h> 42 /* TODO remove stdio */ 43 #include <stdio.h> 39 44 #include <errno.h> 40 #include <io/log.h> 41 #include <stdio.h> 42 #include <task.h> 43 44 #include <icmp_remote.h> 45 46 #include <ipc/services.h> 47 #include <ipc/net.h> 48 #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> 59 #include <packet_client.h> 60 #include <packet_remote.h> 61 #include <net_checksum.h> 45 62 #include <ip_client.h> 46 63 #include <ip_interface.h> 47 #include <ipc/services.h> 48 #include <ipc/tl.h> 64 #include <icmp_client.h> 65 #include <icmp_remote.h> 66 #include <net_interface.h> 67 #include <socket_core.h> 49 68 #include <tl_common.h> 69 #include <tl_remote.h> 50 70 #include <tl_skel.h> 51 #include <packet_client.h> 52 #include <packet_remote.h> 53 54 #include "ncsim.h" 55 #include "pdu.h" 56 #include "rqueue.h" 57 #include "sock.h" 58 #include "std.h" 71 59 72 #include "tcp.h" 60 #include "test.h" 61 62 #define NAME "tcp" 63 64 async_sess_t *net_sess; 65 static async_sess_t *icmp_sess; 66 async_sess_t *ip_sess; 67 packet_dimensions_t pkt_dims; 68 69 static void tcp_received_pdu(tcp_pdu_t *pdu); 70 71 /* Pull up packets into a single memory block. */ 72 static int pq_pullup(packet_t *packet, void **data, size_t *dsize) 73 { 74 packet_t *npacket; 75 size_t tot_len; 76 int length; 77 78 npacket = packet; 79 tot_len = 0; 80 do { 81 length = packet_get_data_length(packet); 82 if (length <= 0) 83 return EINVAL; 84 85 tot_len += length; 86 } while ((npacket = pq_next(npacket)) != NULL); 87 88 uint8_t *buf; 89 uint8_t *dp; 90 91 buf = calloc(tot_len, 1); 92 if (buf == NULL) { 93 free(buf); 94 return ENOMEM; 95 } 96 97 npacket = packet; 98 dp = buf; 99 do { 100 length = packet_get_data_length(packet); 101 if (length <= 0) { 102 free(buf); 103 return EINVAL; 104 } 105 106 memcpy(dp, packet_get_data(packet), length); 107 dp += length; 108 } while ((npacket = pq_next(npacket)) != NULL); 109 110 *data = buf; 111 *dsize = tot_len; 112 return EOK; 113 } 114 115 /** Process packet received from network layer. */ 116 static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet, 117 services_t error) 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(nic_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(nic_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(nic_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(nic_device_id_t device_id, packet_t *packet, 223 services_t receiver, services_t error) 118 224 { 119 225 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(nic_device_id_t device_id, packet_t *packet, services_t error) 241 { 242 size_t length; 120 243 size_t offset; 121 int length; 122 struct sockaddr_in *src_addr; 123 struct sockaddr_in *dest_addr; 124 size_t addr_len; 125 126 log_msg(LVL_DEBUG, "tcp_received_msg()"); 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; 127 258 128 259 switch (error) { … … 130 261 break; 131 262 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; 132 274 default: 133 log_msg(LVL_WARN, "Unsupported service number %u", 134 (unsigned)error); 135 pq_release_remote(net_sess, packet_get_id(packet)); 136 return ENOTSUP; 137 } 138 139 /* Process and trim off IP header */ 140 log_msg(LVL_DEBUG, "tcp_received_msg() - IP header"); 141 142 rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 143 if (rc < 0) { 144 log_msg(LVL_WARN, "ip_client_process_packet() failed"); 145 pq_release_remote(net_sess, packet_get_id(packet)); 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 285 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 */ 293 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 } 449 450 return EOK; 451 } 452 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); 146 1028 return rc; 147 1029 } 148 1030 149 offset = (size_t)rc; 150 length = packet_get_data_length(packet); 151 152 if (length < 0 || (size_t)length < offset) { 153 log_msg(LVL_WARN, "length=%d, dropping.", length); 154 pq_release_remote(net_sess, packet_get_id(packet)); 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); 155 1036 return EINVAL; 156 1037 } 157 1038 158 addr_len = packet_get_addr(packet, (uint8_t **)&src_addr, 159 (uint8_t **)&dest_addr); 160 if (addr_len <= 0) { 161 log_msg(LVL_WARN, "Failed to get packet address."); 162 pq_release_remote(net_sess, packet_get_id(packet)); 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 = NIC_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, NIC_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 if (packet) { 1654 pq_get_order(packet, NULL, &data_length); 1655 copy = tcp_prepare_copy(socket, socket_data, packet, 1656 data_length, sequence_number); 1657 fibril_rwlock_write_unlock(socket_data->local_lock); 1658 // printf("r send %d\n", packet_get_id(packet)); 1659 if (copy) 1660 tcp_send_packets(socket_data->device_id, copy); 1661 } else { 1662 fibril_rwlock_write_unlock(socket_data->local_lock); 1663 } 1664 } 1665 1666 int tcp_listen_message(socket_cores_t *local_sockets, int socket_id, 1667 int backlog) 1668 { 1669 socket_core_t *socket; 1670 tcp_socket_data_t *socket_data; 1671 1672 assert(local_sockets); 1673 1674 if (backlog < 0) 163 1675 return EINVAL; 164 } 165 166 if (addr_len != sizeof(struct sockaddr_in)) { 167 log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)", 168 addr_len, sizeof(struct sockaddr_in)); 169 pq_release_remote(net_sess, packet_get_id(packet)); 170 return EINVAL; 171 } 172 173 rc = packet_trim(packet, offset, 0); 1676 1677 /* Find the socket */ 1678 socket = socket_cores_find(local_sockets, socket_id); 1679 if (!socket) 1680 return ENOTSOCK; 1681 1682 /* Get the socket specific data */ 1683 socket_data = (tcp_socket_data_t *) socket->specific_data; 1684 assert(socket_data); 1685 1686 /* Set the backlog */ 1687 socket_data->backlog = backlog; 1688 1689 return EOK; 1690 } 1691 1692 int tcp_connect_message(socket_cores_t *local_sockets, int socket_id, 1693 struct sockaddr *addr, socklen_t addrlen) 1694 { 1695 socket_core_t *socket; 1696 int rc; 1697 1698 assert(local_sockets); 1699 assert(addr); 1700 assert(addrlen > 0); 1701 1702 /* Find the socket */ 1703 socket = socket_cores_find(local_sockets, socket_id); 1704 if (!socket) 1705 return ENOTSOCK; 1706 1707 rc = tcp_connect_core(socket, local_sockets, addr, addrlen); 174 1708 if (rc != EOK) { 175 log_msg(LVL_WARN, "Failed to trim packet."); 176 pq_release_remote(net_sess, packet_get_id(packet)); 177 return rc; 178 } 179 180 /* Pull up packets into a single memory block, pdu_raw. */ 181 log_msg(LVL_DEBUG, "tcp_received_msg() - pull up"); 182 uint8_t *pdu_raw; 183 size_t pdu_raw_size = 0; 184 185 pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size); 186 187 /* Split into header and payload. */ 188 189 log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload"); 190 191 tcp_pdu_t *pdu; 192 size_t hdr_size; 193 194 /* XXX Header options */ 195 hdr_size = sizeof(tcp_header_t); 196 197 if (pdu_raw_size < hdr_size) { 198 log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu", 199 pdu_raw_size, hdr_size); 200 pq_release_remote(net_sess, packet_get_id(packet)); 201 return EINVAL; 202 } 203 204 log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu", 205 pdu_raw_size, hdr_size); 206 pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size, 207 pdu_raw_size - hdr_size); 208 if (pdu == NULL) { 209 log_msg(LVL_WARN, "Failed creating PDU. Dropped."); 210 return ENOMEM; 211 } 212 213 free(pdu_raw); 214 215 pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr); 216 pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr); 217 log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x", 218 pdu->src_addr.ipv4, pdu->dest_addr.ipv4); 219 220 tcp_received_pdu(pdu); 221 tcp_pdu_delete(pdu); 222 223 return EOK; 224 } 225 226 /** Receive packets from network layer. */ 227 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 228 { 1709 tcp_free_socket_data(socket); 1710 /* Unbind if bound */ 1711 if (socket->port > 0) { 1712 socket_ports_exclude(&tcp_globals.sockets, 1713 socket->port, free); 1714 socket->port = 0; 1715 } 1716 } 1717 return rc; 1718 } 1719 1720 int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets, 1721 struct sockaddr *addr, socklen_t addrlen) 1722 { 1723 tcp_socket_data_t *socket_data; 229 1724 packet_t *packet; 230 1725 int rc; 231 1726 232 log_msg(LVL_DEBUG, "tcp_receiver()"); 233 1727 assert(socket); 1728 assert(addr); 1729 assert(addrlen > 0); 1730 1731 /* Get the socket specific data */ 1732 socket_data = (tcp_socket_data_t *) socket->specific_data; 1733 assert(socket_data); 1734 assert(socket->specific_data == socket_data); 1735 if ((socket_data->state != TCP_SOCKET_INITIAL) && 1736 ((socket_data->state != TCP_SOCKET_LISTEN) || 1737 (socket->port <= 0))) 1738 return EINVAL; 1739 1740 /* Get the destination port */ 1741 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port); 1742 if (rc != EOK) 1743 return rc; 1744 1745 if (socket->port <= 0) { 1746 /* Try to find a free port */ 1747 rc = socket_bind_free_port(&tcp_globals.sockets, socket, 1748 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, 1749 tcp_globals.last_used_port); 1750 if (rc != EOK) 1751 return rc; 1752 /* Set the next port as the search starting port number */ 1753 tcp_globals.last_used_port = socket->port; 1754 } 1755 1756 rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP, 1757 addr, addrlen, &socket_data->device_id, 1758 &socket_data->pseudo_header, &socket_data->headerlen); 1759 if (rc != EOK) 1760 return rc; 1761 1762 /* Create the notification packet */ 1763 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0); 1764 if (rc != EOK) 1765 return rc; 1766 1767 /* Unlock the globals and wait for an operation */ 1768 fibril_rwlock_write_unlock(&tcp_globals.lock); 1769 1770 socket_data->addr = addr; 1771 socket_data->addrlen = addrlen; 1772 1773 /* Send the packet */ 1774 1775 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) || 1776 ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0, 1777 TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) != 1778 EOK)) { 1779 socket_data->addr = NULL; 1780 socket_data->addrlen = 0; 1781 fibril_rwlock_write_lock(&tcp_globals.lock); 1782 } else { 1783 packet = tcp_get_packets_to_send(socket, socket_data); 1784 if (packet) { 1785 fibril_mutex_lock(&socket_data->operation.mutex); 1786 fibril_rwlock_write_unlock(socket_data->local_lock); 1787 1788 socket_data->state = TCP_SOCKET_SYN_SENT; 1789 1790 /* Send the packet */ 1791 tcp_send_packets(socket_data->device_id, packet); 1792 1793 /* Wait for a reply */ 1794 fibril_condvar_wait(&socket_data->operation.condvar, 1795 &socket_data->operation.mutex); 1796 rc = socket_data->operation.result; 1797 if (rc != EOK) { 1798 socket_data->addr = NULL; 1799 socket_data->addrlen = 0; 1800 } 1801 } else { 1802 socket_data->addr = NULL; 1803 socket_data->addrlen = 0; 1804 rc = EINTR; 1805 } 1806 } 1807 1808 fibril_mutex_unlock(&socket_data->operation.mutex); 1809 return rc; 1810 } 1811 1812 int tcp_queue_prepare_packet(socket_core_t *socket, 1813 tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length) 1814 { 1815 tcp_header_t *header; 1816 int rc; 1817 1818 assert(socket); 1819 assert(socket_data); 1820 assert(socket->specific_data == socket_data); 1821 1822 /* Get TCP header */ 1823 header = (tcp_header_t *) packet_get_data(packet); 1824 if (!header) 1825 return NO_DATA; 1826 1827 header->destination_port = htons(socket_data->dest_port); 1828 header->source_port = htons(socket->port); 1829 header->sequence_number = htonl(socket_data->next_outgoing); 1830 1831 rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr, 1832 socket_data->addrlen); 1833 if (rc != EOK) 1834 return tcp_release_and_return(packet, EINVAL); 1835 1836 /* Remember the outgoing FIN */ 1837 if (GET_TCP_HEADER_FINALIZE(header)) 1838 socket_data->fin_outgoing = socket_data->next_outgoing; 1839 1840 return EOK; 1841 } 1842 1843 int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data, 1844 packet_t *packet, size_t data_length) 1845 { 1846 int rc; 1847 1848 assert(socket); 1849 assert(socket_data); 1850 assert(socket->specific_data == socket_data); 1851 1852 rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length); 1853 if (rc != EOK) 1854 return rc; 1855 1856 rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing, 1857 data_length); 1858 if (rc != EOK) 1859 return tcp_release_and_return(packet, rc); 1860 1861 socket_data->next_outgoing += data_length; 1862 return EOK; 1863 } 1864 1865 packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t * 1866 socket_data) 1867 { 1868 packet_t *packet; 1869 packet_t *copy; 1870 packet_t *sending = NULL; 1871 packet_t *previous = NULL; 1872 size_t data_length; 1873 int rc; 1874 1875 assert(socket); 1876 assert(socket_data); 1877 assert(socket->specific_data == socket_data); 1878 1879 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1); 1880 while (packet) { 1881 pq_get_order(packet, NULL, &data_length); 1882 1883 /* 1884 * Send only if fits into the window, respecting the possible 1885 * overflow. 1886 */ 1887 if (!IS_IN_INTERVAL_OVERFLOW( 1888 (uint32_t) socket_data->last_outgoing, 1889 (uint32_t) (socket_data->last_outgoing + data_length), 1890 (uint32_t) (socket_data->expected + socket_data->treshold))) 1891 break; 1892 1893 copy = tcp_prepare_copy(socket, socket_data, packet, 1894 data_length, socket_data->last_outgoing + 1); 1895 if (!copy) 1896 return sending; 1897 1898 if (!sending) { 1899 sending = copy; 1900 } else { 1901 rc = pq_insert_after(previous, copy); 1902 if (rc != EOK) { 1903 pq_release_remote(tcp_globals.net_sess, 1904 packet_get_id(copy)); 1905 return sending; 1906 } 1907 } 1908 1909 previous = copy; 1910 packet = pq_next(packet); 1911 1912 /* Overflow occurred? */ 1913 if (!packet && 1914 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1915 printf("gpts overflow\n"); 1916 /* Continue from the beginning */ 1917 packet = socket_data->outgoing; 1918 } 1919 socket_data->last_outgoing += data_length; 1920 } 1921 1922 return sending; 1923 } 1924 1925 packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t * 1926 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1927 { 1928 tcp_header_t *header; 1929 uint32_t checksum; 1930 int rc; 1931 1932 assert(socket); 1933 assert(socket_data); 1934 assert(socket->specific_data == socket_data); 1935 1936 /* Adjust the pseudo header */ 1937 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, 1938 socket_data->headerlen, packet_get_data_length(packet)); 1939 if (rc != EOK) { 1940 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1941 return NULL; 1942 } 1943 1944 /* Get the header */ 1945 header = (tcp_header_t *) packet_get_data(packet); 1946 if (!header) { 1947 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1948 return NULL; 1949 } 1950 assert(ntohl(header->sequence_number) == sequence_number); 1951 1952 /* Adjust the header */ 1953 if (socket_data->next_incoming) { 1954 header->acknowledgement_number = 1955 htonl(socket_data->next_incoming); 1956 SET_TCP_HEADER_ACKNOWLEDGE(header, 1); 1957 } 1958 header->window = htons(socket_data->window); 1959 1960 /* Checksum */ 1961 header->checksum = 0; 1962 checksum = compute_checksum(0, socket_data->pseudo_header, 1963 socket_data->headerlen); 1964 checksum = compute_checksum(checksum, 1965 (uint8_t *) packet_get_data(packet), 1966 packet_get_data_length(packet)); 1967 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 1968 1969 /* Prepare the packet */ 1970 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 1971 if (rc != EOK) { 1972 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1973 return NULL; 1974 } 1975 1976 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1977 sequence_number, socket_data->state, socket_data->timeout, true); 1978 if (rc != EOK) { 1979 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 1980 return NULL; 1981 } 1982 1983 return packet; 1984 } 1985 1986 packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t * 1987 socket_data, packet_t *packet, size_t data_length, size_t sequence_number) 1988 { 1989 packet_t *copy; 1990 1991 assert(socket); 1992 assert(socket_data); 1993 assert(socket->specific_data == socket_data); 1994 1995 /* Make a copy of the packet */ 1996 copy = packet_get_copy(tcp_globals.net_sess, packet); 1997 if (!copy) 1998 return NULL; 1999 2000 return tcp_send_prepare_packet(socket, socket_data, copy, data_length, 2001 sequence_number); 2002 } 2003 2004 void tcp_send_packets(nic_device_id_t device_id, packet_t *packet) 2005 { 2006 packet_t *next; 2007 2008 while (packet) { 2009 next = pq_detach(packet); 2010 ip_send_msg(tcp_globals.ip_sess, device_id, packet, 2011 SERVICE_TCP, 0); 2012 packet = next; 2013 } 2014 } 2015 2016 void tcp_prepare_operation_header(socket_core_t *socket, 2017 tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize, 2018 int finalize) 2019 { 2020 assert(socket); 2021 assert(socket_data); 2022 assert(socket->specific_data == socket_data); 2023 assert(header); 2024 2025 bzero(header, sizeof(*header)); 2026 header->source_port = htons(socket->port); 2027 header->source_port = htons(socket_data->dest_port); 2028 SET_TCP_HEADER_LENGTH(header, 2029 TCP_COMPUTE_HEADER_LENGTH(sizeof(*header))); 2030 SET_TCP_HEADER_SYNCHRONIZE(header, synchronize); 2031 SET_TCP_HEADER_FINALIZE(header, finalize); 2032 } 2033 2034 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 2035 socket_core_t *socket, tcp_socket_data_t *socket_data, 2036 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, 2037 int globals_read_only) 2038 { 2039 tcp_timeout_t *operation_timeout; 2040 fid_t fibril; 2041 2042 assert(socket); 2043 assert(socket_data); 2044 assert(socket->specific_data == socket_data); 2045 2046 /* Prepare the timeout with key bundle structure */ 2047 operation_timeout = malloc(sizeof(*operation_timeout) + 2048 socket->key_length + 1); 2049 if (!operation_timeout) 2050 return ENOMEM; 2051 2052 bzero(operation_timeout, sizeof(*operation_timeout)); 2053 operation_timeout->globals_read_only = globals_read_only; 2054 operation_timeout->port = socket->port; 2055 operation_timeout->local_sockets = socket_data->local_sockets; 2056 operation_timeout->socket_id = socket->socket_id; 2057 operation_timeout->timeout = timeout; 2058 operation_timeout->sequence_number = sequence_number; 2059 operation_timeout->state = state; 2060 2061 /* Copy the key */ 2062 operation_timeout->key = ((uint8_t *) operation_timeout) + 2063 sizeof(*operation_timeout); 2064 operation_timeout->key_length = socket->key_length; 2065 memcpy(operation_timeout->key, socket->key, socket->key_length); 2066 operation_timeout->key[operation_timeout->key_length] = '\0'; 2067 2068 /* Prepare the timeouting thread */ 2069 fibril = fibril_create(timeout_function, operation_timeout); 2070 if (!fibril) { 2071 free(operation_timeout); 2072 return ENOMEM; 2073 } 2074 2075 // fibril_mutex_lock(&socket_data->operation.mutex); 2076 /* Start the timeout fibril */ 2077 fibril_add_ready(fibril); 2078 //socket_data->state = state; 2079 return EOK; 2080 } 2081 2082 int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 2083 int flags, size_t *addrlen) 2084 { 2085 socket_core_t *socket; 2086 tcp_socket_data_t *socket_data; 2087 int packet_id; 2088 packet_t *packet; 2089 size_t length; 2090 int rc; 2091 2092 assert(local_sockets); 2093 2094 /* Find the socket */ 2095 socket = socket_cores_find(local_sockets, socket_id); 2096 if (!socket) 2097 return ENOTSOCK; 2098 2099 /* Get the socket specific data */ 2100 if (!socket->specific_data) 2101 return NO_DATA; 2102 2103 socket_data = (tcp_socket_data_t *) socket->specific_data; 2104 2105 /* Check state */ 2106 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2107 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2108 return ENOTCONN; 2109 2110 /* Send the source address if desired */ 2111 if (addrlen) { 2112 rc = data_reply(socket_data->addr, socket_data->addrlen); 2113 if (rc != EOK) 2114 return rc; 2115 *addrlen = socket_data->addrlen; 2116 } 2117 2118 /* Get the next received packet */ 2119 packet_id = dyn_fifo_value(&socket->received); 2120 if (packet_id < 0) 2121 return NO_DATA; 2122 2123 rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id); 2124 if (rc != EOK) 2125 return rc; 2126 2127 /* Reply the packets */ 2128 rc = socket_reply_packets(packet, &length); 2129 if (rc != EOK) 2130 return rc; 2131 2132 /* Release the packet */ 2133 dyn_fifo_pop(&socket->received); 2134 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2135 2136 /* Return the total length */ 2137 return (int) length; 2138 } 2139 2140 int tcp_send_message(socket_cores_t *local_sockets, int socket_id, 2141 int fragments, size_t *data_fragment_size, int flags) 2142 { 2143 socket_core_t *socket; 2144 tcp_socket_data_t *socket_data; 2145 packet_dimension_t *packet_dimension; 2146 packet_t *packet; 2147 size_t total_length; 2148 tcp_header_t *header; 2149 int index; 2150 int result; 2151 int rc; 2152 2153 assert(local_sockets); 2154 assert(data_fragment_size); 2155 2156 /* Find the socket */ 2157 socket = socket_cores_find(local_sockets, socket_id); 2158 if (!socket) 2159 return ENOTSOCK; 2160 2161 /* Get the socket specific data */ 2162 if (!socket->specific_data) 2163 return NO_DATA; 2164 2165 socket_data = (tcp_socket_data_t *) socket->specific_data; 2166 2167 /* Check state */ 2168 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2169 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2170 return ENOTCONN; 2171 2172 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2173 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2174 if (rc != EOK) 2175 return rc; 2176 2177 *data_fragment_size = 2178 ((packet_dimension->content < socket_data->data_fragment_size) ? 2179 packet_dimension->content : socket_data->data_fragment_size); 2180 2181 for (index = 0; index < fragments; index++) { 2182 /* Read the data fragment */ 2183 result = tl_socket_read_packet_data(tcp_globals.net_sess, 2184 &packet, TCP_HEADER_SIZE, packet_dimension, 2185 socket_data->addr, socket_data->addrlen); 2186 if (result < 0) 2187 return result; 2188 2189 total_length = (size_t) result; 2190 2191 /* Prefix the TCP header */ 2192 header = PACKET_PREFIX(packet, tcp_header_t); 2193 if (!header) 2194 return tcp_release_and_return(packet, ENOMEM); 2195 2196 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 2197 rc = tcp_queue_packet(socket, socket_data, packet, total_length); 2198 if (rc != EOK) 2199 return rc; 2200 } 2201 2202 /* Flush packets */ 2203 packet = tcp_get_packets_to_send(socket, socket_data); 2204 fibril_rwlock_write_unlock(socket_data->local_lock); 2205 fibril_rwlock_read_unlock(&tcp_globals.lock); 2206 2207 if (packet) { 2208 /* Send the packet */ 2209 tcp_send_packets(socket_data->device_id, packet); 2210 } 2211 2212 return EOK; 2213 } 2214 2215 int 2216 tcp_close_message(socket_cores_t *local_sockets, int socket_id) 2217 { 2218 socket_core_t *socket; 2219 tcp_socket_data_t *socket_data; 2220 packet_t *packet; 2221 int rc; 2222 2223 /* Find the socket */ 2224 socket = socket_cores_find(local_sockets, socket_id); 2225 if (!socket) 2226 return ENOTSOCK; 2227 2228 /* Get the socket specific data */ 2229 socket_data = (tcp_socket_data_t *) socket->specific_data; 2230 assert(socket_data); 2231 2232 /* Check state */ 2233 switch (socket_data->state) { 2234 case TCP_SOCKET_ESTABLISHED: 2235 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 2236 break; 2237 2238 case TCP_SOCKET_CLOSE_WAIT: 2239 socket_data->state = TCP_SOCKET_LAST_ACK; 2240 break; 2241 2242 // case TCP_SOCKET_LISTEN: 2243 2244 default: 2245 /* Just destroy */ 2246 rc = socket_destroy(tcp_globals.net_sess, socket_id, 2247 local_sockets, &tcp_globals.sockets, 2248 tcp_free_socket_data); 2249 if (rc == EOK) { 2250 fibril_rwlock_write_unlock(socket_data->local_lock); 2251 fibril_rwlock_write_unlock(&tcp_globals.lock); 2252 } 2253 return rc; 2254 } 2255 2256 /* 2257 * Send FIN. 2258 * TODO should I wait to complete? 2259 */ 2260 2261 /* Create the notification packet */ 2262 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 2263 if (rc != EOK) 2264 return rc; 2265 2266 /* Send the packet */ 2267 rc = tcp_queue_packet(socket, socket_data, packet, 1); 2268 if (rc != EOK) 2269 return rc; 2270 2271 /* Flush packets */ 2272 packet = tcp_get_packets_to_send(socket, socket_data); 2273 fibril_rwlock_write_unlock(socket_data->local_lock); 2274 fibril_rwlock_write_unlock(&tcp_globals.lock); 2275 2276 if (packet) { 2277 /* Send the packet */ 2278 tcp_send_packets(socket_data->device_id, packet); 2279 } 2280 2281 return EOK; 2282 } 2283 2284 int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket, 2285 tcp_socket_data_t *socket_data, int synchronize, int finalize) 2286 { 2287 packet_dimension_t *packet_dimension; 2288 tcp_header_t *header; 2289 int rc; 2290 2291 assert(packet); 2292 2293 /* Get the device packet dimension */ 2294 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2295 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); 2296 if (rc != EOK) 2297 return rc; 2298 2299 /* Get a new packet */ 2300 *packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE, 2301 packet_dimension->addr_len, packet_dimension->prefix, 2302 packet_dimension->suffix); 2303 2304 if (!*packet) 2305 return ENOMEM; 2306 2307 /* Allocate space in the packet */ 2308 header = PACKET_SUFFIX(*packet, tcp_header_t); 2309 if (!header) 2310 tcp_release_and_return(*packet, ENOMEM); 2311 2312 tcp_prepare_operation_header(socket, socket_data, header, synchronize, 2313 finalize); 2314 2315 return EOK; 2316 } 2317 2318 int tcp_accept_message(socket_cores_t *local_sockets, int socket_id, 2319 int new_socket_id, size_t *data_fragment_size, size_t *addrlen) 2320 { 2321 socket_core_t *accepted; 2322 socket_core_t *socket; 2323 tcp_socket_data_t *socket_data; 2324 packet_dimension_t *packet_dimension; 2325 int rc; 2326 2327 assert(local_sockets); 2328 assert(data_fragment_size); 2329 assert(addrlen); 2330 2331 /* Find the socket */ 2332 socket = socket_cores_find(local_sockets, socket_id); 2333 if (!socket) 2334 return ENOTSOCK; 2335 2336 /* Get the socket specific data */ 2337 socket_data = (tcp_socket_data_t *) socket->specific_data; 2338 assert(socket_data); 2339 2340 /* Check state */ 2341 if (socket_data->state != TCP_SOCKET_LISTEN) 2342 return EINVAL; 2343 2344 do { 2345 socket_id = dyn_fifo_value(&socket->accepted); 2346 if (socket_id < 0) 2347 return ENOTSOCK; 2348 socket_id *= -1; 2349 2350 accepted = socket_cores_find(local_sockets, socket_id); 2351 if (!accepted) 2352 return ENOTSOCK; 2353 2354 /* Get the socket specific data */ 2355 socket_data = (tcp_socket_data_t *) accepted->specific_data; 2356 assert(socket_data); 2357 /* TODO can it be in another state? */ 2358 if (socket_data->state == TCP_SOCKET_ESTABLISHED) { 2359 rc = data_reply(socket_data->addr, 2360 socket_data->addrlen); 2361 if (rc != EOK) 2362 return rc; 2363 rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess, 2364 &tcp_globals.dimensions, socket_data->device_id, 2365 &packet_dimension); 2366 if (rc != EOK) 2367 return rc; 2368 *addrlen = socket_data->addrlen; 2369 2370 *data_fragment_size = 2371 ((packet_dimension->content < 2372 socket_data->data_fragment_size) ? 2373 packet_dimension->content : 2374 socket_data->data_fragment_size); 2375 2376 if (new_socket_id > 0) { 2377 rc = socket_cores_update(local_sockets, 2378 accepted->socket_id, new_socket_id); 2379 if (rc != EOK) 2380 return rc; 2381 accepted->socket_id = new_socket_id; 2382 } 2383 } 2384 dyn_fifo_pop(&socket->accepted); 2385 } while (socket_data->state != TCP_SOCKET_ESTABLISHED); 2386 2387 printf("ret accept %d\n", accepted->socket_id); 2388 return accepted->socket_id; 2389 } 2390 2391 void tcp_free_socket_data(socket_core_t *socket) 2392 { 2393 tcp_socket_data_t *socket_data; 2394 2395 assert(socket); 2396 2397 printf("destroy_socket %d\n", socket->socket_id); 2398 2399 /* Get the socket specific data */ 2400 socket_data = (tcp_socket_data_t *) socket->specific_data; 2401 assert(socket_data); 2402 2403 /* Free the pseudo header */ 2404 if (socket_data->pseudo_header) { 2405 if (socket_data->headerlen) { 2406 printf("d pseudo\n"); 2407 free(socket_data->pseudo_header); 2408 socket_data->headerlen = 0; 2409 } 2410 socket_data->pseudo_header = NULL; 2411 } 2412 2413 socket_data->headerlen = 0; 2414 2415 /* Free the address */ 2416 if (socket_data->addr) { 2417 if (socket_data->addrlen) { 2418 printf("d addr\n"); 2419 free(socket_data->addr); 2420 socket_data->addrlen = 0; 2421 } 2422 socket_data->addr = NULL; 2423 } 2424 socket_data->addrlen = 0; 2425 } 2426 2427 /** Releases the packet and returns the result. 2428 * 2429 * @param[in] packet The packet queue to be released. 2430 * @param[in] result The result to be returned. 2431 * @return The result parameter. 2432 */ 2433 int tcp_release_and_return(packet_t *packet, int result) 2434 { 2435 pq_release_remote(tcp_globals.net_sess, packet_get_id(packet)); 2436 return result; 2437 } 2438 2439 /** Process IPC messages from the IP module 2440 * 2441 * @param[in] iid Message identifier. 2442 * @param[in,out] icall Message parameters. 2443 * @param[in] arg Local argument. 2444 * 2445 */ 2446 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg) 2447 { 2448 packet_t *packet; 2449 int rc; 2450 234 2451 while (true) { 235 2452 switch (IPC_GET_IMETHOD(*icall)) { 236 2453 case NET_TL_RECEIVED: 237 log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED"); 238 rc = packet_translate_remote(net_sess, &packet, 2454 rc = packet_translate_remote(tcp_globals.net_sess, &packet, 239 2455 IPC_GET_PACKET(*icall)); 240 if (rc != EOK) { 241 log_msg(LVL_DEBUG, "Error %d translating packet.", rc); 242 async_answer_0(iid, (sysarg_t)rc); 243 break; 244 } 245 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 246 IPC_GET_ERROR(*icall)); 247 async_answer_0(iid, (sysarg_t)rc); 2456 if (rc == EOK) 2457 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 2458 SERVICE_TCP, IPC_GET_ERROR(*icall)); 2459 2460 async_answer_0(iid, (sysarg_t) rc); 248 2461 break; 249 2462 default: 250 log_msg(LVL_DEBUG, "method = %u", 251 (unsigned)IPC_GET_IMETHOD(*icall)); 252 async_answer_0(iid, ENOTSUP); 253 break; 254 } 255 2463 async_answer_0(iid, (sysarg_t) ENOTSUP); 2464 } 2465 256 2466 iid = async_get_call(icall); 257 2467 } 258 2468 } 259 2469 260 /** Transmit PDU over network layer. */ 261 void tcp_transmit_pdu(tcp_pdu_t *pdu) 262 { 263 struct sockaddr_in dest; 264 nic_device_id_t dev_id; 265 void *phdr; 266 size_t phdr_len; 267 packet_dimension_t *pkt_dim; 268 int rc; 269 packet_t *packet; 270 void *pkt_data; 271 size_t pdu_size; 272 273 dest.sin_family = AF_INET; 274 dest.sin_port = 0; /* not needed */ 275 dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4); 276 277 /* Find route. Obtained pseudo-header is not used. */ 278 rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest, 279 sizeof(dest), &dev_id, &phdr, &phdr_len); 2470 /** Initialize the TCP module. 2471 * 2472 * @param[in] sess Network module session. 2473 * 2474 * @return EOK on success. 2475 * @return ENOMEM if there is not enough memory left. 2476 * 2477 */ 2478 int tl_initialize(async_sess_t *sess) 2479 { 2480 fibril_rwlock_initialize(&tcp_globals.lock); 2481 fibril_rwlock_write_lock(&tcp_globals.lock); 2482 2483 tcp_globals.net_sess = sess; 2484 2485 tcp_globals.icmp_sess = icmp_connect_module(); 2486 tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, 2487 SERVICE_TCP, tcp_receiver); 2488 if (tcp_globals.ip_sess == NULL) { 2489 fibril_rwlock_write_unlock(&tcp_globals.lock); 2490 return ENOENT; 2491 } 2492 2493 int rc = socket_ports_initialize(&tcp_globals.sockets); 2494 if (rc != EOK) 2495 goto out; 2496 2497 rc = packet_dimensions_initialize(&tcp_globals.dimensions); 280 2498 if (rc != EOK) { 281 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route."); 282 return; 283 } 284 285 rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim); 286 if (rc != EOK) { 287 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension."); 288 return; 289 } 290 291 pdu_size = pdu->header_size + pdu->text_size; 292 293 packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len, 294 pkt_dim->prefix, pkt_dim->suffix); 295 if (!packet) { 296 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet."); 297 return; 298 } 299 300 pkt_data = packet_suffix(packet, pdu_size); 301 if (!pkt_data) { 302 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr."); 303 pq_release_remote(net_sess, packet_get_id(packet)); 304 return; 305 } 306 307 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 308 if (rc != EOK) { 309 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part."); 310 pq_release_remote(net_sess, packet_get_id(packet)); 311 return; 312 } 313 314 rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest)); 315 if (rc != EOK) { 316 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address."); 317 pq_release_remote(net_sess, packet_get_id(packet)); 318 return; 319 } 320 321 /* Copy PDU data to packet */ 322 memcpy(pkt_data, pdu->header, pdu->header_size); 323 memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text, 324 pdu->text_size); 325 326 /* Transmit packet. XXX Transfers packet ownership to IP? */ 327 ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0); 328 } 329 330 /** Process received PDU. */ 331 static void tcp_received_pdu(tcp_pdu_t *pdu) 332 { 333 tcp_segment_t *dseg; 334 tcp_sockpair_t rident; 335 336 log_msg(LVL_DEBUG, "tcp_received_pdu()"); 337 338 if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) { 339 log_msg(LVL_WARN, "Not enough memory. PDU dropped."); 340 return; 341 } 342 343 /* Insert decoded segment into rqueue */ 344 tcp_rqueue_insert_seg(&rident, dseg); 345 } 346 347 /* Called from libnet */ 348 void tl_connection(void) 349 { 350 log_msg(LVL_DEBUG, "tl_connection()"); 351 } 352 353 /* Called from libnet */ 354 int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 355 size_t *answer_count) 356 { 357 async_sess_t *callback; 358 359 log_msg(LVL_DEBUG, "tl_message()"); 360 361 *answer_count = 0; 362 callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call); 363 if (callback) 364 return tcp_sock_connection(callback, callid, *call); 365 366 return ENOTSUP; 367 } 368 369 /* Called from libnet */ 370 int tl_initialize(async_sess_t *sess) 371 { 372 int rc; 373 374 net_sess = sess; 375 icmp_sess = icmp_connect_module(); 376 377 log_msg(LVL_DEBUG, "tl_initialize()"); 378 379 tcp_sock_init(); 380 381 ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, 382 tcp_receiver); 383 if (ip_sess == NULL) 384 return ENOENT; 385 386 rc = packet_dimensions_initialize(&pkt_dims); 387 if (rc != EOK) 388 return rc; 389 390 return EOK; 391 } 392 393 int main(int argc, char **argv) 394 { 395 int rc; 396 397 printf(NAME ": TCP (Transmission Control Protocol) network module\n"); 398 399 rc = log_init(NAME, LVL_ERROR); 400 if (rc != EOK) { 401 printf(NAME ": Failed to initialize log.\n"); 402 return 1; 403 } 404 405 // printf(NAME ": Accepting connections\n"); 406 // task_retval(0); 407 408 tcp_rqueue_init(); 409 tcp_rqueue_thread_start(); 410 411 tcp_ncsim_init(); 412 tcp_ncsim_thread_start(); 413 414 if (0) tcp_test(); 415 /* 416 async_manager(); 417 */ 418 tl_module_start(SERVICE_TCP); 419 420 /* Not reached */ 421 return 0; 422 } 423 424 /** 425 * @} 2499 socket_ports_destroy(&tcp_globals.sockets, free); 2500 goto out; 2501 } 2502 2503 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1; 2504 2505 out: 2506 fibril_rwlock_write_unlock(&tcp_globals.lock); 2507 return rc; 2508 } 2509 2510 int main(int argc, char *argv[]) 2511 { 2512 return tl_module_start(SERVICE_TCP); 2513 } 2514 2515 /** @} 426 2516 */
Note:
See TracChangeset
for help on using the changeset viewer.