tcp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Lukas Mejdrech
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include <assert.h>
00039 #include <async.h>
00040 #include <fibril_synch.h>
00041 #include <malloc.h>
00042 /* TODO remove stdio */
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 /* static */ 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                 /* Process error */
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         /* TODO process received ipopts? */
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         /* Trim all but TCP header */
00292         rc = packet_trim(packet, offset, 0);
00293         if (rc != EOK)
00294                 return tcp_release_and_return(packet, rc);
00295 
00296         /* Get tcp header */
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         /* Find the destination socket */
00316         socket = socket_port_find(&tcp_globals.sockets,
00317             ntohs(header->destination_port), (uint8_t *) src, addrlen);
00318         if (!socket) {
00319                 /* Find the listening destination socket */
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         /* Some data received, clear the timeout counter */
00339         socket_data->timeout_count = 0;
00340 
00341         /* Count the received packet fragments */
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                 /* Add partial checksum if set */
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                         /* Checksum error ICMP */
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         /* TODO error reporting/handling */
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                 /* ack changing the state to FIN_WAIT_2 gets processed later */
00430         case TCP_SOCKET_FIN_WAIT_2:
00431                 /* fin changing state to LAST_ACK gets processed later */
00432         case TCP_SOCKET_LAST_ACK:
00433                 /* ack releasing the socket get processed later */
00434         case TCP_SOCKET_CLOSING:
00435                 /* ack releasing the socket gets processed later */
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         /* Trim begining if containing expected data */
00484         if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
00485             socket_data->next_incoming, new_sequence_number + total_length)) {
00486 
00487                 /* Get the acknowledged offset */
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                 /* Trim the acknowledged data */
00501                 while (length <= offset) {
00502                         /* Release the acknowledged packets */
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         /* Release if overflowing the window */
00521 /*
00522         if (IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming +
00523             socket_data->window, new_sequence_number, new_sequence_number +
00524             total_length)) {
00525                 return tcp_release_and_return(packet, EOVERFLOW);
00526         }
00527 
00528         // trim end if overflowing the window
00529         if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number,
00530             socket_data->next_incoming + socket_data->window,
00531             new_sequence_number + total_length)) {
00532                 // get the allowed data length
00533                 if (socket_data->next_incoming + socket_data->window <
00534                     new_sequence_number) {
00535                         offset = new_sequence_number -
00536                             socket_data->next_incoming + socket_data->window;
00537                 } else {
00538                         offset = socket_data->next_incoming +
00539                             socket_data->window - new_sequence_number;
00540                 }
00541                 next_packet = packet;
00542                 // trim the overflowing data
00543                 while (next_packet && (offset > 0)) {
00544                         length = packet_get_data_length(packet);
00545                         if (length <= offset)
00546                                 next_packet = pq_next(next_packet);
00547                         else {
00548                                 rc = packet_trim(next_packet, 0,
00549                                     length - offset));
00550                                 if (rc != EOK)
00551                                         return tcp_release_and_return(packet,
00552                                             rc);
00553                         }
00554                         offset -= length;
00555                         total_length -= length - offset;
00556                 }
00557                 // release the overflowing packets
00558                 next_packet = pq_next(next_packet);
00559                 if (next_packet) {
00560                         tmp_packet = next_packet;
00561                         next_packet = pq_next(next_packet);
00562                         pq_insert_after(tmp_packet, next_packet);
00563                         pq_release_remote(tcp_globals.net_phone,
00564                             packet_get_id(tmp_packet));
00565                 }
00566                 assert(new_sequence_number + total_length ==
00567                     socket_data->next_incoming + socket_data->window);
00568         }
00569 */
00570         /* The expected one arrived? */
00571         if (new_sequence_number == socket_data->next_incoming) {
00572                 printf("expected\n");
00573                 /* Process acknowledgement */
00574                 tcp_process_acknowledgement(socket, socket_data, header);
00575 
00576                 /* Remove the header */
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                                 /* Remove the corrupted packet */
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                                 /* Move to the next */
00610                                 packet = pq_next(packet);
00611                                 /* Coninual data? */
00612                         } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming,
00613                             sequence_number, socket_data->next_incoming)) {
00614                                 /* Detach the packet */
00615                                 next_packet = pq_detach(packet);
00616                                 if (packet == socket_data->incoming)
00617                                         socket_data->incoming = next_packet;
00618                                 /* Get data length */
00619                                 length = packet_get_data_length(packet);
00620                                 new_sequence_number = sequence_number + length;
00621                                 if (length <= 0) {
00622                                         /* Remove the empty packet */
00623                                         pq_release_remote(tcp_globals.net_phone,
00624                                             packet_get_id(packet));
00625                                         packet = next_packet;
00626                                         continue;
00627                                 }
00628                                 /* Exactly following */
00629                                 if (sequence_number ==
00630                                     socket_data->next_incoming) {
00631                                         /* Queue received data */
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                                         /* At least partly following data? */
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                                                 /* Queue received data */
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                                 /* Remove the duplicit or corrupted packet */
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                 /* Process acknowledgement */
00683                 tcp_process_acknowledgement(socket, socket_data, header);
00684 
00685                 /* Remove the header */
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                         /* Remove the corrupted packets */
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                 /* Release duplicite or restricted */
00724                 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
00725                 forced_ack = true;
00726         }
00727 
00728         /* If next in sequence is an incoming FIN */
00729         if (socket_data->next_incoming == socket_data->fin_incoming) {
00730                 /* Advance sequence number */
00731                 socket_data->next_incoming += 1;
00732 
00733                 /* Handle FIN */
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                         /* Queue end-of-data marker on the socket. */
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                 /* Create the notification packet */
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         /* Send the packet */
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         /* Queue the received packet */
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         /* Decrease the window size */
00798         socket_data->window -= total_length;
00799 
00800         /* Notify the destination socket */
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         /* Notify the destination socket */
00822         async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
00823             (sysarg_t) socket->socket_id,
00824             0, 0, 0,
00825             (sysarg_t) 0 /* 0 fragments == no more data */);
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         /* Process acknowledgement */
00844         tcp_process_acknowledgement(socket, socket_data, header);
00845 
00846         socket_data->next_incoming = ntohl(header->sequence_number) + 1;
00847 
00848         /* Release additional packets */
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         /* Trim if longer than the header */
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                         /* Send the packet */
00874                         tcp_send_packets(socket_data->device_id, packet);
00875                         /* Signal the result */
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         /* Create a socket */
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         /* Find the destination socket */
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                 /* A shadow may remain until app hangs up */
00962                 return tcp_release_and_return(packet, EOK /*ENOTSOCK*/);
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                 /* Where is the socket?!? */
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 //      rc = socket_bind_free_port(&tcp_globals.sockets, socket,
00986 //          TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
00987 //          tcp_globals.last_used_port);
00988 //      tcp_globals.last_used_port = socket->port;
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         /* Release additional packets */
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         /* Trim if longer than the header */
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         /* Send the packet */
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         /* Process acknowledgement */
01063         tcp_process_acknowledgement(socket, socket_data, header);
01064 
01065         socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */
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                 /* Queue the received packet */
01076                 rc = dyn_fifo_push(&listening_socket->accepted,
01077                     (-1 * socket->socket_id), listening_socket_data->backlog);
01078                 if (rc == EOK) {
01079                         /* Notify the destination socket */
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         /* Send FIN */
01090         socket_data->state = TCP_SOCKET_FIN_WAIT_1;
01091 
01092         /* Create the notification packet */
01093         rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
01094         if (rc != EOK)
01095                 return rc;
01096 
01097         /* Send the packet */
01098         rc = tcp_queue_packet(socket, socket_data, packet, 1);
01099         if (rc != EOK)
01100                 return rc;
01101 
01102         /* Flush packets */
01103         packet = tcp_get_packets_to_send(socket, socket_data);
01104         fibril_rwlock_write_unlock(socket_data->local_lock);
01105         if (packet) {
01106                 /* Send the packet */
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         /* If more data acknowledged */
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                                  * FIN acknowledged - release the socket in
01146                                  * another fibril.
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                 /* Update the treshold if higher than set */
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                 /* Set new expected sequence number */
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                                 /* Add to acknowledged or release */
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                 /* Release acknowledged */
01187                 if (acknowledged) {
01188                         pq_release_remote(tcp_globals.net_phone,
01189                             packet_get_id(acknowledged));
01190                 }
01191                 return;
01192                 /* If the same as the previous time */
01193         }
01194 
01195         if (number == socket_data->expected) {
01196                 /* Increase the counter */
01197                 socket_data->expected_count++;
01198                 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) {
01199                         socket_data->expected_count = 1;
01200                         /* TODO retransmit lock */
01201                         //tcp_retransmit_packet(socket, socket_data, number);
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          * Accept the connection
01287          *  - Answer the first IPC_M_CONNECT_ME_TO call.
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                 /* Answer the call */
01298                 answer_call(callid, res, &answer, answer_count);
01299                 /* Refresh data */
01300                 refresh_answer(&answer, &answer_count);
01301                 /* Get the next call */
01302                 callid = async_get_call(&call);
01303 
01304                 /* Process the call */
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 //                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
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 //                      fibril_rwlock_write_lock(&tcp_globals.lock);
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 //                      fibril_rwlock_write_unlock(&tcp_globals.lock);
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                          * The global lock may be released in the
01391                          * tcp_connect_message() function.
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         /* Release the application phone */
01508         async_hangup(app_phone);
01509 
01510         printf("release\n");
01511         /* Release all local sockets */
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         /* Sleep the given timeout */
01528         async_usleep(timeout->timeout);
01529         /* Lock the globals */
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         /* Find the pending operation socket */
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                 /* Increase the timeout counter */
01549                 socket_data->timeout_count++;
01550                 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) {
01551                         /* TODO release as connection lost */
01552                         //tcp_refresh_socket_data(socket_data);
01553                         fibril_rwlock_write_unlock(socket_data->local_lock);
01554                 } else {
01555                         /* Retransmit */
01556 //                      tcp_retransmit_packet(socket,
01557 //                          socket_data, timeout->sequence_number);
01558                         fibril_rwlock_write_unlock(socket_data->local_lock);
01559                 }
01560         } else {
01561                 fibril_mutex_lock(&socket_data->operation.mutex);
01562                 /* Set the timeout operation result if state not changed */
01563                 if (socket_data->state == timeout->state) {
01564                         socket_data->operation.result = ETIMEOUT;
01565 
01566                         /* Notify the main fibril */
01567                         fibril_condvar_signal(&socket_data->operation.condvar);
01568 
01569                         /* Keep the global write lock */
01570                         keep_write_lock = true;
01571                 } else {
01572                         /*
01573                          * Operation is ok, do nothing.
01574                          * Unlocking from now on, so the unlocking
01575                          * order does not matter.
01576                          */
01577                         fibril_rwlock_write_unlock(socket_data->local_lock);
01578                 }
01579                 fibril_mutex_unlock(&socket_data->operation.mutex);
01580         }
01581 
01582 out:
01583         /* Unlock only if no socket */
01584         if (timeout->globals_read_only)
01585                 fibril_rwlock_read_unlock(&tcp_globals.lock);
01586         else if (!keep_write_lock)
01587                 /* Release if not desired */
01588                 fibril_rwlock_write_unlock(&tcp_globals.lock);
01589         
01590         /* Release the timeout structure */
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         /* Sleep the given timeout */
01605         async_usleep(timeout->timeout);
01606 
01607         /* Lock the globals */
01608         fibril_rwlock_write_lock(&tcp_globals.lock);
01609 
01610         /* Find the pending operation socket */
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         /* Unlock the globals */
01628         fibril_rwlock_write_unlock(&tcp_globals.lock);
01629 
01630         /* Release the timeout structure */
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         /* Sent packet? */
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 //              printf("r send %d\n", packet_get_id(packet));
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         /* Find the socket */
01675         socket = socket_cores_find(local_sockets, socket_id);
01676         if (!socket) 
01677                 return ENOTSOCK;
01678         
01679         /* Get the socket specific data */
01680         socket_data = (tcp_socket_data_t *) socket->specific_data;
01681         assert(socket_data);
01682 
01683         /* Set the backlog */
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         /* Find the socket */
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                 /* Unbind if bound */
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         /* Get the socket specific data */
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         /* Get the destination port */
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                 /* Try to find a free port */
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                 /* Set the next port as the search starting port number */
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         /* Create the notification packet */
01760         rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0);
01761         if (rc != EOK)
01762                 return rc;
01763 
01764         /* Unlock the globals and wait for an operation */
01765         fibril_rwlock_write_unlock(&tcp_globals.lock);
01766 
01767         socket_data->addr = addr;
01768         socket_data->addrlen = addrlen;
01769 
01770         /* Send the packet */
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                         /* Send the packet */
01788                         printf("connecting %d\n", packet_get_id(packet));
01789                         tcp_send_packets(socket_data->device_id, packet);
01790 
01791                         /* Wait for a reply */
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         /* Get TCP header */
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         /* Remember the outgoing FIN */
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                  * Send only if fits into the window, respecting the possible
01883                  * overflow.
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                 /* Overflow occurred? */
01911                 if (!packet &&
01912                     (socket_data->last_outgoing > socket_data->next_outgoing)) {
01913                         printf("gpts overflow\n");
01914                         /* Continue from the beginning */
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         /* Adjust the pseudo header */
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         /* Get the header */
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         /* Adjust the header */
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         /* Checksum */
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         /* Prepare the packet */
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         /* Make a copy of the packet */
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         /* Prepare the timeout with key bundle structure */
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         /* Copy the key */
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         /* Prepare the timeouting thread */
02067         fibril = fibril_create(timeout_function, operation_timeout);
02068         if (!fibril) {
02069                 free(operation_timeout);
02070                 return ENOMEM;
02071         }
02072 
02073 //      fibril_mutex_lock(&socket_data->operation.mutex);
02074         /* Start the timeout fibril */
02075         fibril_add_ready(fibril);
02076         //socket_data->state = state;
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         /* Find the socket */
02093         socket = socket_cores_find(local_sockets, socket_id);
02094         if (!socket)
02095                 return ENOTSOCK;
02096 
02097         /* Get the socket specific data */
02098         if (!socket->specific_data)
02099                 return NO_DATA;
02100 
02101         socket_data = (tcp_socket_data_t *) socket->specific_data;
02102 
02103         /* Check state */
02104         if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
02105             (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
02106                 return ENOTCONN;
02107 
02108         /* Send the source address if desired */
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         /* Get the next received packet */
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         /* Reply the packets */
02126         rc = socket_reply_packets(packet, &length);
02127         if (rc != EOK)
02128                 return rc;
02129 
02130         /* Release the packet */
02131         dyn_fifo_pop(&socket->received);
02132         pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
02133 
02134         /* Return the total length */
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         /* Find the socket */
02155         socket = socket_cores_find(local_sockets, socket_id);
02156         if (!socket)
02157                 return ENOTSOCK;
02158 
02159         /* Get the socket specific data */
02160         if (!socket->specific_data)
02161                 return NO_DATA;
02162 
02163         socket_data = (tcp_socket_data_t *) socket->specific_data;
02164 
02165         /* Check state */
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                 /* Read the data fragment */
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                 /* Prefix the TCP header */
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         /* Flush packets */
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                 /* Send the packet */
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         /* Find the socket */
02222         socket = socket_cores_find(local_sockets, socket_id);
02223         if (!socket)
02224                 return ENOTSOCK;
02225 
02226         /* Get the socket specific data */
02227         socket_data = (tcp_socket_data_t *) socket->specific_data;
02228         assert(socket_data);
02229 
02230         /* Check state */
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 //      case TCP_SOCKET_LISTEN:
02241 
02242         default:
02243                 /* Just destroy */
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          * Send FIN.
02256          * TODO should I wait to complete?
02257          */
02258 
02259         /* Create the notification packet */
02260         rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
02261         if (rc != EOK)
02262                 return rc;
02263 
02264         /* Send the packet */
02265         rc = tcp_queue_packet(socket, socket_data, packet, 1);
02266         if (rc != EOK)
02267                 return rc;
02268 
02269         /* Flush packets */
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                 /* Send the packet */
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         /* Get the device packet dimension */
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         /* Get a new packet */
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         /* Allocate space in the packet */
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         /* Find the socket */
02330         socket = socket_cores_find(local_sockets, socket_id);
02331         if (!socket)
02332                 return ENOTSOCK;
02333 
02334         /* Get the socket specific data */
02335         socket_data = (tcp_socket_data_t *) socket->specific_data;
02336         assert(socket_data);
02337 
02338         /* Check state */
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                 /* Get the socket specific data */
02353                 socket_data = (tcp_socket_data_t *) accepted->specific_data;
02354                 assert(socket_data);
02355                 /* TODO can it be in another state? */
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         /* Get the socket specific data */
02398         socket_data = (tcp_socket_data_t *) socket->specific_data;
02399         assert(socket_data);
02400 
02401         /* Free the pseudo header */
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         /* Free the address */
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 

Generated on Thu Jun 2 07:45:50 2011 for HelenOS/USB by  doxygen 1.4.7