Changeset c5808b41 in mainline


Ignore:
Timestamp:
2011-09-18T17:51:58Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4c55a64
Parents:
45a9cf4
Message:

Remove old TCP module and replace it with a new one (WIP).

Location:
uspace/srv/net/tl/tcp
Files:
20 added
2 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/tcp/Makefile

    r45a9cf4 rc5808b41  
    11#
    2 # Copyright (c) 2005 Martin Decky
    3 # Copyright (c) 2007 Jakub Jermar
     2# Copyright (c) 2011 Jiri Svoboda
    43# All rights reserved.
    54#
     
    3433
    3534SOURCES = \
    36         tcp.c
     35        conn.c \
     36        header.c \
     37        iqueue.c \
     38        rqueue.c \
     39        segment.c \
     40        seq_no.c \
     41        state.c \
     42        tcp.c \
     43        test.c \
     44        tqueue.c
    3745
    3846include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/tcp/tcp.c

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