00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <assert.h>
00039 #include <async.h>
00040 #include <fibril_synch.h>
00041 #include <malloc.h>
00042
00043 #include <stdio.h>
00044 #include <errno.h>
00045
00046 #include <ipc/services.h>
00047 #include <ipc/net.h>
00048 #include <ipc/tl.h>
00049 #include <ipc/socket.h>
00050
00051 #include <net/socket_codes.h>
00052 #include <net/ip_protocols.h>
00053 #include <net/in.h>
00054 #include <net/in6.h>
00055 #include <net/inet.h>
00056 #include <net/modules.h>
00057
00058 #include <adt/dynamic_fifo.h>
00059 #include <packet_client.h>
00060 #include <packet_remote.h>
00061 #include <net_checksum.h>
00062 #include <ip_client.h>
00063 #include <ip_interface.h>
00064 #include <icmp_client.h>
00065 #include <icmp_remote.h>
00066 #include <net_interface.h>
00067 #include <socket_core.h>
00068 #include <tl_common.h>
00069 #include <tl_remote.h>
00070 #include <tl_skel.h>
00071
00072 #include "tcp.h"
00073 #include "tcp_header.h"
00074
00076 #define NAME "tcp"
00077
00079 #define NET_DEFAULT_TCP_WINDOW 10240
00080
00082 #define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
00083
00085 #define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L
00086
00088 #define TCP_INITIAL_SEQUENCE_NUMBER 2999
00089
00091 #define MAX_TCP_FRAGMENT_SIZE 65535
00092
00094 #define TCP_FREE_PORTS_START 1025
00095
00097 #define TCP_FREE_PORTS_END 65535
00098
00100 #define TCP_SYN_SENT_TIMEOUT 1000000L
00101
00103 #define TCP_MAX_TIMEOUTS 8
00104
00106 #define TCP_FAST_RETRANSMIT_COUNT 3
00107
00117 #define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \
00118 ((((lower) < (value)) && (((value) <= (higher_equal)) || \
00119 ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && \
00120 ((higher_equal) < (lower))))
00121
00125 typedef struct tcp_timeout tcp_timeout_t;
00126
00131 struct tcp_timeout {
00133 int globals_read_only;
00134
00136 int port;
00137
00139 socket_cores_t *local_sockets;
00140
00142 int socket_id;
00143
00145 tcp_socket_state_t state;
00146
00148 int sequence_number;
00149
00151 suseconds_t timeout;
00152
00154 uint8_t *key;
00155
00157 size_t key_length;
00158 };
00159
00160 static int tcp_release_and_return(packet_t *, int);
00161 static void tcp_prepare_operation_header(socket_core_t *, tcp_socket_data_t *,
00162 tcp_header_t *, int synchronize, int);
00163 static int tcp_prepare_timeout(int (*)(void *), socket_core_t *,
00164 tcp_socket_data_t *, size_t, tcp_socket_state_t, suseconds_t, int);
00165 static void tcp_free_socket_data(socket_core_t *);
00166
00167 static int tcp_timeout(void *);
00168
00169 static int tcp_release_after_timeout(void *);
00170
00171 static int tcp_process_packet(device_id_t, packet_t *, services_t);
00172 static int tcp_connect_core(socket_core_t *, socket_cores_t *,
00173 struct sockaddr *, socklen_t);
00174 static int tcp_queue_prepare_packet(socket_core_t *, tcp_socket_data_t *,
00175 packet_t *, size_t);
00176 static int tcp_queue_packet(socket_core_t *, tcp_socket_data_t *, packet_t *,
00177 size_t);
00178 static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *);
00179 static void tcp_send_packets(device_id_t, packet_t *);
00180
00181 static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *,
00182 tcp_header_t *);
00183 static packet_t *tcp_send_prepare_packet(socket_core_t *, tcp_socket_data_t *,
00184 packet_t *, size_t, size_t);
00185 static packet_t *tcp_prepare_copy(socket_core_t *, tcp_socket_data_t *,
00186 packet_t *, size_t, size_t);
00187 void tcp_retransmit_packet(socket_core_t *, tcp_socket_data_t *,
00188 size_t);
00189 static int tcp_create_notification_packet(packet_t **, socket_core_t *,
00190 tcp_socket_data_t *, int, int);
00191 static void tcp_refresh_socket_data(tcp_socket_data_t *);
00192
00193 static void tcp_initialize_socket_data(tcp_socket_data_t *);
00194
00195 static int tcp_process_listen(socket_core_t *, tcp_socket_data_t *,
00196 tcp_header_t *, packet_t *, struct sockaddr *, struct sockaddr *, size_t);
00197 static int tcp_process_syn_sent(socket_core_t *, tcp_socket_data_t *,
00198 tcp_header_t *, packet_t *);
00199 static int tcp_process_syn_received(socket_core_t *, tcp_socket_data_t *,
00200 tcp_header_t *, packet_t *);
00201 static int tcp_process_established(socket_core_t *, tcp_socket_data_t *,
00202 tcp_header_t *, packet_t *, int, size_t);
00203 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
00204 packet_t *, int, size_t);
00205 static void tcp_queue_received_end_of_data(socket_core_t *socket);
00206
00207 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
00208 static int tcp_process_client_messages(ipc_callid_t, ipc_call_t);
00209
00210 static int tcp_listen_message(socket_cores_t *, int, int);
00211 static int tcp_connect_message(socket_cores_t *, int, struct sockaddr *,
00212 socklen_t);
00213 static int tcp_recvfrom_message(socket_cores_t *, int, int, size_t *);
00214 static int tcp_send_message(socket_cores_t *, int, int, size_t *, int);
00215 static int tcp_accept_message(socket_cores_t *, int, int, size_t *, size_t *);
00216 static int tcp_close_message(socket_cores_t *, int);
00217
00219 tcp_globals_t tcp_globals;
00220
00221 int tcp_received_msg(device_id_t device_id, packet_t *packet,
00222 services_t receiver, services_t error)
00223 {
00224 int rc;
00225
00226 if (receiver != SERVICE_TCP)
00227 return EREFUSED;
00228
00229 fibril_rwlock_write_lock(&tcp_globals.lock);
00230 rc = tcp_process_packet(device_id, packet, error);
00231 if (rc != EOK)
00232 fibril_rwlock_write_unlock(&tcp_globals.lock);
00233
00234 printf("receive %d \n", rc);
00235
00236 return rc;
00237 }
00238
00239 int tcp_process_packet(device_id_t device_id, packet_t *packet, services_t error)
00240 {
00241 size_t length;
00242 size_t offset;
00243 int result;
00244 tcp_header_t *header;
00245 socket_core_t *socket;
00246 tcp_socket_data_t *socket_data;
00247 packet_t *next_packet;
00248 size_t total_length;
00249 uint32_t checksum;
00250 int fragments;
00251 icmp_type_t type;
00252 icmp_code_t code;
00253 struct sockaddr *src;
00254 struct sockaddr *dest;
00255 size_t addrlen;
00256 int rc;
00257
00258 switch (error) {
00259 case SERVICE_NONE:
00260 break;
00261 case SERVICE_ICMP:
00262
00263 result = icmp_client_process_packet(packet, &type, &code, NULL,
00264 NULL);
00265 if (result < 0)
00266 return tcp_release_and_return(packet, result);
00267
00268 length = (size_t) result;
00269 rc = packet_trim(packet, length, 0);
00270 if (rc != EOK)
00271 return tcp_release_and_return(packet, rc);
00272 break;
00273 default:
00274 return tcp_release_and_return(packet, ENOTSUP);
00275 }
00276
00277
00278 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
00279 if (result < 0)
00280 return tcp_release_and_return(packet, result);
00281
00282 offset = (size_t) result;
00283
00284 length = packet_get_data_length(packet);
00285 if (length <= 0)
00286 return tcp_release_and_return(packet, EINVAL);
00287
00288 if (length < TCP_HEADER_SIZE + offset)
00289 return tcp_release_and_return(packet, NO_DATA);
00290
00291
00292 rc = packet_trim(packet, offset, 0);
00293 if (rc != EOK)
00294 return tcp_release_and_return(packet, rc);
00295
00296
00297 header = (tcp_header_t *) packet_get_data(packet);
00298 if (!header)
00299 return tcp_release_and_return(packet, NO_DATA);
00300
00301 #if 0
00302 printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
00303 ntohs(header->destination_port));
00304 #endif
00305 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
00306 if (result <= 0)
00307 return tcp_release_and_return(packet, result);
00308
00309 addrlen = (size_t) result;
00310
00311 rc = tl_set_address_port(src, addrlen, ntohs(header->source_port));
00312 if (rc != EOK)
00313 return tcp_release_and_return(packet, rc);
00314
00315
00316 socket = socket_port_find(&tcp_globals.sockets,
00317 ntohs(header->destination_port), (uint8_t *) src, addrlen);
00318 if (!socket) {
00319
00320 socket = socket_port_find(&tcp_globals.sockets,
00321 ntohs(header->destination_port),
00322 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
00323 }
00324
00325 if (!socket) {
00326 if (tl_prepare_icmp_packet(tcp_globals.net_phone,
00327 tcp_globals.icmp_phone, packet, error) == EOK) {
00328 icmp_destination_unreachable_msg(tcp_globals.icmp_phone,
00329 ICMP_PORT_UNREACH, 0, packet);
00330 }
00331 return EADDRNOTAVAIL;
00332 }
00333
00334 printf("socket id %d\n", socket->socket_id);
00335 socket_data = (tcp_socket_data_t *) socket->specific_data;
00336 assert(socket_data);
00337
00338
00339 socket_data->timeout_count = 0;
00340
00341
00342 next_packet = packet;
00343 fragments = 0;
00344 checksum = 0;
00345 total_length = 0;
00346 do {
00347 fragments++;
00348 length = packet_get_data_length(next_packet);
00349 if (length <= 0)
00350 return tcp_release_and_return(packet, NO_DATA);
00351
00352 total_length += length;
00353
00354
00355 if (!error) {
00356 checksum = compute_checksum(checksum,
00357 packet_get_data(packet),
00358 packet_get_data_length(packet));
00359 }
00360
00361 } while ((next_packet = pq_next(next_packet)));
00362
00363 fibril_rwlock_write_lock(socket_data->local_lock);
00364
00365 if (error)
00366 goto has_error_service;
00367
00368 if (socket_data->state == TCP_SOCKET_LISTEN) {
00369 if (socket_data->pseudo_header) {
00370 free(socket_data->pseudo_header);
00371 socket_data->pseudo_header = NULL;
00372 socket_data->headerlen = 0;
00373 }
00374
00375 rc = ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen,
00376 dest, addrlen, total_length, &socket_data->pseudo_header,
00377 &socket_data->headerlen);
00378 if (rc != EOK) {
00379 fibril_rwlock_write_unlock(socket_data->local_lock);
00380 return tcp_release_and_return(packet, rc);
00381 }
00382 } else {
00383 rc = ip_client_set_pseudo_header_data_length(
00384 socket_data->pseudo_header, socket_data->headerlen,
00385 total_length);
00386 if (rc != EOK) {
00387 fibril_rwlock_write_unlock(socket_data->local_lock);
00388 return tcp_release_and_return(packet, rc);
00389 }
00390 }
00391
00392 checksum = compute_checksum(checksum, socket_data->pseudo_header,
00393 socket_data->headerlen);
00394 if (flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO) {
00395 printf("checksum err %x -> %x\n", header->checksum,
00396 flip_checksum(compact_checksum(checksum)));
00397 fibril_rwlock_write_unlock(socket_data->local_lock);
00398
00399 rc = tl_prepare_icmp_packet(tcp_globals.net_phone,
00400 tcp_globals.icmp_phone, packet, error);
00401 if (rc == EOK) {
00402
00403 icmp_parameter_problem_msg(tcp_globals.icmp_phone,
00404 ICMP_PARAM_POINTER,
00405 ((size_t) ((void *) &header->checksum)) -
00406 ((size_t) ((void *) header)), packet);
00407 }
00408
00409 return EINVAL;
00410 }
00411
00412 has_error_service:
00413 fibril_rwlock_write_unlock(&tcp_globals.lock);
00414
00415
00416 switch (socket_data->state) {
00417 case TCP_SOCKET_LISTEN:
00418 rc = tcp_process_listen(socket, socket_data, header, packet,
00419 src, dest, addrlen);
00420 break;
00421 case TCP_SOCKET_SYN_RECEIVED:
00422 rc = tcp_process_syn_received(socket, socket_data, header,
00423 packet);
00424 break;
00425 case TCP_SOCKET_SYN_SENT:
00426 rc = tcp_process_syn_sent(socket, socket_data, header, packet);
00427 break;
00428 case TCP_SOCKET_FIN_WAIT_1:
00429
00430 case TCP_SOCKET_FIN_WAIT_2:
00431
00432 case TCP_SOCKET_LAST_ACK:
00433
00434 case TCP_SOCKET_CLOSING:
00435
00436 case TCP_SOCKET_ESTABLISHED:
00437 rc = tcp_process_established(socket, socket_data, header,
00438 packet, fragments, total_length);
00439 break;
00440 default:
00441 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
00442 }
00443
00444 if (rc != EOK) {
00445 fibril_rwlock_write_unlock(socket_data->local_lock);
00446 printf("process %d\n", rc);
00447 }
00448
00449 return EOK;
00450 }
00451
00452 int tcp_process_established(socket_core_t *socket, tcp_socket_data_t *
00453 socket_data, tcp_header_t *header, packet_t *packet, int fragments,
00454 size_t total_length)
00455 {
00456 packet_t *next_packet;
00457 packet_t *tmp_packet;
00458 uint32_t old_incoming;
00459 size_t order;
00460 uint32_t sequence_number;
00461 size_t length;
00462 size_t offset;
00463 uint32_t new_sequence_number;
00464 bool forced_ack;
00465 int rc;
00466
00467 assert(socket);
00468 assert(socket_data);
00469 assert(socket->specific_data == socket_data);
00470 assert(header);
00471 assert(packet);
00472
00473 forced_ack = false;
00474
00475 new_sequence_number = ntohl(header->sequence_number);
00476 old_incoming = socket_data->next_incoming;
00477
00478 if (GET_TCP_HEADER_FINALIZE(header)) {
00479 socket_data->fin_incoming = new_sequence_number +
00480 total_length - TCP_HEADER_LENGTH(header);
00481 }
00482
00483
00484 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
00485 socket_data->next_incoming, new_sequence_number + total_length)) {
00486
00487
00488 if (socket_data->next_incoming < new_sequence_number) {
00489 offset = new_sequence_number -
00490 socket_data->next_incoming;
00491 } else {
00492 offset = socket_data->next_incoming -
00493 new_sequence_number;
00494 }
00495
00496 new_sequence_number += offset;
00497 total_length -= offset;
00498 length = packet_get_data_length(packet);
00499
00500
00501 while (length <= offset) {
00502
00503 next_packet = pq_next(packet);
00504 pq_release_remote(tcp_globals.net_phone,
00505 packet_get_id(packet));
00506 packet = next_packet;
00507 offset -= length;
00508 length = packet_get_data_length(packet);
00509 }
00510
00511 if (offset > 0) {
00512 rc = packet_trim(packet, offset, 0);
00513 if (rc != EOK)
00514 return tcp_release_and_return(packet, rc);
00515 }
00516
00517 assert(new_sequence_number == socket_data->next_incoming);
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if (new_sequence_number == socket_data->next_incoming) {
00572 printf("expected\n");
00573
00574 tcp_process_acknowledgement(socket, socket_data, header);
00575
00576
00577 total_length -= TCP_HEADER_LENGTH(header);
00578 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0);
00579 if (rc != EOK)
00580 return tcp_release_and_return(packet, rc);
00581
00582 if (total_length) {
00583 rc = tcp_queue_received_packet(socket, socket_data,
00584 packet, fragments, total_length);
00585 if (rc != EOK)
00586 return rc;
00587 } else {
00588 total_length = 1;
00589 }
00590
00591 socket_data->next_incoming = old_incoming + total_length;
00592 packet = socket_data->incoming;
00593 while (packet) {
00594 rc = pq_get_order(socket_data->incoming, &order, NULL);
00595 if (rc != EOK) {
00596
00597 next_packet = pq_detach(packet);
00598 if (packet == socket_data->incoming)
00599 socket_data->incoming = next_packet;
00600 pq_release_remote(tcp_globals.net_phone,
00601 packet_get_id(packet));
00602 packet = next_packet;
00603 continue;
00604 }
00605
00606 sequence_number = (uint32_t) order;
00607 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
00608 old_incoming, socket_data->next_incoming)) {
00609
00610 packet = pq_next(packet);
00611
00612 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming,
00613 sequence_number, socket_data->next_incoming)) {
00614
00615 next_packet = pq_detach(packet);
00616 if (packet == socket_data->incoming)
00617 socket_data->incoming = next_packet;
00618
00619 length = packet_get_data_length(packet);
00620 new_sequence_number = sequence_number + length;
00621 if (length <= 0) {
00622
00623 pq_release_remote(tcp_globals.net_phone,
00624 packet_get_id(packet));
00625 packet = next_packet;
00626 continue;
00627 }
00628
00629 if (sequence_number ==
00630 socket_data->next_incoming) {
00631
00632 rc = tcp_queue_received_packet(socket,
00633 socket_data, packet, 1,
00634 packet_get_data_length(packet));
00635 if (rc != EOK)
00636 return rc;
00637 socket_data->next_incoming =
00638 new_sequence_number;
00639 packet = next_packet;
00640 continue;
00641
00642 }
00643 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
00644 socket_data->next_incoming, new_sequence_number)) {
00645 if (socket_data->next_incoming <
00646 new_sequence_number) {
00647 length = new_sequence_number -
00648 socket_data->next_incoming;
00649 } else {
00650 length =
00651 socket_data->next_incoming -
00652 new_sequence_number;
00653 }
00654 rc = packet_trim(packet,length, 0);
00655 if (rc == EOK) {
00656
00657 rc = tcp_queue_received_packet(
00658 socket, socket_data, packet,
00659 1, packet_get_data_length(
00660 packet));
00661 if (rc != EOK)
00662 return rc;
00663 socket_data->next_incoming =
00664 new_sequence_number;
00665 packet = next_packet;
00666 continue;
00667 }
00668 }
00669
00670 pq_release_remote(tcp_globals.net_phone,
00671 packet_get_id(packet));
00672 packet = next_packet;
00673 continue;
00674 } else {
00675 break;
00676 }
00677 }
00678 } else if (IS_IN_INTERVAL(socket_data->next_incoming,
00679 new_sequence_number,
00680 socket_data->next_incoming + socket_data->window)) {
00681 printf("in window\n");
00682
00683 tcp_process_acknowledgement(socket, socket_data, header);
00684
00685
00686 total_length -= TCP_HEADER_LENGTH(header);
00687 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0);
00688 if (rc != EOK)
00689 return tcp_release_and_return(packet, rc);
00690
00691 next_packet = pq_detach(packet);
00692 length = packet_get_data_length(packet);
00693 rc = pq_add(&socket_data->incoming, packet, new_sequence_number,
00694 length);
00695 if (rc != EOK) {
00696
00697 pq_release_remote(tcp_globals.net_phone,
00698 packet_get_id(packet));
00699 pq_release_remote(tcp_globals.net_phone,
00700 packet_get_id(next_packet));
00701 } else {
00702 while (next_packet) {
00703 new_sequence_number += length;
00704 tmp_packet = pq_detach(next_packet);
00705 length = packet_get_data_length(next_packet);
00706
00707 rc = pq_set_order(next_packet,
00708 new_sequence_number, length);
00709 if (rc != EOK) {
00710 pq_release_remote(tcp_globals.net_phone,
00711 packet_get_id(next_packet));
00712 }
00713 rc = pq_insert_after(packet, next_packet);
00714 if (rc != EOK) {
00715 pq_release_remote(tcp_globals.net_phone,
00716 packet_get_id(next_packet));
00717 }
00718 next_packet = tmp_packet;
00719 }
00720 }
00721 } else {
00722 printf("unexpected\n");
00723
00724 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
00725 forced_ack = true;
00726 }
00727
00728
00729 if (socket_data->next_incoming == socket_data->fin_incoming) {
00730
00731 socket_data->next_incoming += 1;
00732
00733
00734 switch (socket_data->state) {
00735 case TCP_SOCKET_FIN_WAIT_1:
00736 case TCP_SOCKET_FIN_WAIT_2:
00737 case TCP_SOCKET_CLOSING:
00738 socket_data->state = TCP_SOCKET_CLOSING;
00739 break;
00740 case TCP_SOCKET_ESTABLISHED:
00741
00742 tcp_queue_received_end_of_data(socket);
00743 socket_data->state = TCP_SOCKET_CLOSE_WAIT;
00744 break;
00745 default:
00746 socket_data->state = TCP_SOCKET_CLOSE_WAIT;
00747 break;
00748 }
00749 }
00750
00751 packet = tcp_get_packets_to_send(socket, socket_data);
00752 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) {
00753
00754 rc = tcp_create_notification_packet(&packet, socket,
00755 socket_data, 0, 0);
00756 if (rc != EOK)
00757 return rc;
00758 rc = tcp_queue_prepare_packet(socket, socket_data, packet, 1);
00759 if (rc != EOK)
00760 return rc;
00761 packet = tcp_send_prepare_packet(socket, socket_data, packet, 1,
00762 socket_data->last_outgoing + 1);
00763 }
00764
00765 fibril_rwlock_write_unlock(socket_data->local_lock);
00766
00767
00768 tcp_send_packets(socket_data->device_id, packet);
00769
00770 return EOK;
00771 }
00772
00773 int tcp_queue_received_packet(socket_core_t *socket,
00774 tcp_socket_data_t *socket_data, packet_t *packet, int fragments,
00775 size_t total_length)
00776 {
00777 packet_dimension_t *packet_dimension;
00778 int rc;
00779
00780 assert(socket);
00781 assert(socket_data);
00782 assert(socket->specific_data == socket_data);
00783 assert(packet);
00784 assert(fragments >= 1);
00785 assert(socket_data->window > total_length);
00786
00787
00788 rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
00789 SOCKET_MAX_RECEIVED_SIZE);
00790 if (rc != EOK)
00791 return tcp_release_and_return(packet, rc);
00792 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
00793 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
00794 if (rc != EOK)
00795 return tcp_release_and_return(packet, rc);
00796
00797
00798 socket_data->window -= total_length;
00799
00800
00801 async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
00802 (sysarg_t) socket->socket_id,
00803 ((packet_dimension->content < socket_data->data_fragment_size) ?
00804 packet_dimension->content : socket_data->data_fragment_size), 0, 0,
00805 (sysarg_t) fragments);
00806
00807 return EOK;
00808 }
00809
00817 static void tcp_queue_received_end_of_data(socket_core_t *socket)
00818 {
00819 assert(socket != NULL);
00820
00821
00822 async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
00823 (sysarg_t) socket->socket_id,
00824 0, 0, 0,
00825 (sysarg_t) 0 );
00826 }
00827
00828 int tcp_process_syn_sent(socket_core_t *socket, tcp_socket_data_t *
00829 socket_data, tcp_header_t *header, packet_t *packet)
00830 {
00831 packet_t *next_packet;
00832 int rc;
00833
00834 assert(socket);
00835 assert(socket_data);
00836 assert(socket->specific_data == socket_data);
00837 assert(header);
00838 assert(packet);
00839
00840 if (!GET_TCP_HEADER_SYNCHRONIZE(header))
00841 return tcp_release_and_return(packet, EINVAL);
00842
00843
00844 tcp_process_acknowledgement(socket, socket_data, header);
00845
00846 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
00847
00848
00849 next_packet = pq_detach(packet);
00850 if (next_packet) {
00851 pq_release_remote(tcp_globals.net_phone,
00852 packet_get_id(next_packet));
00853 }
00854
00855
00856 if (packet_get_data_length(packet) > sizeof(*header)) {
00857 rc = packet_trim(packet, 0,
00858 packet_get_data_length(packet) - sizeof(*header));
00859 if (rc != EOK)
00860 return tcp_release_and_return(packet, rc);
00861 }
00862
00863 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
00864 fibril_mutex_lock(&socket_data->operation.mutex);
00865 socket_data->operation.result = tcp_queue_packet(socket, socket_data,
00866 packet, 1);
00867
00868 if (socket_data->operation.result == EOK) {
00869 socket_data->state = TCP_SOCKET_ESTABLISHED;
00870 packet = tcp_get_packets_to_send(socket, socket_data);
00871 if (packet) {
00872 fibril_rwlock_write_unlock( socket_data->local_lock);
00873
00874 tcp_send_packets(socket_data->device_id, packet);
00875
00876 fibril_condvar_signal( &socket_data->operation.condvar);
00877 fibril_mutex_unlock( &socket_data->operation.mutex);
00878 return EOK;
00879 }
00880 }
00881
00882 fibril_mutex_unlock(&socket_data->operation.mutex);
00883 return tcp_release_and_return(packet, EINVAL);
00884 }
00885
00886 int tcp_process_listen(socket_core_t *listening_socket,
00887 tcp_socket_data_t *listening_socket_data, tcp_header_t *header,
00888 packet_t *packet, struct sockaddr *src, struct sockaddr *dest,
00889 size_t addrlen)
00890 {
00891 packet_t *next_packet;
00892 socket_core_t *socket;
00893 tcp_socket_data_t *socket_data;
00894 int socket_id;
00895 int listening_socket_id = listening_socket->socket_id;
00896 int listening_port = listening_socket->port;
00897 int rc;
00898
00899 assert(listening_socket);
00900 assert(listening_socket_data);
00901 assert(listening_socket->specific_data == listening_socket_data);
00902 assert(header);
00903 assert(packet);
00904
00905 if (!GET_TCP_HEADER_SYNCHRONIZE(header))
00906 return tcp_release_and_return(packet, EINVAL);
00907
00908 socket_data = (tcp_socket_data_t *) malloc(sizeof(*socket_data));
00909 if (!socket_data)
00910 return tcp_release_and_return(packet, ENOMEM);
00911
00912 tcp_initialize_socket_data(socket_data);
00913 socket_data->local_lock = listening_socket_data->local_lock;
00914 socket_data->local_sockets = listening_socket_data->local_sockets;
00915 socket_data->listening_socket_id = listening_socket->socket_id;
00916 socket_data->next_incoming = ntohl(header->sequence_number);
00917 socket_data->treshold = socket_data->next_incoming +
00918 ntohs(header->window);
00919 socket_data->addrlen = addrlen;
00920 socket_data->addr = malloc(socket_data->addrlen);
00921 if (!socket_data->addr) {
00922 free(socket_data);
00923 return tcp_release_and_return(packet, ENOMEM);
00924 }
00925
00926 memcpy(socket_data->addr, src, socket_data->addrlen);
00927 socket_data->dest_port = ntohs(header->source_port);
00928 rc = tl_set_address_port(socket_data->addr, socket_data->addrlen,
00929 socket_data->dest_port);
00930 if (rc != EOK) {
00931 free(socket_data->addr);
00932 free(socket_data);
00933 return tcp_release_and_return(packet, rc);
00934 }
00935
00936
00937 socket_id = -1;
00938 rc = socket_create(socket_data->local_sockets, listening_socket->phone,
00939 socket_data, &socket_id);
00940 if (rc != EOK) {
00941 free(socket_data->addr);
00942 free(socket_data);
00943 return tcp_release_and_return(packet, rc);
00944 }
00945
00946 printf("new_sock %d\n", socket_id);
00947 socket_data->pseudo_header = listening_socket_data->pseudo_header;
00948 socket_data->headerlen = listening_socket_data->headerlen;
00949 listening_socket_data->pseudo_header = NULL;
00950 listening_socket_data->headerlen = 0;
00951
00952 fibril_rwlock_write_unlock(socket_data->local_lock);
00953 fibril_rwlock_write_lock(&tcp_globals.lock);
00954
00955
00956 listening_socket = socket_port_find(&tcp_globals.sockets,
00957 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
00958 if (!listening_socket ||
00959 (listening_socket->socket_id != listening_socket_id)) {
00960 fibril_rwlock_write_unlock(&tcp_globals.lock);
00961
00962 return tcp_release_and_return(packet, EOK );
00963 }
00964 listening_socket_data =
00965 (tcp_socket_data_t *) listening_socket->specific_data;
00966 assert(listening_socket_data);
00967
00968 fibril_rwlock_write_lock(listening_socket_data->local_lock);
00969
00970 socket = socket_cores_find(listening_socket_data->local_sockets,
00971 socket_id);
00972 if (!socket) {
00973
00974 fibril_rwlock_write_unlock(&tcp_globals.lock);
00975 return ENOTSOCK;
00976 }
00977 socket_data = (tcp_socket_data_t *) socket->specific_data;
00978 assert(socket_data);
00979
00980 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket,
00981 (uint8_t *) socket_data->addr, socket_data->addrlen);
00982 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port,
00983 (uint8_t *) socket_data->addr, socket_data->addrlen));
00984
00985
00986
00987
00988
00989 fibril_rwlock_write_unlock(&tcp_globals.lock);
00990 if (rc != EOK) {
00991 socket_destroy(tcp_globals.net_phone, socket->socket_id,
00992 socket_data->local_sockets, &tcp_globals.sockets,
00993 tcp_free_socket_data);
00994 return tcp_release_and_return(packet, rc);
00995 }
00996
00997 socket_data->state = TCP_SOCKET_LISTEN;
00998 socket_data->next_incoming = ntohl(header->sequence_number) + 1;
00999
01000
01001 next_packet = pq_detach(packet);
01002 if (next_packet) {
01003 pq_release_remote(tcp_globals.net_phone,
01004 packet_get_id(next_packet));
01005 }
01006
01007
01008 if (packet_get_data_length(packet) > sizeof(*header)) {
01009 rc = packet_trim(packet, 0,
01010 packet_get_data_length(packet) - sizeof(*header));
01011 if (rc != EOK) {
01012 socket_destroy(tcp_globals.net_phone, socket->socket_id,
01013 socket_data->local_sockets, &tcp_globals.sockets,
01014 tcp_free_socket_data);
01015 return tcp_release_and_return(packet, rc);
01016 }
01017 }
01018
01019 tcp_prepare_operation_header(socket, socket_data, header, 1, 0);
01020
01021 rc = tcp_queue_packet(socket, socket_data, packet, 1);
01022 if (rc != EOK) {
01023 socket_destroy(tcp_globals.net_phone, socket->socket_id,
01024 socket_data->local_sockets, &tcp_globals.sockets,
01025 tcp_free_socket_data);
01026 return rc;
01027 }
01028
01029 packet = tcp_get_packets_to_send(socket, socket_data);
01030 if (!packet) {
01031 socket_destroy(tcp_globals.net_phone, socket->socket_id,
01032 socket_data->local_sockets, &tcp_globals.sockets,
01033 tcp_free_socket_data);
01034 return EINVAL;
01035 }
01036
01037 socket_data->state = TCP_SOCKET_SYN_RECEIVED;
01038 fibril_rwlock_write_unlock(socket_data->local_lock);
01039
01040
01041 tcp_send_packets(socket_data->device_id, packet);
01042
01043 return EOK;
01044 }
01045
01046 int tcp_process_syn_received(socket_core_t *socket,
01047 tcp_socket_data_t *socket_data, tcp_header_t *header, packet_t *packet)
01048 {
01049 socket_core_t *listening_socket;
01050 tcp_socket_data_t *listening_socket_data;
01051 int rc;
01052
01053 assert(socket);
01054 assert(socket_data);
01055 assert(socket->specific_data == socket_data);
01056 assert(header);
01057 assert(packet);
01058
01059 if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
01060 return tcp_release_and_return(packet, EINVAL);
01061
01062
01063 tcp_process_acknowledgement(socket, socket_data, header);
01064
01065 socket_data->next_incoming = ntohl(header->sequence_number);
01066 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
01067 socket_data->state = TCP_SOCKET_ESTABLISHED;
01068 listening_socket = socket_cores_find(socket_data->local_sockets,
01069 socket_data->listening_socket_id);
01070 if (listening_socket) {
01071 listening_socket_data =
01072 (tcp_socket_data_t *) listening_socket->specific_data;
01073 assert(listening_socket_data);
01074
01075
01076 rc = dyn_fifo_push(&listening_socket->accepted,
01077 (-1 * socket->socket_id), listening_socket_data->backlog);
01078 if (rc == EOK) {
01079
01080 async_msg_5(socket->phone, NET_SOCKET_ACCEPTED,
01081 (sysarg_t) listening_socket->socket_id,
01082 socket_data->data_fragment_size, TCP_HEADER_SIZE,
01083 0, (sysarg_t) socket->socket_id);
01084
01085 fibril_rwlock_write_unlock(socket_data->local_lock);
01086 return EOK;
01087 }
01088 }
01089
01090 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
01091
01092
01093 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
01094 if (rc != EOK)
01095 return rc;
01096
01097
01098 rc = tcp_queue_packet(socket, socket_data, packet, 1);
01099 if (rc != EOK)
01100 return rc;
01101
01102
01103 packet = tcp_get_packets_to_send(socket, socket_data);
01104 fibril_rwlock_write_unlock(socket_data->local_lock);
01105 if (packet) {
01106
01107 tcp_send_packets(socket_data->device_id, packet);
01108 }
01109
01110 return EOK;
01111 }
01112
01113 void tcp_process_acknowledgement(socket_core_t *socket,
01114 tcp_socket_data_t *socket_data, tcp_header_t *header)
01115 {
01116 size_t number;
01117 size_t length;
01118 packet_t *packet;
01119 packet_t *next;
01120 packet_t *acknowledged = NULL;
01121 uint32_t old;
01122
01123 assert(socket);
01124 assert(socket_data);
01125 assert(socket->specific_data == socket_data);
01126 assert(header);
01127
01128 if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
01129 return;
01130
01131 number = ntohl(header->acknowledgement_number);
01132
01133
01134 if (number != socket_data->expected) {
01135 old = socket_data->expected;
01136 if (IS_IN_INTERVAL_OVERFLOW(old, socket_data->fin_outgoing,
01137 number)) {
01138 switch (socket_data->state) {
01139 case TCP_SOCKET_FIN_WAIT_1:
01140 socket_data->state = TCP_SOCKET_FIN_WAIT_2;
01141 break;
01142 case TCP_SOCKET_LAST_ACK:
01143 case TCP_SOCKET_CLOSING:
01144
01145
01146
01147
01148 tcp_prepare_timeout(tcp_release_after_timeout,
01149 socket, socket_data, 0,
01150 TCP_SOCKET_TIME_WAIT,
01151 NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true);
01152 break;
01153 default:
01154 break;
01155 }
01156 }
01157
01158
01159 if (number + ntohs(header->window) >
01160 socket_data->expected + socket_data->treshold) {
01161 socket_data->treshold = number + ntohs(header->window) -
01162 socket_data->expected;
01163 }
01164
01165
01166 socket_data->expected = number;
01167 socket_data->expected_count = 1;
01168 packet = socket_data->outgoing;
01169 while (pq_get_order(packet, &number, &length) == EOK) {
01170 if (IS_IN_INTERVAL_OVERFLOW((uint32_t) old,
01171 (uint32_t) (number + length),
01172 (uint32_t) socket_data->expected)) {
01173 next = pq_detach(packet);
01174 if (packet == socket_data->outgoing)
01175 socket_data->outgoing = next;
01176
01177
01178 if (pq_add(&acknowledged, packet, 0, 0) != EOK)
01179 pq_release_remote(tcp_globals.net_phone,
01180 packet_get_id(packet));
01181 packet = next;
01182 } else if (old < socket_data->expected)
01183 break;
01184 }
01185
01186
01187 if (acknowledged) {
01188 pq_release_remote(tcp_globals.net_phone,
01189 packet_get_id(acknowledged));
01190 }
01191 return;
01192
01193 }
01194
01195 if (number == socket_data->expected) {
01196
01197 socket_data->expected_count++;
01198 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) {
01199 socket_data->expected_count = 1;
01200
01201
01202 }
01203 }
01204 }
01205
01209 void tl_connection(void)
01210 {
01211 }
01212
01226 int tl_message(ipc_callid_t callid, ipc_call_t *call,
01227 ipc_call_t *answer, size_t *answer_count)
01228 {
01229 assert(call);
01230 assert(answer);
01231 assert(answer_count);
01232
01233 *answer_count = 0;
01234 switch (IPC_GET_IMETHOD(*call)) {
01235 case IPC_M_CONNECT_TO_ME:
01236 return tcp_process_client_messages(callid, *call);
01237 }
01238
01239 return ENOTSUP;
01240 }
01241
01242 void tcp_refresh_socket_data(tcp_socket_data_t *socket_data)
01243 {
01244 assert(socket_data);
01245
01246 bzero(socket_data, sizeof(*socket_data));
01247 socket_data->state = TCP_SOCKET_INITIAL;
01248 socket_data->device_id = DEVICE_INVALID_ID;
01249 socket_data->window = NET_DEFAULT_TCP_WINDOW;
01250 socket_data->treshold = socket_data->window;
01251 socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
01252 socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
01253 socket_data->acknowledged = socket_data->last_outgoing;
01254 socket_data->next_outgoing = socket_data->last_outgoing + 1;
01255 socket_data->expected = socket_data->next_outgoing;
01256 }
01257
01258 void tcp_initialize_socket_data(tcp_socket_data_t *socket_data)
01259 {
01260 assert(socket_data);
01261
01262 tcp_refresh_socket_data(socket_data);
01263 fibril_mutex_initialize(&socket_data->operation.mutex);
01264 fibril_condvar_initialize(&socket_data->operation.condvar);
01265 socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
01266 }
01267
01268 int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
01269 {
01270 int res;
01271 bool keep_on_going = true;
01272 socket_cores_t local_sockets;
01273 int app_phone = IPC_GET_PHONE(call);
01274 struct sockaddr *addr;
01275 int socket_id;
01276 size_t addrlen;
01277 size_t size;
01278 fibril_rwlock_t lock;
01279 ipc_call_t answer;
01280 size_t answer_count;
01281 tcp_socket_data_t *socket_data;
01282 socket_core_t *socket;
01283 packet_dimension_t *packet_dimension;
01284
01285
01286
01287
01288
01289 res = EOK;
01290 answer_count = 0;
01291
01292 socket_cores_initialize(&local_sockets);
01293 fibril_rwlock_initialize(&lock);
01294
01295 while (keep_on_going) {
01296
01297
01298 answer_call(callid, res, &answer, answer_count);
01299
01300 refresh_answer(&answer, &answer_count);
01301
01302 callid = async_get_call(&call);
01303
01304
01305 switch (IPC_GET_IMETHOD(call)) {
01306 case IPC_M_PHONE_HUNGUP:
01307 keep_on_going = false;
01308 res = EHANGUP;
01309 break;
01310
01311 case NET_SOCKET:
01312 socket_data =
01313 (tcp_socket_data_t *) malloc(sizeof(*socket_data));
01314 if (!socket_data) {
01315 res = ENOMEM;
01316 break;
01317 }
01318
01319 tcp_initialize_socket_data(socket_data);
01320 socket_data->local_lock = &lock;
01321 socket_data->local_sockets = &local_sockets;
01322 fibril_rwlock_write_lock(&lock);
01323 socket_id = SOCKET_GET_SOCKET_ID(call);
01324 res = socket_create(&local_sockets, app_phone,
01325 socket_data, &socket_id);
01326 SOCKET_SET_SOCKET_ID(answer, socket_id);
01327 fibril_rwlock_write_unlock(&lock);
01328 if (res != EOK) {
01329 free(socket_data);
01330 break;
01331 }
01332 if (tl_get_ip_packet_dimension(tcp_globals.ip_phone,
01333 &tcp_globals.dimensions, DEVICE_INVALID_ID,
01334 &packet_dimension) == EOK) {
01335 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
01336 ((packet_dimension->content <
01337 socket_data->data_fragment_size) ?
01338 packet_dimension->content :
01339 socket_data->data_fragment_size));
01340 }
01341
01342 SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
01343 answer_count = 3;
01344 break;
01345
01346 case NET_SOCKET_BIND:
01347 res = async_data_write_accept((void **) &addr, false,
01348 0, 0, 0, &addrlen);
01349 if (res != EOK)
01350 break;
01351 fibril_rwlock_write_lock(&tcp_globals.lock);
01352 fibril_rwlock_write_lock(&lock);
01353 res = socket_bind(&local_sockets, &tcp_globals.sockets,
01354 SOCKET_GET_SOCKET_ID(call), addr, addrlen,
01355 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
01356 tcp_globals.last_used_port);
01357 if (res == EOK) {
01358 socket = socket_cores_find(&local_sockets,
01359 SOCKET_GET_SOCKET_ID(call));
01360 if (socket) {
01361 socket_data = (tcp_socket_data_t *)
01362 socket->specific_data;
01363 assert(socket_data);
01364 socket_data->state = TCP_SOCKET_LISTEN;
01365 }
01366 }
01367 fibril_rwlock_write_unlock(&lock);
01368 fibril_rwlock_write_unlock(&tcp_globals.lock);
01369 free(addr);
01370 break;
01371
01372 case NET_SOCKET_LISTEN:
01373 fibril_rwlock_read_lock(&tcp_globals.lock);
01374
01375 fibril_rwlock_write_lock(&lock);
01376 res = tcp_listen_message(&local_sockets,
01377 SOCKET_GET_SOCKET_ID(call),
01378 SOCKET_GET_BACKLOG(call));
01379 fibril_rwlock_write_unlock(&lock);
01380
01381 fibril_rwlock_read_unlock(&tcp_globals.lock);
01382 break;
01383
01384 case NET_SOCKET_CONNECT:
01385 res = async_data_write_accept((void **) &addr, false,
01386 0, 0, 0, &addrlen);
01387 if (res != EOK)
01388 break;
01389
01390
01391
01392
01393 fibril_rwlock_write_lock(&tcp_globals.lock);
01394 fibril_rwlock_write_lock(&lock);
01395 res = tcp_connect_message(&local_sockets,
01396 SOCKET_GET_SOCKET_ID(call), addr, addrlen);
01397 if (res != EOK) {
01398 fibril_rwlock_write_unlock(&lock);
01399 fibril_rwlock_write_unlock(&tcp_globals.lock);
01400 free(addr);
01401 }
01402 break;
01403
01404 case NET_SOCKET_ACCEPT:
01405 fibril_rwlock_read_lock(&tcp_globals.lock);
01406 fibril_rwlock_write_lock(&lock);
01407 res = tcp_accept_message(&local_sockets,
01408 SOCKET_GET_SOCKET_ID(call),
01409 SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen);
01410 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
01411 fibril_rwlock_write_unlock(&lock);
01412 fibril_rwlock_read_unlock(&tcp_globals.lock);
01413 if (res > 0) {
01414 SOCKET_SET_SOCKET_ID(answer, res);
01415 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
01416 answer_count = 3;
01417 }
01418 break;
01419
01420 case NET_SOCKET_SEND:
01421 fibril_rwlock_read_lock(&tcp_globals.lock);
01422 fibril_rwlock_write_lock(&lock);
01423 res = tcp_send_message(&local_sockets,
01424 SOCKET_GET_SOCKET_ID(call),
01425 SOCKET_GET_DATA_FRAGMENTS(call), &size,
01426 SOCKET_GET_FLAGS(call));
01427 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
01428 if (res != EOK) {
01429 fibril_rwlock_write_unlock(&lock);
01430 fibril_rwlock_read_unlock(&tcp_globals.lock);
01431 } else {
01432 answer_count = 2;
01433 }
01434 break;
01435
01436 case NET_SOCKET_SENDTO:
01437 res = async_data_write_accept((void **) &addr, false,
01438 0, 0, 0, &addrlen);
01439 if (res != EOK)
01440 break;
01441 fibril_rwlock_read_lock(&tcp_globals.lock);
01442 fibril_rwlock_write_lock(&lock);
01443 res = tcp_send_message(&local_sockets,
01444 SOCKET_GET_SOCKET_ID(call),
01445 SOCKET_GET_DATA_FRAGMENTS(call), &size,
01446 SOCKET_GET_FLAGS(call));
01447 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
01448 if (res != EOK) {
01449 fibril_rwlock_write_unlock(&lock);
01450 fibril_rwlock_read_unlock(&tcp_globals.lock);
01451 } else {
01452 answer_count = 2;
01453 }
01454 free(addr);
01455 break;
01456
01457 case NET_SOCKET_RECV:
01458 fibril_rwlock_read_lock(&tcp_globals.lock);
01459 fibril_rwlock_write_lock(&lock);
01460 res = tcp_recvfrom_message(&local_sockets,
01461 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
01462 NULL);
01463 fibril_rwlock_write_unlock(&lock);
01464 fibril_rwlock_read_unlock(&tcp_globals.lock);
01465 if (res > 0) {
01466 SOCKET_SET_READ_DATA_LENGTH(answer, res);
01467 answer_count = 1;
01468 res = EOK;
01469 }
01470 break;
01471
01472 case NET_SOCKET_RECVFROM:
01473 fibril_rwlock_read_lock(&tcp_globals.lock);
01474 fibril_rwlock_write_lock(&lock);
01475 res = tcp_recvfrom_message(&local_sockets,
01476 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
01477 &addrlen);
01478 fibril_rwlock_write_unlock(&lock);
01479 fibril_rwlock_read_unlock(&tcp_globals.lock);
01480 if (res > 0) {
01481 SOCKET_SET_READ_DATA_LENGTH(answer, res);
01482 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
01483 answer_count = 3;
01484 res = EOK;
01485 }
01486 break;
01487
01488 case NET_SOCKET_CLOSE:
01489 fibril_rwlock_write_lock(&tcp_globals.lock);
01490 fibril_rwlock_write_lock(&lock);
01491 res = tcp_close_message(&local_sockets,
01492 SOCKET_GET_SOCKET_ID(call));
01493 if (res != EOK) {
01494 fibril_rwlock_write_unlock(&lock);
01495 fibril_rwlock_write_unlock(&tcp_globals.lock);
01496 }
01497 break;
01498
01499 case NET_SOCKET_GETSOCKOPT:
01500 case NET_SOCKET_SETSOCKOPT:
01501 default:
01502 res = ENOTSUP;
01503 break;
01504 }
01505 }
01506
01507
01508 async_hangup(app_phone);
01509
01510 printf("release\n");
01511
01512 socket_cores_release(tcp_globals.net_phone, &local_sockets,
01513 &tcp_globals.sockets, tcp_free_socket_data);
01514
01515 return EOK;
01516 }
01517
01518 int tcp_timeout(void *data)
01519 {
01520 tcp_timeout_t *timeout = data;
01521 int keep_write_lock = false;
01522 socket_core_t *socket;
01523 tcp_socket_data_t *socket_data;
01524
01525 assert(timeout);
01526
01527
01528 async_usleep(timeout->timeout);
01529
01530 if (timeout->globals_read_only)
01531 fibril_rwlock_read_lock(&tcp_globals.lock);
01532 else
01533 fibril_rwlock_write_lock(&tcp_globals.lock);
01534
01535
01536 socket = socket_port_find(&tcp_globals.sockets, timeout->port,
01537 timeout->key, timeout->key_length);
01538 if (!socket || (socket->socket_id != timeout->socket_id))
01539 goto out;
01540
01541 socket_data = (tcp_socket_data_t *) socket->specific_data;
01542 assert(socket_data);
01543 if (socket_data->local_sockets != timeout->local_sockets)
01544 goto out;
01545
01546 fibril_rwlock_write_lock(socket_data->local_lock);
01547 if (timeout->sequence_number) {
01548
01549 socket_data->timeout_count++;
01550 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) {
01551
01552
01553 fibril_rwlock_write_unlock(socket_data->local_lock);
01554 } else {
01555
01556
01557
01558 fibril_rwlock_write_unlock(socket_data->local_lock);
01559 }
01560 } else {
01561 fibril_mutex_lock(&socket_data->operation.mutex);
01562
01563 if (socket_data->state == timeout->state) {
01564 socket_data->operation.result = ETIMEOUT;
01565
01566
01567 fibril_condvar_signal(&socket_data->operation.condvar);
01568
01569
01570 keep_write_lock = true;
01571 } else {
01572
01573
01574
01575
01576
01577 fibril_rwlock_write_unlock(socket_data->local_lock);
01578 }
01579 fibril_mutex_unlock(&socket_data->operation.mutex);
01580 }
01581
01582 out:
01583
01584 if (timeout->globals_read_only)
01585 fibril_rwlock_read_unlock(&tcp_globals.lock);
01586 else if (!keep_write_lock)
01587
01588 fibril_rwlock_write_unlock(&tcp_globals.lock);
01589
01590
01591 free(timeout);
01592 return EOK;
01593 }
01594
01595 int tcp_release_after_timeout(void *data)
01596 {
01597 tcp_timeout_t *timeout = data;
01598 socket_core_t *socket;
01599 tcp_socket_data_t *socket_data;
01600 fibril_rwlock_t *local_lock;
01601
01602 assert(timeout);
01603
01604
01605 async_usleep(timeout->timeout);
01606
01607
01608 fibril_rwlock_write_lock(&tcp_globals.lock);
01609
01610
01611 socket = socket_port_find(&tcp_globals.sockets, timeout->port,
01612 timeout->key, timeout->key_length);
01613
01614 if (socket && (socket->socket_id == timeout->socket_id)) {
01615 socket_data = (tcp_socket_data_t *) socket->specific_data;
01616 assert(socket_data);
01617 if (socket_data->local_sockets == timeout->local_sockets) {
01618 local_lock = socket_data->local_lock;
01619 fibril_rwlock_write_lock(local_lock);
01620 socket_destroy(tcp_globals.net_phone,
01621 timeout->socket_id, timeout->local_sockets,
01622 &tcp_globals.sockets, tcp_free_socket_data);
01623 fibril_rwlock_write_unlock(local_lock);
01624 }
01625 }
01626
01627
01628 fibril_rwlock_write_unlock(&tcp_globals.lock);
01629
01630
01631 free(timeout);
01632
01633 return EOK;
01634 }
01635
01636 void tcp_retransmit_packet(socket_core_t *socket, tcp_socket_data_t *
01637 socket_data, size_t sequence_number)
01638 {
01639 packet_t *packet;
01640 packet_t *copy;
01641 size_t data_length;
01642
01643 assert(socket);
01644 assert(socket_data);
01645 assert(socket->specific_data == socket_data);
01646
01647
01648 packet = pq_find(socket_data->outgoing, sequence_number);
01649 printf("retransmit %d\n", packet_get_id(packet));
01650 if (packet) {
01651 pq_get_order(packet, NULL, &data_length);
01652 copy = tcp_prepare_copy(socket, socket_data, packet,
01653 data_length, sequence_number);
01654 fibril_rwlock_write_unlock(socket_data->local_lock);
01655
01656 if (copy)
01657 tcp_send_packets(socket_data->device_id, copy);
01658 } else {
01659 fibril_rwlock_write_unlock(socket_data->local_lock);
01660 }
01661 }
01662
01663 int tcp_listen_message(socket_cores_t *local_sockets, int socket_id,
01664 int backlog)
01665 {
01666 socket_core_t *socket;
01667 tcp_socket_data_t *socket_data;
01668
01669 assert(local_sockets);
01670
01671 if (backlog < 0)
01672 return EINVAL;
01673
01674
01675 socket = socket_cores_find(local_sockets, socket_id);
01676 if (!socket)
01677 return ENOTSOCK;
01678
01679
01680 socket_data = (tcp_socket_data_t *) socket->specific_data;
01681 assert(socket_data);
01682
01683
01684 socket_data->backlog = backlog;
01685
01686 return EOK;
01687 }
01688
01689 int tcp_connect_message(socket_cores_t *local_sockets, int socket_id,
01690 struct sockaddr *addr, socklen_t addrlen)
01691 {
01692 socket_core_t *socket;
01693 int rc;
01694
01695 assert(local_sockets);
01696 assert(addr);
01697 assert(addrlen > 0);
01698
01699
01700 socket = socket_cores_find(local_sockets, socket_id);
01701 if (!socket)
01702 return ENOTSOCK;
01703
01704 rc = tcp_connect_core(socket, local_sockets, addr, addrlen);
01705 if (rc != EOK) {
01706 tcp_free_socket_data(socket);
01707
01708 if (socket->port > 0) {
01709 socket_ports_exclude(&tcp_globals.sockets,
01710 socket->port, free);
01711 socket->port = 0;
01712 }
01713 }
01714 return rc;
01715 }
01716
01717 int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets,
01718 struct sockaddr *addr, socklen_t addrlen)
01719 {
01720 tcp_socket_data_t *socket_data;
01721 packet_t *packet;
01722 int rc;
01723
01724 assert(socket);
01725 assert(addr);
01726 assert(addrlen > 0);
01727
01728
01729 socket_data = (tcp_socket_data_t *) socket->specific_data;
01730 assert(socket_data);
01731 assert(socket->specific_data == socket_data);
01732 if ((socket_data->state != TCP_SOCKET_INITIAL) &&
01733 ((socket_data->state != TCP_SOCKET_LISTEN) ||
01734 (socket->port <= 0)))
01735 return EINVAL;
01736
01737
01738 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port);
01739 if (rc != EOK)
01740 return rc;
01741
01742 if (socket->port <= 0) {
01743
01744 rc = socket_bind_free_port(&tcp_globals.sockets, socket,
01745 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
01746 tcp_globals.last_used_port);
01747 if (rc != EOK)
01748 return rc;
01749
01750 tcp_globals.last_used_port = socket->port;
01751 }
01752
01753 rc = ip_get_route_req(tcp_globals.ip_phone, IPPROTO_TCP,
01754 addr, addrlen, &socket_data->device_id,
01755 &socket_data->pseudo_header, &socket_data->headerlen);
01756 if (rc != EOK)
01757 return rc;
01758
01759
01760 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0);
01761 if (rc != EOK)
01762 return rc;
01763
01764
01765 fibril_rwlock_write_unlock(&tcp_globals.lock);
01766
01767 socket_data->addr = addr;
01768 socket_data->addrlen = addrlen;
01769
01770
01771
01772 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) ||
01773 ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0,
01774 TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) !=
01775 EOK)) {
01776 socket_data->addr = NULL;
01777 socket_data->addrlen = 0;
01778 fibril_rwlock_write_lock(&tcp_globals.lock);
01779 } else {
01780 packet = tcp_get_packets_to_send(socket, socket_data);
01781 if (packet) {
01782 fibril_mutex_lock(&socket_data->operation.mutex);
01783 fibril_rwlock_write_unlock(socket_data->local_lock);
01784
01785 socket_data->state = TCP_SOCKET_SYN_SENT;
01786
01787
01788 printf("connecting %d\n", packet_get_id(packet));
01789 tcp_send_packets(socket_data->device_id, packet);
01790
01791
01792 fibril_condvar_wait(&socket_data->operation.condvar,
01793 &socket_data->operation.mutex);
01794 rc = socket_data->operation.result;
01795 if (rc != EOK) {
01796 socket_data->addr = NULL;
01797 socket_data->addrlen = 0;
01798 }
01799 } else {
01800 socket_data->addr = NULL;
01801 socket_data->addrlen = 0;
01802 rc = EINTR;
01803 }
01804 }
01805
01806 fibril_mutex_unlock(&socket_data->operation.mutex);
01807 return rc;
01808 }
01809
01810 int tcp_queue_prepare_packet(socket_core_t *socket,
01811 tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length)
01812 {
01813 tcp_header_t *header;
01814 int rc;
01815
01816 assert(socket);
01817 assert(socket_data);
01818 assert(socket->specific_data == socket_data);
01819
01820
01821 header = (tcp_header_t *) packet_get_data(packet);
01822 if (!header)
01823 return NO_DATA;
01824
01825 header->destination_port = htons(socket_data->dest_port);
01826 header->source_port = htons(socket->port);
01827 header->sequence_number = htonl(socket_data->next_outgoing);
01828
01829 rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr,
01830 socket_data->addrlen);
01831 if (rc != EOK)
01832 return tcp_release_and_return(packet, EINVAL);
01833
01834
01835 if (GET_TCP_HEADER_FINALIZE(header))
01836 socket_data->fin_outgoing = socket_data->next_outgoing;
01837
01838 return EOK;
01839 }
01840
01841 int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data,
01842 packet_t *packet, size_t data_length)
01843 {
01844 int rc;
01845
01846 assert(socket);
01847 assert(socket_data);
01848 assert(socket->specific_data == socket_data);
01849
01850 rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length);
01851 if (rc != EOK)
01852 return rc;
01853
01854 rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing,
01855 data_length);
01856 if (rc != EOK)
01857 return tcp_release_and_return(packet, rc);
01858
01859 socket_data->next_outgoing += data_length;
01860 return EOK;
01861 }
01862
01863 packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t *
01864 socket_data)
01865 {
01866 packet_t *packet;
01867 packet_t *copy;
01868 packet_t *sending = NULL;
01869 packet_t *previous = NULL;
01870 size_t data_length;
01871 int rc;
01872
01873 assert(socket);
01874 assert(socket_data);
01875 assert(socket->specific_data == socket_data);
01876
01877 packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
01878 while (packet) {
01879 pq_get_order(packet, NULL, &data_length);
01880
01881
01882
01883
01884
01885 if (!IS_IN_INTERVAL_OVERFLOW(
01886 (uint32_t) socket_data->last_outgoing,
01887 (uint32_t) (socket_data->last_outgoing + data_length),
01888 (uint32_t) (socket_data->expected + socket_data->treshold)))
01889 break;
01890
01891 copy = tcp_prepare_copy(socket, socket_data, packet,
01892 data_length, socket_data->last_outgoing + 1);
01893 if (!copy)
01894 return sending;
01895
01896 if (!sending) {
01897 sending = copy;
01898 } else {
01899 rc = pq_insert_after(previous, copy);
01900 if (rc != EOK) {
01901 pq_release_remote(tcp_globals.net_phone,
01902 packet_get_id(copy));
01903 return sending;
01904 }
01905 }
01906
01907 previous = copy;
01908 packet = pq_next(packet);
01909
01910
01911 if (!packet &&
01912 (socket_data->last_outgoing > socket_data->next_outgoing)) {
01913 printf("gpts overflow\n");
01914
01915 packet = socket_data->outgoing;
01916 }
01917 socket_data->last_outgoing += data_length;
01918 }
01919
01920 return sending;
01921 }
01922
01923 packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t *
01924 socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
01925 {
01926 tcp_header_t *header;
01927 uint32_t checksum;
01928 int rc;
01929
01930 assert(socket);
01931 assert(socket_data);
01932 assert(socket->specific_data == socket_data);
01933
01934
01935 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header,
01936 socket_data->headerlen, packet_get_data_length(packet));
01937 if (rc != EOK) {
01938 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
01939 return NULL;
01940 }
01941
01942
01943 header = (tcp_header_t *) packet_get_data(packet);
01944 if (!header) {
01945 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
01946 return NULL;
01947 }
01948 assert(ntohl(header->sequence_number) == sequence_number);
01949
01950
01951 if (socket_data->next_incoming) {
01952 header->acknowledgement_number =
01953 htonl(socket_data->next_incoming);
01954 SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
01955 }
01956 header->window = htons(socket_data->window);
01957
01958
01959 header->checksum = 0;
01960 checksum = compute_checksum(0, socket_data->pseudo_header,
01961 socket_data->headerlen);
01962 checksum = compute_checksum(checksum,
01963 (uint8_t *) packet_get_data(packet),
01964 packet_get_data_length(packet));
01965 header->checksum = htons(flip_checksum(compact_checksum(checksum)));
01966
01967
01968 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
01969 if (rc != EOK) {
01970 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
01971 return NULL;
01972 }
01973
01974 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data,
01975 sequence_number, socket_data->state, socket_data->timeout, true);
01976 if (rc != EOK) {
01977 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
01978 return NULL;
01979 }
01980
01981 return packet;
01982 }
01983
01984 packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t *
01985 socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
01986 {
01987 packet_t *copy;
01988
01989 assert(socket);
01990 assert(socket_data);
01991 assert(socket->specific_data == socket_data);
01992
01993
01994 copy = packet_get_copy(tcp_globals.net_phone, packet);
01995 if (!copy)
01996 return NULL;
01997
01998 return tcp_send_prepare_packet(socket, socket_data, copy, data_length,
01999 sequence_number);
02000 }
02001
02002 void tcp_send_packets(device_id_t device_id, packet_t *packet)
02003 {
02004 packet_t *next;
02005
02006 while (packet) {
02007 next = pq_detach(packet);
02008 ip_send_msg(tcp_globals.ip_phone, device_id, packet,
02009 SERVICE_TCP, 0);
02010 packet = next;
02011 }
02012 }
02013
02014 void tcp_prepare_operation_header(socket_core_t *socket,
02015 tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize,
02016 int finalize)
02017 {
02018 assert(socket);
02019 assert(socket_data);
02020 assert(socket->specific_data == socket_data);
02021 assert(header);
02022
02023 bzero(header, sizeof(*header));
02024 header->source_port = htons(socket->port);
02025 header->source_port = htons(socket_data->dest_port);
02026 SET_TCP_HEADER_LENGTH(header,
02027 TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
02028 SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
02029 SET_TCP_HEADER_FINALIZE(header, finalize);
02030 }
02031
02032 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t),
02033 socket_core_t *socket, tcp_socket_data_t *socket_data,
02034 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout,
02035 int globals_read_only)
02036 {
02037 tcp_timeout_t *operation_timeout;
02038 fid_t fibril;
02039
02040 assert(socket);
02041 assert(socket_data);
02042 assert(socket->specific_data == socket_data);
02043
02044
02045 operation_timeout = malloc(sizeof(*operation_timeout) +
02046 socket->key_length + 1);
02047 if (!operation_timeout)
02048 return ENOMEM;
02049
02050 bzero(operation_timeout, sizeof(*operation_timeout));
02051 operation_timeout->globals_read_only = globals_read_only;
02052 operation_timeout->port = socket->port;
02053 operation_timeout->local_sockets = socket_data->local_sockets;
02054 operation_timeout->socket_id = socket->socket_id;
02055 operation_timeout->timeout = timeout;
02056 operation_timeout->sequence_number = sequence_number;
02057 operation_timeout->state = state;
02058
02059
02060 operation_timeout->key = ((uint8_t *) operation_timeout) +
02061 sizeof(*operation_timeout);
02062 operation_timeout->key_length = socket->key_length;
02063 memcpy(operation_timeout->key, socket->key, socket->key_length);
02064 operation_timeout->key[operation_timeout->key_length] = '\0';
02065
02066
02067 fibril = fibril_create(timeout_function, operation_timeout);
02068 if (!fibril) {
02069 free(operation_timeout);
02070 return ENOMEM;
02071 }
02072
02073
02074
02075 fibril_add_ready(fibril);
02076
02077 return EOK;
02078 }
02079
02080 int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
02081 int flags, size_t *addrlen)
02082 {
02083 socket_core_t *socket;
02084 tcp_socket_data_t *socket_data;
02085 int packet_id;
02086 packet_t *packet;
02087 size_t length;
02088 int rc;
02089
02090 assert(local_sockets);
02091
02092
02093 socket = socket_cores_find(local_sockets, socket_id);
02094 if (!socket)
02095 return ENOTSOCK;
02096
02097
02098 if (!socket->specific_data)
02099 return NO_DATA;
02100
02101 socket_data = (tcp_socket_data_t *) socket->specific_data;
02102
02103
02104 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
02105 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
02106 return ENOTCONN;
02107
02108
02109 if (addrlen) {
02110 rc = data_reply(socket_data->addr, socket_data->addrlen);
02111 if (rc != EOK)
02112 return rc;
02113 *addrlen = socket_data->addrlen;
02114 }
02115
02116
02117 packet_id = dyn_fifo_value(&socket->received);
02118 if (packet_id < 0)
02119 return NO_DATA;
02120
02121 rc = packet_translate_remote(tcp_globals.net_phone, &packet, packet_id);
02122 if (rc != EOK)
02123 return rc;
02124
02125
02126 rc = socket_reply_packets(packet, &length);
02127 if (rc != EOK)
02128 return rc;
02129
02130
02131 dyn_fifo_pop(&socket->received);
02132 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
02133
02134
02135 return (int) length;
02136 }
02137
02138 int tcp_send_message(socket_cores_t *local_sockets, int socket_id,
02139 int fragments, size_t *data_fragment_size, int flags)
02140 {
02141 socket_core_t *socket;
02142 tcp_socket_data_t *socket_data;
02143 packet_dimension_t *packet_dimension;
02144 packet_t *packet;
02145 size_t total_length;
02146 tcp_header_t *header;
02147 int index;
02148 int result;
02149 int rc;
02150
02151 assert(local_sockets);
02152 assert(data_fragment_size);
02153
02154
02155 socket = socket_cores_find(local_sockets, socket_id);
02156 if (!socket)
02157 return ENOTSOCK;
02158
02159
02160 if (!socket->specific_data)
02161 return NO_DATA;
02162
02163 socket_data = (tcp_socket_data_t *) socket->specific_data;
02164
02165
02166 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
02167 (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
02168 return ENOTCONN;
02169
02170 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
02171 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
02172 if (rc != EOK)
02173 return rc;
02174
02175 *data_fragment_size =
02176 ((packet_dimension->content < socket_data->data_fragment_size) ?
02177 packet_dimension->content : socket_data->data_fragment_size);
02178
02179 for (index = 0; index < fragments; index++) {
02180
02181 result = tl_socket_read_packet_data(tcp_globals.net_phone,
02182 &packet, TCP_HEADER_SIZE, packet_dimension,
02183 socket_data->addr, socket_data->addrlen);
02184 if (result < 0)
02185 return result;
02186
02187 total_length = (size_t) result;
02188
02189
02190 header = PACKET_PREFIX(packet, tcp_header_t);
02191 if (!header)
02192 return tcp_release_and_return(packet, ENOMEM);
02193
02194 tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
02195 rc = tcp_queue_packet(socket, socket_data, packet, total_length);
02196 if (rc != EOK)
02197 return rc;
02198 }
02199
02200
02201 packet = tcp_get_packets_to_send(socket, socket_data);
02202 fibril_rwlock_write_unlock(socket_data->local_lock);
02203 fibril_rwlock_read_unlock(&tcp_globals.lock);
02204
02205 if (packet) {
02206
02207 tcp_send_packets(socket_data->device_id, packet);
02208 }
02209
02210 return EOK;
02211 }
02212
02213 int
02214 tcp_close_message(socket_cores_t *local_sockets, int socket_id)
02215 {
02216 socket_core_t *socket;
02217 tcp_socket_data_t *socket_data;
02218 packet_t *packet;
02219 int rc;
02220
02221
02222 socket = socket_cores_find(local_sockets, socket_id);
02223 if (!socket)
02224 return ENOTSOCK;
02225
02226
02227 socket_data = (tcp_socket_data_t *) socket->specific_data;
02228 assert(socket_data);
02229
02230
02231 switch (socket_data->state) {
02232 case TCP_SOCKET_ESTABLISHED:
02233 socket_data->state = TCP_SOCKET_FIN_WAIT_1;
02234 break;
02235
02236 case TCP_SOCKET_CLOSE_WAIT:
02237 socket_data->state = TCP_SOCKET_LAST_ACK;
02238 break;
02239
02240
02241
02242 default:
02243
02244 rc = socket_destroy(tcp_globals.net_phone, socket_id,
02245 local_sockets, &tcp_globals.sockets,
02246 tcp_free_socket_data);
02247 if (rc == EOK) {
02248 fibril_rwlock_write_unlock(socket_data->local_lock);
02249 fibril_rwlock_write_unlock(&tcp_globals.lock);
02250 }
02251 return rc;
02252 }
02253
02254
02255
02256
02257
02258
02259
02260 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
02261 if (rc != EOK)
02262 return rc;
02263
02264
02265 rc = tcp_queue_packet(socket, socket_data, packet, 1);
02266 if (rc != EOK)
02267 return rc;
02268
02269
02270 packet = tcp_get_packets_to_send(socket, socket_data);
02271 fibril_rwlock_write_unlock(socket_data->local_lock);
02272 fibril_rwlock_write_unlock(&tcp_globals.lock);
02273
02274 if (packet) {
02275
02276 tcp_send_packets(socket_data->device_id, packet);
02277 }
02278
02279 return EOK;
02280 }
02281
02282 int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket,
02283 tcp_socket_data_t *socket_data, int synchronize, int finalize)
02284 {
02285 packet_dimension_t *packet_dimension;
02286 tcp_header_t *header;
02287 int rc;
02288
02289 assert(packet);
02290
02291
02292 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
02293 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
02294 if (rc != EOK)
02295 return rc;
02296
02297
02298 *packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE,
02299 packet_dimension->addr_len, packet_dimension->prefix,
02300 packet_dimension->suffix);
02301
02302 if (!*packet)
02303 return ENOMEM;
02304
02305
02306 header = PACKET_SUFFIX(*packet, tcp_header_t);
02307 if (!header)
02308 tcp_release_and_return(*packet, ENOMEM);
02309
02310 tcp_prepare_operation_header(socket, socket_data, header, synchronize,
02311 finalize);
02312
02313 return EOK;
02314 }
02315
02316 int tcp_accept_message(socket_cores_t *local_sockets, int socket_id,
02317 int new_socket_id, size_t *data_fragment_size, size_t *addrlen)
02318 {
02319 socket_core_t *accepted;
02320 socket_core_t *socket;
02321 tcp_socket_data_t *socket_data;
02322 packet_dimension_t *packet_dimension;
02323 int rc;
02324
02325 assert(local_sockets);
02326 assert(data_fragment_size);
02327 assert(addrlen);
02328
02329
02330 socket = socket_cores_find(local_sockets, socket_id);
02331 if (!socket)
02332 return ENOTSOCK;
02333
02334
02335 socket_data = (tcp_socket_data_t *) socket->specific_data;
02336 assert(socket_data);
02337
02338
02339 if (socket_data->state != TCP_SOCKET_LISTEN)
02340 return EINVAL;
02341
02342 do {
02343 socket_id = dyn_fifo_value(&socket->accepted);
02344 if (socket_id < 0)
02345 return ENOTSOCK;
02346 socket_id *= -1;
02347
02348 accepted = socket_cores_find(local_sockets, socket_id);
02349 if (!accepted)
02350 return ENOTSOCK;
02351
02352
02353 socket_data = (tcp_socket_data_t *) accepted->specific_data;
02354 assert(socket_data);
02355
02356 if (socket_data->state == TCP_SOCKET_ESTABLISHED) {
02357 rc = data_reply(socket_data->addr,
02358 socket_data->addrlen);
02359 if (rc != EOK)
02360 return rc;
02361 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
02362 &tcp_globals.dimensions, socket_data->device_id,
02363 &packet_dimension);
02364 if (rc != EOK)
02365 return rc;
02366 *addrlen = socket_data->addrlen;
02367
02368 *data_fragment_size =
02369 ((packet_dimension->content <
02370 socket_data->data_fragment_size) ?
02371 packet_dimension->content :
02372 socket_data->data_fragment_size);
02373
02374 if (new_socket_id > 0) {
02375 rc = socket_cores_update(local_sockets,
02376 accepted->socket_id, new_socket_id);
02377 if (rc != EOK)
02378 return rc;
02379 accepted->socket_id = new_socket_id;
02380 }
02381 }
02382 dyn_fifo_pop(&socket->accepted);
02383 } while (socket_data->state != TCP_SOCKET_ESTABLISHED);
02384
02385 printf("ret accept %d\n", accepted->socket_id);
02386 return accepted->socket_id;
02387 }
02388
02389 void tcp_free_socket_data(socket_core_t *socket)
02390 {
02391 tcp_socket_data_t *socket_data;
02392
02393 assert(socket);
02394
02395 printf("destroy_socket %d\n", socket->socket_id);
02396
02397
02398 socket_data = (tcp_socket_data_t *) socket->specific_data;
02399 assert(socket_data);
02400
02401
02402 if (socket_data->pseudo_header) {
02403 if (socket_data->headerlen) {
02404 printf("d pseudo\n");
02405 free(socket_data->pseudo_header);
02406 socket_data->headerlen = 0;
02407 }
02408 socket_data->pseudo_header = NULL;
02409 }
02410
02411 socket_data->headerlen = 0;
02412
02413
02414 if (socket_data->addr) {
02415 if (socket_data->addrlen) {
02416 printf("d addr\n");
02417 free(socket_data->addr);
02418 socket_data->addrlen = 0;
02419 }
02420 socket_data->addr = NULL;
02421 }
02422 socket_data->addrlen = 0;
02423 }
02424
02431 int tcp_release_and_return(packet_t *packet, int result)
02432 {
02433 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
02434 return result;
02435 }
02436
02443 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
02444 {
02445 packet_t *packet;
02446 int rc;
02447
02448 while (true) {
02449 switch (IPC_GET_IMETHOD(*icall)) {
02450 case NET_TL_RECEIVED:
02451 rc = packet_translate_remote(tcp_globals.net_phone, &packet,
02452 IPC_GET_PACKET(*icall));
02453 if (rc == EOK)
02454 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
02455 SERVICE_TCP, IPC_GET_ERROR(*icall));
02456
02457 async_answer_0(iid, (sysarg_t) rc);
02458 break;
02459 default:
02460 async_answer_0(iid, (sysarg_t) ENOTSUP);
02461 }
02462
02463 iid = async_get_call(icall);
02464 }
02465 }
02466
02475 int tl_initialize(int net_phone)
02476 {
02477 fibril_rwlock_initialize(&tcp_globals.lock);
02478 fibril_rwlock_write_lock(&tcp_globals.lock);
02479
02480 tcp_globals.net_phone = net_phone;
02481
02482 tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
02483 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
02484 SERVICE_TCP, tcp_receiver);
02485 if (tcp_globals.ip_phone < 0) {
02486 fibril_rwlock_write_unlock(&tcp_globals.lock);
02487 return tcp_globals.ip_phone;
02488 }
02489
02490 int rc = socket_ports_initialize(&tcp_globals.sockets);
02491 if (rc != EOK)
02492 goto out;
02493
02494 rc = packet_dimensions_initialize(&tcp_globals.dimensions);
02495 if (rc != EOK) {
02496 socket_ports_destroy(&tcp_globals.sockets, free);
02497 goto out;
02498 }
02499
02500 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
02501
02502 out:
02503 fibril_rwlock_write_unlock(&tcp_globals.lock);
02504 return rc;
02505 }
02506
02507 int main(int argc, char *argv[])
02508 {
02509 return tl_module_start(SERVICE_TCP);
02510 }
02511