Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/tcp/tcp.c

    rb5eae30 r49bd793b  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2008 Lukas Mejdrech
    33 * All rights reserved.
    44 *
     
    3131 */
    3232
    33 /**
    34  * @file TCP (Transmission Control Protocol) network module
     33/** @file
     34 * TCP module implementation.
     35 * @see tcp.h
    3536 */
    3637
     38#include <assert.h>
    3739#include <async.h>
    38 #include <byteorder.h>
     40#include <fibril_synch.h>
     41#include <malloc.h>
     42/* TODO remove stdio */
     43#include <stdio.h>
    3944#include <errno.h>
    40 #include <io/log.h>
    41 #include <stdio.h>
    42 #include <task.h>
    43 
    44 #include <icmp_remote.h>
     45
     46#include <ipc/services.h>
     47#include <ipc/net.h>
     48#include <ipc/tl.h>
     49#include <ipc/socket.h>
     50
     51#include <net/socket_codes.h>
     52#include <net/ip_protocols.h>
     53#include <net/in.h>
     54#include <net/in6.h>
     55#include <net/inet.h>
     56#include <net/modules.h>
     57
     58#include <adt/dynamic_fifo.h>
     59#include <packet_client.h>
     60#include <packet_remote.h>
     61#include <net_checksum.h>
    4562#include <ip_client.h>
    4663#include <ip_interface.h>
    47 #include <ipc/services.h>
    48 #include <ipc/tl.h>
     64#include <icmp_client.h>
     65#include <icmp_remote.h>
     66#include <net_interface.h>
     67#include <socket_core.h>
    4968#include <tl_common.h>
     69#include <tl_remote.h>
    5070#include <tl_skel.h>
    51 #include <packet_client.h>
    52 #include <packet_remote.h>
    53 
    54 #include "ncsim.h"
    55 #include "pdu.h"
    56 #include "rqueue.h"
    57 #include "sock.h"
    58 #include "std.h"
     71
    5972#include "tcp.h"
    60 #include "test.h"
    61 
    62 #define NAME       "tcp"
    63 
    64 async_sess_t *net_sess;
    65 static async_sess_t *icmp_sess;
    66 async_sess_t *ip_sess;
    67 packet_dimensions_t pkt_dims;
    68 
    69 static void tcp_received_pdu(tcp_pdu_t *pdu);
    70 
    71 /* Pull up packets into a single memory block. */
    72 static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
    73 {
    74         packet_t *npacket;
    75         size_t tot_len;
    76         int length;
    77 
    78         npacket = packet;
    79         tot_len = 0;
    80         do {
    81                 length = packet_get_data_length(packet);
    82                 if (length <= 0)
    83                         return EINVAL;
    84 
    85                 tot_len += length;
    86         } while ((npacket = pq_next(npacket)) != NULL);
    87 
    88         uint8_t *buf;
    89         uint8_t *dp;
    90 
    91         buf = calloc(tot_len, 1);
    92         if (buf == NULL) {
    93                 free(buf);
    94                 return ENOMEM;
    95         }
    96 
    97         npacket = packet;
    98         dp = buf;
    99         do {
    100                 length = packet_get_data_length(packet);
    101                 if (length <= 0) {
    102                         free(buf);
    103                         return EINVAL;
    104                 }
    105 
    106                 memcpy(dp, packet_get_data(packet), length);
    107                 dp += length;
    108         } while ((npacket = pq_next(npacket)) != NULL);
    109 
    110         *data = buf;
    111         *dsize = tot_len;
    112         return EOK;
    113 }
    114 
    115 /** Process packet received from network layer. */
    116 static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
    117     services_t error)
     73#include "tcp_header.h"
     74
     75/** TCP module name. */
     76#define NAME  "tcp"
     77
     78/** The TCP window default value. */
     79#define NET_DEFAULT_TCP_WINDOW          10240
     80
     81/** Initial timeout for new connections. */
     82#define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
     83
     84/** Default timeout for closing. */
     85#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT 2000L
     86
     87/** The initial outgoing sequence number. */
     88#define TCP_INITIAL_SEQUENCE_NUMBER     2999
     89
     90/** Maximum TCP fragment size. */
     91#define MAX_TCP_FRAGMENT_SIZE           65535
     92
     93/** Free ports pool start. */
     94#define TCP_FREE_PORTS_START            1025
     95
     96/** Free ports pool end. */
     97#define TCP_FREE_PORTS_END              65535
     98
     99/** Timeout for connection initialization, SYN sent. */
     100#define TCP_SYN_SENT_TIMEOUT            1000000L
     101
     102/** The maximum number of timeouts in a row before singaling connection lost. */
     103#define TCP_MAX_TIMEOUTS                8
     104
     105/** The number of acknowledgements before retransmit. */
     106#define TCP_FAST_RETRANSMIT_COUNT       3
     107
     108/** Returns a value indicating whether the value is in the interval respecting
     109 * the possible overflow.
     110 *
     111 * The high end and/or the value may overflow, be lower than the low value.
     112 *
     113 * @param[in] lower     The last value before the interval.
     114 * @param[in] value     The value to be checked.
     115 * @param[in] higher_equal The last value in the interval.
     116 */
     117#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \
     118        ((((lower) < (value)) && (((value) <= (higher_equal)) || \
     119        ((higher_equal) < (lower)))) || (((value) <= (higher_equal)) && \
     120        ((higher_equal) < (lower))))
     121
     122/** Type definition of the TCP timeout.
     123 *  @see tcp_timeout
     124 */
     125typedef struct tcp_timeout tcp_timeout_t;
     126
     127/** TCP reply timeout data.
     128 *  Used as a timeouting fibril argument.
     129 *  @see tcp_timeout()
     130 */
     131struct 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
     160static int tcp_release_and_return(packet_t *, int);
     161static void tcp_prepare_operation_header(socket_core_t *, tcp_socket_data_t *,
     162    tcp_header_t *, int synchronize, int);
     163static int tcp_prepare_timeout(int (*)(void *), socket_core_t *,
     164    tcp_socket_data_t *, size_t, tcp_socket_state_t, suseconds_t, int);
     165static void tcp_free_socket_data(socket_core_t *);
     166
     167static int tcp_timeout(void *);
     168
     169static int tcp_release_after_timeout(void *);
     170
     171static int tcp_process_packet(nic_device_id_t, packet_t *, services_t);
     172static int tcp_connect_core(socket_core_t *, socket_cores_t *,
     173    struct sockaddr *, socklen_t);
     174static int tcp_queue_prepare_packet(socket_core_t *, tcp_socket_data_t *,
     175    packet_t *, size_t);
     176static int tcp_queue_packet(socket_core_t *, tcp_socket_data_t *, packet_t *,
     177    size_t);
     178static packet_t *tcp_get_packets_to_send(socket_core_t *, tcp_socket_data_t *);
     179static void tcp_send_packets(nic_device_id_t, packet_t *);
     180
     181static void tcp_process_acknowledgement(socket_core_t *, tcp_socket_data_t *,
     182    tcp_header_t *);
     183static packet_t *tcp_send_prepare_packet(socket_core_t *, tcp_socket_data_t *,
     184    packet_t *, size_t, size_t);
     185static 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);
     189static int tcp_create_notification_packet(packet_t **, socket_core_t *,
     190    tcp_socket_data_t *, int, int);
     191static void tcp_refresh_socket_data(tcp_socket_data_t *);
     192
     193static void tcp_initialize_socket_data(tcp_socket_data_t *);
     194
     195static int tcp_process_listen(socket_core_t *, tcp_socket_data_t *,
     196    tcp_header_t *, packet_t *, struct sockaddr *, struct sockaddr *, size_t);
     197static int tcp_process_syn_sent(socket_core_t *, tcp_socket_data_t *,
     198    tcp_header_t *, packet_t *);
     199static int tcp_process_syn_received(socket_core_t *, tcp_socket_data_t *,
     200    tcp_header_t *, packet_t *);
     201static int tcp_process_established(socket_core_t *, tcp_socket_data_t *,
     202    tcp_header_t *, packet_t *, int, size_t);
     203static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
     204    packet_t *, int, size_t);
     205static void tcp_queue_received_end_of_data(socket_core_t *socket);
     206
     207static int tcp_received_msg(nic_device_id_t, packet_t *, services_t, services_t);
     208static int tcp_process_client_messages(async_sess_t *, ipc_callid_t,
     209    ipc_call_t);
     210
     211static int tcp_listen_message(socket_cores_t *, int, int);
     212static int tcp_connect_message(socket_cores_t *, int, struct sockaddr *,
     213    socklen_t);
     214static int tcp_recvfrom_message(socket_cores_t *, int, int, size_t *);
     215static int tcp_send_message(socket_cores_t *, int, int, size_t *, int);
     216static int tcp_accept_message(socket_cores_t *, int, int, size_t *, size_t *);
     217static int tcp_close_message(socket_cores_t *, int);
     218
     219/** TCP global data. */
     220tcp_globals_t tcp_globals;
     221
     222int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
     223    services_t receiver, services_t error)
    118224{
    119225        int rc;
     226
     227        if (receiver != SERVICE_TCP)
     228                return EREFUSED;
     229
     230        fibril_rwlock_write_lock(&tcp_globals.lock);
     231        rc = tcp_process_packet(device_id, packet, error);
     232        if (rc != EOK)
     233                fibril_rwlock_write_unlock(&tcp_globals.lock);
     234
     235        printf("receive %d \n", rc);
     236
     237        return rc;
     238}
     239
     240int tcp_process_packet(nic_device_id_t device_id, packet_t *packet, services_t error)
     241{
     242        size_t length;
    120243        size_t offset;
    121         int length;
    122         struct sockaddr_in *src_addr;
    123         struct sockaddr_in *dest_addr;
    124         size_t addr_len;
    125 
    126         log_msg(LVL_DEBUG, "tcp_received_msg()");
     244        int result;
     245        tcp_header_t *header;
     246        socket_core_t *socket;
     247        tcp_socket_data_t *socket_data;
     248        packet_t *next_packet;
     249        size_t total_length;
     250        uint32_t checksum;
     251        int fragments;
     252        icmp_type_t type;
     253        icmp_code_t code;
     254        struct sockaddr *src;
     255        struct sockaddr *dest;
     256        size_t addrlen;
     257        int rc;
    127258
    128259        switch (error) {
     
    130261                break;
    131262        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;
    132274        default:
    133                 log_msg(LVL_WARN, "Unsupported service number %u",
    134                     (unsigned)error);
    135                 pq_release_remote(net_sess, packet_get_id(packet));
    136                 return ENOTSUP;
    137         }
    138 
    139         /* Process and trim off IP header */
    140         log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
    141 
    142         rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
    143         if (rc < 0) {
    144                 log_msg(LVL_WARN, "ip_client_process_packet() failed");
    145                 pq_release_remote(net_sess, packet_get_id(packet));
     275                return tcp_release_and_return(packet, ENOTSUP);
     276        }
     277
     278        /* TODO process received ipopts? */
     279        result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
     280        if (result < 0)
     281                return tcp_release_and_return(packet, result);
     282
     283        offset = (size_t) result;
     284
     285        length = packet_get_data_length(packet);
     286        if (length <= 0)
     287                return tcp_release_and_return(packet, EINVAL);
     288
     289        if (length < TCP_HEADER_SIZE + offset)
     290                return tcp_release_and_return(packet, NO_DATA);
     291
     292        /* Trim all but TCP header */
     293        rc = packet_trim(packet, offset, 0);
     294        if (rc != EOK)
     295                return tcp_release_and_return(packet, rc);
     296
     297        /* Get tcp header */
     298        header = (tcp_header_t *) packet_get_data(packet);
     299        if (!header)
     300                return tcp_release_and_return(packet, NO_DATA);
     301
     302#if 0
     303        printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
     304            ntohs(header->destination_port));
     305#endif
     306        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     307        if (result <= 0)
     308                return tcp_release_and_return(packet, result);
     309
     310        addrlen = (size_t) result;
     311
     312        rc = tl_set_address_port(src, addrlen, ntohs(header->source_port));
     313        if (rc != EOK)
     314                return tcp_release_and_return(packet, rc);
     315       
     316        /* Find the destination socket */
     317        socket = socket_port_find(&tcp_globals.sockets,
     318            ntohs(header->destination_port), (uint8_t *) src, addrlen);
     319        if (!socket) {
     320                /* Find the listening destination socket */
     321                socket = socket_port_find(&tcp_globals.sockets,
     322                    ntohs(header->destination_port),
     323                    (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
     324        }
     325
     326        if (!socket) {
     327                if (tl_prepare_icmp_packet(tcp_globals.net_sess,
     328                    tcp_globals.icmp_sess, packet, error) == EOK) {
     329                        icmp_destination_unreachable_msg(tcp_globals.icmp_sess,
     330                            ICMP_PORT_UNREACH, 0, packet);
     331                }
     332                return EADDRNOTAVAIL;
     333        }
     334
     335        printf("socket id %d\n", socket->socket_id);
     336        socket_data = (tcp_socket_data_t *) socket->specific_data;
     337        assert(socket_data);
     338
     339        /* Some data received, clear the timeout counter */
     340        socket_data->timeout_count = 0;
     341
     342        /* Count the received packet fragments */
     343        next_packet = packet;
     344        fragments = 0;
     345        checksum = 0;
     346        total_length = 0;
     347        do {
     348                fragments++;
     349                length = packet_get_data_length(next_packet);
     350                if (length <= 0)
     351                        return tcp_release_and_return(packet, NO_DATA);
     352
     353                total_length += length;
     354
     355                /* Add partial checksum if set */
     356                if (!error) {
     357                        checksum = compute_checksum(checksum,
     358                            packet_get_data(packet),
     359                            packet_get_data_length(packet));
     360                }
     361
     362        } while ((next_packet = pq_next(next_packet)));
     363
     364        fibril_rwlock_write_lock(socket_data->local_lock);
     365
     366        if (error)
     367                goto has_error_service;
     368       
     369        if (socket_data->state == TCP_SOCKET_LISTEN) {
     370                if (socket_data->pseudo_header) {
     371                        free(socket_data->pseudo_header);
     372                        socket_data->pseudo_header = NULL;
     373                        socket_data->headerlen = 0;
     374                }
     375
     376                rc = ip_client_get_pseudo_header(IPPROTO_TCP, src, addrlen,
     377                    dest, addrlen, total_length, &socket_data->pseudo_header,
     378                    &socket_data->headerlen);
     379                if (rc != EOK) {
     380                        fibril_rwlock_write_unlock(socket_data->local_lock);
     381                        return tcp_release_and_return(packet, rc);
     382                }
     383        } else {
     384                rc = ip_client_set_pseudo_header_data_length(
     385                    socket_data->pseudo_header, socket_data->headerlen,
     386                    total_length);
     387                if (rc != EOK) {
     388                        fibril_rwlock_write_unlock(socket_data->local_lock);
     389                        return tcp_release_and_return(packet, rc);
     390                }
     391        }
     392       
     393        checksum = compute_checksum(checksum, socket_data->pseudo_header,
     394            socket_data->headerlen);
     395        if (flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO) {
     396                printf("checksum err %x -> %x\n", header->checksum,
     397                    flip_checksum(compact_checksum(checksum)));
     398                fibril_rwlock_write_unlock(socket_data->local_lock);
     399
     400                rc = tl_prepare_icmp_packet(tcp_globals.net_sess,
     401                    tcp_globals.icmp_sess, packet, error);
     402                if (rc == EOK) {
     403                        /* Checksum error ICMP */
     404                        icmp_parameter_problem_msg(tcp_globals.icmp_sess,
     405                            ICMP_PARAM_POINTER,
     406                            ((size_t) ((void *) &header->checksum)) -
     407                            ((size_t) ((void *) header)), packet);
     408                }
     409
     410                return EINVAL;
     411        }
     412
     413has_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
     453int 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
     774int tcp_queue_received_packet(socket_core_t *socket,
     775    tcp_socket_data_t *socket_data, packet_t *packet, int fragments,
     776    size_t total_length)
     777{
     778        packet_dimension_t *packet_dimension;
     779        int rc;
     780
     781        assert(socket);
     782        assert(socket_data);
     783        assert(socket->specific_data == socket_data);
     784        assert(packet);
     785        assert(fragments >= 1);
     786        assert(socket_data->window > total_length);
     787
     788        /* Queue the received packet */
     789        rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
     790            SOCKET_MAX_RECEIVED_SIZE);
     791        if (rc != EOK)
     792                return tcp_release_and_return(packet, rc);
     793        rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
     794            &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
     795        if (rc != EOK)
     796                return tcp_release_and_return(packet, rc);
     797
     798        /* Decrease the window size */
     799        socket_data->window -= total_length;
     800
     801        /* Notify the destination socket */
     802        async_exch_t *exch = async_exchange_begin(socket->sess);
     803        async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
     804            ((packet_dimension->content < socket_data->data_fragment_size) ?
     805            packet_dimension->content : socket_data->data_fragment_size), 0, 0,
     806            (sysarg_t) fragments);
     807        async_exchange_end(exch);
     808
     809        return EOK;
     810}
     811
     812/** Queue end-of-data marker on the socket.
     813 *
     814 * Next element in the sequence space is FIN. Queue end-of-data marker
     815 * on the socket.
     816 *
     817 * @param socket        Socket
     818 */
     819static 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
     830int 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
     888int 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);
    1461028                return rc;
    1471029        }
    1481030
    149         offset = (size_t)rc;
    150         length = packet_get_data_length(packet);
    151 
    152         if (length < 0 || (size_t)length < offset) {
    153                 log_msg(LVL_WARN, "length=%d, dropping.", length);
    154                 pq_release_remote(net_sess, packet_get_id(packet));
     1031        packet = tcp_get_packets_to_send(socket, socket_data);
     1032        if (!packet) {
     1033                socket_destroy(tcp_globals.net_sess, socket->socket_id,
     1034                    socket_data->local_sockets, &tcp_globals.sockets,
     1035                    tcp_free_socket_data);
    1551036                return EINVAL;
    1561037        }
    1571038
    158         addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
    159             (uint8_t **)&dest_addr);
    160         if (addr_len <= 0) {
    161                 log_msg(LVL_WARN, "Failed to get packet address.");
    162                 pq_release_remote(net_sess, packet_get_id(packet));
     1039        socket_data->state = TCP_SOCKET_SYN_RECEIVED;
     1040        fibril_rwlock_write_unlock(socket_data->local_lock);
     1041
     1042        /* Send the packet */
     1043        tcp_send_packets(socket_data->device_id, packet);
     1044
     1045        return EOK;
     1046}
     1047
     1048int 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
     1117void 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 */
     1213void 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 */
     1230int 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
     1247void tcp_refresh_socket_data(tcp_socket_data_t *socket_data)
     1248{
     1249        assert(socket_data);
     1250
     1251        bzero(socket_data, sizeof(*socket_data));
     1252        socket_data->state = TCP_SOCKET_INITIAL;
     1253        socket_data->device_id = NIC_DEVICE_INVALID_ID;
     1254        socket_data->window = NET_DEFAULT_TCP_WINDOW;
     1255        socket_data->treshold = socket_data->window;
     1256        socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
     1257        socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
     1258        socket_data->acknowledged = socket_data->last_outgoing;
     1259        socket_data->next_outgoing = socket_data->last_outgoing + 1;
     1260        socket_data->expected = socket_data->next_outgoing;
     1261}
     1262
     1263void 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
     1273int tcp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
     1274    ipc_call_t call)
     1275{
     1276        int res;
     1277        socket_cores_t local_sockets;
     1278        struct sockaddr *addr;
     1279        int socket_id;
     1280        size_t addrlen;
     1281        size_t size;
     1282        fibril_rwlock_t lock;
     1283        ipc_call_t answer;
     1284        size_t answer_count;
     1285        tcp_socket_data_t *socket_data;
     1286        socket_core_t *socket;
     1287        packet_dimension_t *packet_dimension;
     1288
     1289        /*
     1290         * Accept the connection
     1291         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     1292         */
     1293        res = EOK;
     1294        answer_count = 0;
     1295
     1296        socket_cores_initialize(&local_sockets);
     1297        fibril_rwlock_initialize(&lock);
     1298
     1299        while (true) {
     1300
     1301                /* Answer the call */
     1302                answer_call(callid, res, &answer, answer_count);
     1303                /* Refresh data */
     1304                refresh_answer(&answer, &answer_count);
     1305                /* Get the next call */
     1306                callid = async_get_call(&call);
     1307               
     1308                if (!IPC_GET_IMETHOD(call)) {
     1309                        res = EHANGUP;
     1310                        break;
     1311                }
     1312
     1313                /* Process the call */
     1314                switch (IPC_GET_IMETHOD(call)) {
     1315                case NET_SOCKET:
     1316                        socket_data =
     1317                            (tcp_socket_data_t *) malloc(sizeof(*socket_data));
     1318                        if (!socket_data) {
     1319                                res = ENOMEM;
     1320                                break;
     1321                        }
     1322                       
     1323                        tcp_initialize_socket_data(socket_data);
     1324                        socket_data->local_lock = &lock;
     1325                        socket_data->local_sockets = &local_sockets;
     1326                        fibril_rwlock_write_lock(&lock);
     1327                        socket_id = SOCKET_GET_SOCKET_ID(call);
     1328                        res = socket_create(&local_sockets, sess,
     1329                            socket_data, &socket_id);
     1330                        SOCKET_SET_SOCKET_ID(answer, socket_id);
     1331                        fibril_rwlock_write_unlock(&lock);
     1332                        if (res != EOK) {
     1333                                free(socket_data);
     1334                                break;
     1335                        }
     1336                        if (tl_get_ip_packet_dimension(tcp_globals.ip_sess,
     1337                            &tcp_globals.dimensions, NIC_DEVICE_INVALID_ID,
     1338                            &packet_dimension) == EOK) {
     1339                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     1340                                    ((packet_dimension->content <
     1341                                    socket_data->data_fragment_size) ?
     1342                                    packet_dimension->content :
     1343                                    socket_data->data_fragment_size));
     1344                        }
     1345//                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_TCP_FRAGMENT_SIZE);
     1346                        SOCKET_SET_HEADER_SIZE(answer, TCP_HEADER_SIZE);
     1347                        answer_count = 3;
     1348                        break;
     1349
     1350                case NET_SOCKET_BIND:
     1351                        res = async_data_write_accept((void **) &addr, false,
     1352                            0, 0, 0, &addrlen);
     1353                        if (res != EOK)
     1354                                break;
     1355                        fibril_rwlock_write_lock(&tcp_globals.lock);
     1356                        fibril_rwlock_write_lock(&lock);
     1357                        res = socket_bind(&local_sockets, &tcp_globals.sockets,
     1358                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     1359                            TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
     1360                            tcp_globals.last_used_port);
     1361                        if (res == EOK) {
     1362                                socket = socket_cores_find(&local_sockets,
     1363                                    SOCKET_GET_SOCKET_ID(call));
     1364                                if (socket) {
     1365                                        socket_data = (tcp_socket_data_t *)
     1366                                            socket->specific_data;
     1367                                        assert(socket_data);
     1368                                        socket_data->state = TCP_SOCKET_LISTEN;
     1369                                }
     1370                        }
     1371                        fibril_rwlock_write_unlock(&lock);
     1372                        fibril_rwlock_write_unlock(&tcp_globals.lock);
     1373                        free(addr);
     1374                        break;
     1375
     1376                case NET_SOCKET_LISTEN:
     1377                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1378//                      fibril_rwlock_write_lock(&tcp_globals.lock);
     1379                        fibril_rwlock_write_lock(&lock);
     1380                        res = tcp_listen_message(&local_sockets,
     1381                            SOCKET_GET_SOCKET_ID(call),
     1382                            SOCKET_GET_BACKLOG(call));
     1383                        fibril_rwlock_write_unlock(&lock);
     1384//                      fibril_rwlock_write_unlock(&tcp_globals.lock);
     1385                        fibril_rwlock_read_unlock(&tcp_globals.lock);
     1386                        break;
     1387
     1388                case NET_SOCKET_CONNECT:
     1389                        res = async_data_write_accept((void **) &addr, false,
     1390                            0, 0, 0, &addrlen);
     1391                        if (res != EOK)
     1392                                break;
     1393                        /*
     1394                         * The global lock may be released in the
     1395                         * tcp_connect_message() function.
     1396                         */
     1397                        fibril_rwlock_write_lock(&tcp_globals.lock);
     1398                        fibril_rwlock_write_lock(&lock);
     1399                        res = tcp_connect_message(&local_sockets,
     1400                            SOCKET_GET_SOCKET_ID(call), addr, addrlen);
     1401                        if (res != EOK) {
     1402                                fibril_rwlock_write_unlock(&lock);
     1403                                fibril_rwlock_write_unlock(&tcp_globals.lock);
     1404                                free(addr);
     1405                        }
     1406                        break;
     1407
     1408                case NET_SOCKET_ACCEPT:
     1409                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1410                        fibril_rwlock_write_lock(&lock);
     1411                        res = tcp_accept_message(&local_sockets,
     1412                            SOCKET_GET_SOCKET_ID(call),
     1413                            SOCKET_GET_NEW_SOCKET_ID(call), &size, &addrlen);
     1414                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     1415                        fibril_rwlock_write_unlock(&lock);
     1416                        fibril_rwlock_read_unlock(&tcp_globals.lock);
     1417                        if (res > 0) {
     1418                                SOCKET_SET_SOCKET_ID(answer, res);
     1419                                SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     1420                                answer_count = 3;
     1421                        }
     1422                        break;
     1423
     1424                case NET_SOCKET_SEND:
     1425                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1426                        fibril_rwlock_write_lock(&lock);
     1427                        res = tcp_send_message(&local_sockets,
     1428                            SOCKET_GET_SOCKET_ID(call),
     1429                            SOCKET_GET_DATA_FRAGMENTS(call), &size,
     1430                            SOCKET_GET_FLAGS(call));
     1431                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     1432                        if (res != EOK) {
     1433                                fibril_rwlock_write_unlock(&lock);
     1434                                fibril_rwlock_read_unlock(&tcp_globals.lock);
     1435                        } else {
     1436                                answer_count = 2;
     1437                        }
     1438                        break;
     1439
     1440                case NET_SOCKET_SENDTO:
     1441                        res = async_data_write_accept((void **) &addr, false,
     1442                            0, 0, 0, &addrlen);
     1443                        if (res != EOK)
     1444                                break;
     1445                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1446                        fibril_rwlock_write_lock(&lock);
     1447                        res = tcp_send_message(&local_sockets,
     1448                            SOCKET_GET_SOCKET_ID(call),
     1449                            SOCKET_GET_DATA_FRAGMENTS(call), &size,
     1450                            SOCKET_GET_FLAGS(call));
     1451                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     1452                        if (res != EOK) {
     1453                                fibril_rwlock_write_unlock(&lock);
     1454                                fibril_rwlock_read_unlock(&tcp_globals.lock);
     1455                        } else {
     1456                                answer_count = 2;
     1457                        }
     1458                        free(addr);
     1459                        break;
     1460
     1461                case NET_SOCKET_RECV:
     1462                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1463                        fibril_rwlock_write_lock(&lock);
     1464                        res = tcp_recvfrom_message(&local_sockets,
     1465                            SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
     1466                            NULL);
     1467                        fibril_rwlock_write_unlock(&lock);
     1468                        fibril_rwlock_read_unlock(&tcp_globals.lock);
     1469                        if (res > 0) {
     1470                                SOCKET_SET_READ_DATA_LENGTH(answer, res);
     1471                                answer_count = 1;
     1472                                res = EOK;
     1473                        }
     1474                        break;
     1475
     1476                case NET_SOCKET_RECVFROM:
     1477                        fibril_rwlock_read_lock(&tcp_globals.lock);
     1478                        fibril_rwlock_write_lock(&lock);
     1479                        res = tcp_recvfrom_message(&local_sockets,
     1480                            SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
     1481                            &addrlen);
     1482                        fibril_rwlock_write_unlock(&lock);
     1483                        fibril_rwlock_read_unlock(&tcp_globals.lock);
     1484                        if (res > 0) {
     1485                                SOCKET_SET_READ_DATA_LENGTH(answer, res);
     1486                                SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     1487                                answer_count = 3;
     1488                                res = EOK;
     1489                        }
     1490                        break;
     1491
     1492                case NET_SOCKET_CLOSE:
     1493                        fibril_rwlock_write_lock(&tcp_globals.lock);
     1494                        fibril_rwlock_write_lock(&lock);
     1495                        res = tcp_close_message(&local_sockets,
     1496                            SOCKET_GET_SOCKET_ID(call));
     1497                        if (res != EOK) {
     1498                                fibril_rwlock_write_unlock(&lock);
     1499                                fibril_rwlock_write_unlock(&tcp_globals.lock);
     1500                        }
     1501                        break;
     1502
     1503                case NET_SOCKET_GETSOCKOPT:
     1504                case NET_SOCKET_SETSOCKOPT:
     1505                default:
     1506                        res = ENOTSUP;
     1507                        break;
     1508                }
     1509        }
     1510
     1511        /* Release the application session */
     1512        async_hangup(sess);
     1513
     1514        printf("release\n");
     1515        /* Release all local sockets */
     1516        socket_cores_release(tcp_globals.net_sess, &local_sockets,
     1517            &tcp_globals.sockets, tcp_free_socket_data);
     1518
     1519        return EOK;
     1520}
     1521
     1522int 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
     1586out:
     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
     1599int 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
     1640void tcp_retransmit_packet(socket_core_t *socket, tcp_socket_data_t *
     1641    socket_data, size_t sequence_number)
     1642{
     1643        packet_t *packet;
     1644        packet_t *copy;
     1645        size_t data_length;
     1646
     1647        assert(socket);
     1648        assert(socket_data);
     1649        assert(socket->specific_data == socket_data);
     1650
     1651        /* Sent packet? */
     1652        packet = pq_find(socket_data->outgoing, sequence_number);
     1653        if (packet) {
     1654                pq_get_order(packet, NULL, &data_length);
     1655                copy = tcp_prepare_copy(socket, socket_data, packet,
     1656                    data_length, sequence_number);
     1657                fibril_rwlock_write_unlock(socket_data->local_lock);
     1658//              printf("r send %d\n", packet_get_id(packet));
     1659                if (copy)
     1660                        tcp_send_packets(socket_data->device_id, copy);
     1661        } else {
     1662                fibril_rwlock_write_unlock(socket_data->local_lock);
     1663        }
     1664}
     1665
     1666int tcp_listen_message(socket_cores_t *local_sockets, int socket_id,
     1667    int backlog)
     1668{
     1669        socket_core_t *socket;
     1670        tcp_socket_data_t *socket_data;
     1671
     1672        assert(local_sockets);
     1673
     1674        if (backlog < 0)
    1631675                return EINVAL;
    164         }
    165 
    166         if (addr_len != sizeof(struct sockaddr_in)) {
    167                 log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
    168                     addr_len, sizeof(struct sockaddr_in));
    169                 pq_release_remote(net_sess, packet_get_id(packet));
    170                 return EINVAL;
    171         }
    172 
    173         rc = packet_trim(packet, offset, 0);
     1676
     1677        /* Find the socket */
     1678        socket = socket_cores_find(local_sockets, socket_id);
     1679        if (!socket)
     1680                return ENOTSOCK;
     1681       
     1682        /* Get the socket specific data */
     1683        socket_data = (tcp_socket_data_t *) socket->specific_data;
     1684        assert(socket_data);
     1685
     1686        /* Set the backlog */
     1687        socket_data->backlog = backlog;
     1688
     1689        return EOK;
     1690}
     1691
     1692int tcp_connect_message(socket_cores_t *local_sockets, int socket_id,
     1693    struct sockaddr *addr, socklen_t addrlen)
     1694{
     1695        socket_core_t *socket;
     1696        int rc;
     1697
     1698        assert(local_sockets);
     1699        assert(addr);
     1700        assert(addrlen > 0);
     1701
     1702        /* Find the socket */
     1703        socket = socket_cores_find(local_sockets, socket_id);
     1704        if (!socket)
     1705                return ENOTSOCK;
     1706       
     1707        rc = tcp_connect_core(socket, local_sockets, addr, addrlen);
    1741708        if (rc != EOK) {
    175                 log_msg(LVL_WARN, "Failed to trim packet.");
    176                 pq_release_remote(net_sess, packet_get_id(packet));
    177                 return rc;
    178         }
    179 
    180         /* Pull up packets into a single memory block, pdu_raw. */
    181         log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
    182         uint8_t *pdu_raw;
    183         size_t pdu_raw_size = 0;
    184 
    185         pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
    186 
    187         /* Split into header and payload. */
    188 
    189         log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
    190 
    191         tcp_pdu_t *pdu;
    192         size_t hdr_size;
    193 
    194         /* XXX Header options */
    195         hdr_size = sizeof(tcp_header_t);
    196 
    197         if (pdu_raw_size < hdr_size) {
    198                 log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
    199                     pdu_raw_size, hdr_size);
    200                 pq_release_remote(net_sess, packet_get_id(packet));
    201                 return EINVAL;
    202         }
    203 
    204         log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
    205             pdu_raw_size, hdr_size);
    206         pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
    207             pdu_raw_size - hdr_size);
    208         if (pdu == NULL) {
    209                 log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
    210                 return ENOMEM;
    211         }
    212 
    213         free(pdu_raw);
    214 
    215         pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
    216         pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
    217         log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
    218             pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
    219 
    220         tcp_received_pdu(pdu);
    221         tcp_pdu_delete(pdu);
    222 
    223         return EOK;
    224 }
    225 
    226 /** Receive packets from network layer. */
    227 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    228 {
     1709                tcp_free_socket_data(socket);
     1710                /* Unbind if bound */
     1711                if (socket->port > 0) {
     1712                        socket_ports_exclude(&tcp_globals.sockets,
     1713                            socket->port, free);
     1714                        socket->port = 0;
     1715                }
     1716        }
     1717        return rc;
     1718}
     1719
     1720int tcp_connect_core(socket_core_t *socket, socket_cores_t *local_sockets,
     1721    struct sockaddr *addr, socklen_t addrlen)
     1722{
     1723        tcp_socket_data_t *socket_data;
    2291724        packet_t *packet;
    2301725        int rc;
    2311726
    232         log_msg(LVL_DEBUG, "tcp_receiver()");
    233 
     1727        assert(socket);
     1728        assert(addr);
     1729        assert(addrlen > 0);
     1730
     1731        /* Get the socket specific data */
     1732        socket_data = (tcp_socket_data_t *) socket->specific_data;
     1733        assert(socket_data);
     1734        assert(socket->specific_data == socket_data);
     1735        if ((socket_data->state != TCP_SOCKET_INITIAL) &&
     1736            ((socket_data->state != TCP_SOCKET_LISTEN) ||
     1737            (socket->port <= 0)))
     1738                return EINVAL;
     1739
     1740        /* Get the destination port */
     1741        rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port);
     1742        if (rc != EOK)
     1743                return rc;
     1744       
     1745        if (socket->port <= 0) {
     1746                /* Try to find a free port */
     1747                rc = socket_bind_free_port(&tcp_globals.sockets, socket,
     1748                    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
     1749                    tcp_globals.last_used_port);
     1750                if (rc != EOK)
     1751                        return rc;
     1752                /* Set the next port as the search starting port number */
     1753                tcp_globals.last_used_port = socket->port;
     1754        }
     1755
     1756        rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP,
     1757            addr, addrlen, &socket_data->device_id,
     1758            &socket_data->pseudo_header, &socket_data->headerlen);
     1759        if (rc != EOK)
     1760                return rc;
     1761
     1762        /* Create the notification packet */
     1763        rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0);
     1764        if (rc != EOK)
     1765                return rc;
     1766
     1767        /* Unlock the globals and wait for an operation */
     1768        fibril_rwlock_write_unlock(&tcp_globals.lock);
     1769
     1770        socket_data->addr = addr;
     1771        socket_data->addrlen = addrlen;
     1772
     1773        /* Send the packet */
     1774
     1775        if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) ||
     1776            ((rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 0,
     1777            TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false)) !=
     1778            EOK)) {
     1779                socket_data->addr = NULL;
     1780                socket_data->addrlen = 0;
     1781                fibril_rwlock_write_lock(&tcp_globals.lock);
     1782        } else {
     1783                packet = tcp_get_packets_to_send(socket, socket_data);
     1784                if (packet) {
     1785                        fibril_mutex_lock(&socket_data->operation.mutex);
     1786                        fibril_rwlock_write_unlock(socket_data->local_lock);
     1787
     1788                        socket_data->state = TCP_SOCKET_SYN_SENT;
     1789
     1790                        /* Send the packet */
     1791                        tcp_send_packets(socket_data->device_id, packet);
     1792
     1793                        /* Wait for a reply */
     1794                        fibril_condvar_wait(&socket_data->operation.condvar,
     1795                            &socket_data->operation.mutex);
     1796                        rc = socket_data->operation.result;
     1797                        if (rc != EOK) {
     1798                                socket_data->addr = NULL;
     1799                                socket_data->addrlen = 0;
     1800                        }
     1801                } else {
     1802                        socket_data->addr = NULL;
     1803                        socket_data->addrlen = 0;
     1804                        rc = EINTR;
     1805                }
     1806        }
     1807
     1808        fibril_mutex_unlock(&socket_data->operation.mutex);
     1809        return rc;
     1810}
     1811
     1812int tcp_queue_prepare_packet(socket_core_t *socket,
     1813    tcp_socket_data_t *socket_data, packet_t *packet, size_t data_length)
     1814{
     1815        tcp_header_t *header;
     1816        int rc;
     1817
     1818        assert(socket);
     1819        assert(socket_data);
     1820        assert(socket->specific_data == socket_data);
     1821
     1822        /* Get TCP header */
     1823        header = (tcp_header_t *) packet_get_data(packet);
     1824        if (!header)
     1825                return NO_DATA;
     1826       
     1827        header->destination_port = htons(socket_data->dest_port);
     1828        header->source_port = htons(socket->port);
     1829        header->sequence_number = htonl(socket_data->next_outgoing);
     1830
     1831        rc = packet_set_addr(packet, NULL, (uint8_t *) socket_data->addr,
     1832            socket_data->addrlen);
     1833        if (rc != EOK)
     1834                return tcp_release_and_return(packet, EINVAL);
     1835
     1836        /* Remember the outgoing FIN */
     1837        if (GET_TCP_HEADER_FINALIZE(header))
     1838                socket_data->fin_outgoing = socket_data->next_outgoing;
     1839       
     1840        return EOK;
     1841}
     1842
     1843int tcp_queue_packet(socket_core_t *socket, tcp_socket_data_t *socket_data,
     1844    packet_t *packet, size_t data_length)
     1845{
     1846        int rc;
     1847
     1848        assert(socket);
     1849        assert(socket_data);
     1850        assert(socket->specific_data == socket_data);
     1851
     1852        rc = tcp_queue_prepare_packet(socket, socket_data, packet, data_length);
     1853        if (rc != EOK)
     1854                return rc;
     1855
     1856        rc = pq_add(&socket_data->outgoing, packet, socket_data->next_outgoing,
     1857            data_length);
     1858        if (rc != EOK)
     1859                return tcp_release_and_return(packet, rc);
     1860
     1861        socket_data->next_outgoing += data_length;
     1862        return EOK;
     1863}
     1864
     1865packet_t *tcp_get_packets_to_send(socket_core_t *socket, tcp_socket_data_t *
     1866    socket_data)
     1867{
     1868        packet_t *packet;
     1869        packet_t *copy;
     1870        packet_t *sending = NULL;
     1871        packet_t *previous = NULL;
     1872        size_t data_length;
     1873        int rc;
     1874
     1875        assert(socket);
     1876        assert(socket_data);
     1877        assert(socket->specific_data == socket_data);
     1878
     1879        packet = pq_find(socket_data->outgoing, socket_data->last_outgoing + 1);
     1880        while (packet) {
     1881                pq_get_order(packet, NULL, &data_length);
     1882
     1883                /*
     1884                 * Send only if fits into the window, respecting the possible
     1885                 * overflow.
     1886                 */
     1887                if (!IS_IN_INTERVAL_OVERFLOW(
     1888                    (uint32_t) socket_data->last_outgoing,
     1889                    (uint32_t) (socket_data->last_outgoing + data_length),
     1890                    (uint32_t) (socket_data->expected + socket_data->treshold)))
     1891                        break;
     1892
     1893                copy = tcp_prepare_copy(socket, socket_data, packet,
     1894                    data_length, socket_data->last_outgoing + 1);
     1895                if (!copy)
     1896                        return sending;
     1897                       
     1898                if (!sending) {
     1899                        sending = copy;
     1900                } else {
     1901                        rc = pq_insert_after(previous, copy);
     1902                        if (rc != EOK) {
     1903                                pq_release_remote(tcp_globals.net_sess,
     1904                                    packet_get_id(copy));
     1905                                return sending;
     1906                        }
     1907                }
     1908
     1909                previous = copy;
     1910                packet = pq_next(packet);
     1911
     1912                /* Overflow occurred? */
     1913                if (!packet &&
     1914                    (socket_data->last_outgoing > socket_data->next_outgoing)) {
     1915                        printf("gpts overflow\n");
     1916                        /* Continue from the beginning */
     1917                        packet = socket_data->outgoing;
     1918                }
     1919                socket_data->last_outgoing += data_length;
     1920        }
     1921
     1922        return sending;
     1923}
     1924
     1925packet_t *tcp_send_prepare_packet(socket_core_t *socket, tcp_socket_data_t *
     1926    socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
     1927{
     1928        tcp_header_t *header;
     1929        uint32_t checksum;
     1930        int rc;
     1931
     1932        assert(socket);
     1933        assert(socket_data);
     1934        assert(socket->specific_data == socket_data);
     1935
     1936        /* Adjust the pseudo header */
     1937        rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header,
     1938            socket_data->headerlen, packet_get_data_length(packet));
     1939        if (rc != EOK) {
     1940                pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     1941                return NULL;
     1942        }
     1943
     1944        /* Get the header */
     1945        header = (tcp_header_t *) packet_get_data(packet);
     1946        if (!header) {
     1947                pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     1948                return NULL;
     1949        }
     1950        assert(ntohl(header->sequence_number) == sequence_number);
     1951
     1952        /* Adjust the header */
     1953        if (socket_data->next_incoming) {
     1954                header->acknowledgement_number =
     1955                    htonl(socket_data->next_incoming);
     1956                SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
     1957        }
     1958        header->window = htons(socket_data->window);
     1959
     1960        /* Checksum */
     1961        header->checksum = 0;
     1962        checksum = compute_checksum(0, socket_data->pseudo_header,
     1963            socket_data->headerlen);
     1964        checksum = compute_checksum(checksum,
     1965            (uint8_t *) packet_get_data(packet),
     1966            packet_get_data_length(packet));
     1967        header->checksum = htons(flip_checksum(compact_checksum(checksum)));
     1968
     1969        /* Prepare the packet */
     1970        rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
     1971        if (rc != EOK) {
     1972                pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     1973                return NULL;
     1974        }
     1975
     1976        rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data,
     1977            sequence_number, socket_data->state, socket_data->timeout, true);
     1978        if (rc != EOK) {
     1979                pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     1980                return NULL;
     1981        }
     1982
     1983        return packet;
     1984}
     1985
     1986packet_t *tcp_prepare_copy(socket_core_t *socket, tcp_socket_data_t *
     1987    socket_data, packet_t *packet, size_t data_length, size_t sequence_number)
     1988{
     1989        packet_t *copy;
     1990
     1991        assert(socket);
     1992        assert(socket_data);
     1993        assert(socket->specific_data == socket_data);
     1994
     1995        /* Make a copy of the packet */
     1996        copy = packet_get_copy(tcp_globals.net_sess, packet);
     1997        if (!copy)
     1998                return NULL;
     1999
     2000        return tcp_send_prepare_packet(socket, socket_data, copy, data_length,
     2001            sequence_number);
     2002}
     2003
     2004void tcp_send_packets(nic_device_id_t device_id, packet_t *packet)
     2005{
     2006        packet_t *next;
     2007
     2008        while (packet) {
     2009                next = pq_detach(packet);
     2010                ip_send_msg(tcp_globals.ip_sess, device_id, packet,
     2011                    SERVICE_TCP, 0);
     2012                packet = next;
     2013        }
     2014}
     2015
     2016void tcp_prepare_operation_header(socket_core_t *socket,
     2017    tcp_socket_data_t *socket_data, tcp_header_t *header, int synchronize,
     2018    int finalize)
     2019{
     2020        assert(socket);
     2021        assert(socket_data);
     2022        assert(socket->specific_data == socket_data);
     2023        assert(header);
     2024
     2025        bzero(header, sizeof(*header));
     2026        header->source_port = htons(socket->port);
     2027        header->source_port = htons(socket_data->dest_port);
     2028        SET_TCP_HEADER_LENGTH(header,
     2029            TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
     2030        SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
     2031        SET_TCP_HEADER_FINALIZE(header, finalize);
     2032}
     2033
     2034int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t),
     2035    socket_core_t *socket, tcp_socket_data_t *socket_data,
     2036    size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout,
     2037    int globals_read_only)
     2038{
     2039        tcp_timeout_t *operation_timeout;
     2040        fid_t fibril;
     2041
     2042        assert(socket);
     2043        assert(socket_data);
     2044        assert(socket->specific_data == socket_data);
     2045
     2046        /* Prepare the timeout with key bundle structure */
     2047        operation_timeout = malloc(sizeof(*operation_timeout) +
     2048            socket->key_length + 1);
     2049        if (!operation_timeout)
     2050                return ENOMEM;
     2051
     2052        bzero(operation_timeout, sizeof(*operation_timeout));
     2053        operation_timeout->globals_read_only = globals_read_only;
     2054        operation_timeout->port = socket->port;
     2055        operation_timeout->local_sockets = socket_data->local_sockets;
     2056        operation_timeout->socket_id = socket->socket_id;
     2057        operation_timeout->timeout = timeout;
     2058        operation_timeout->sequence_number = sequence_number;
     2059        operation_timeout->state = state;
     2060
     2061        /* Copy the key */
     2062        operation_timeout->key = ((uint8_t *) operation_timeout) +
     2063            sizeof(*operation_timeout);
     2064        operation_timeout->key_length = socket->key_length;
     2065        memcpy(operation_timeout->key, socket->key, socket->key_length);
     2066        operation_timeout->key[operation_timeout->key_length] = '\0';
     2067
     2068        /* Prepare the timeouting thread */
     2069        fibril = fibril_create(timeout_function, operation_timeout);
     2070        if (!fibril) {
     2071                free(operation_timeout);
     2072                return ENOMEM;
     2073        }
     2074
     2075//      fibril_mutex_lock(&socket_data->operation.mutex);
     2076        /* Start the timeout fibril */
     2077        fibril_add_ready(fibril);
     2078        //socket_data->state = state;
     2079        return EOK;
     2080}
     2081
     2082int tcp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
     2083    int flags, size_t *addrlen)
     2084{
     2085        socket_core_t *socket;
     2086        tcp_socket_data_t *socket_data;
     2087        int packet_id;
     2088        packet_t *packet;
     2089        size_t length;
     2090        int rc;
     2091
     2092        assert(local_sockets);
     2093
     2094        /* Find the socket */
     2095        socket = socket_cores_find(local_sockets, socket_id);
     2096        if (!socket)
     2097                return ENOTSOCK;
     2098
     2099        /* Get the socket specific data */
     2100        if (!socket->specific_data)
     2101                return NO_DATA;
     2102
     2103        socket_data = (tcp_socket_data_t *) socket->specific_data;
     2104
     2105        /* Check state */
     2106        if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
     2107            (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
     2108                return ENOTCONN;
     2109
     2110        /* Send the source address if desired */
     2111        if (addrlen) {
     2112                rc = data_reply(socket_data->addr, socket_data->addrlen);
     2113                if (rc != EOK)
     2114                        return rc;
     2115                *addrlen = socket_data->addrlen;
     2116        }
     2117
     2118        /* Get the next received packet */
     2119        packet_id = dyn_fifo_value(&socket->received);
     2120        if (packet_id < 0)
     2121                return NO_DATA;
     2122
     2123        rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id);
     2124        if (rc != EOK)
     2125                return rc;
     2126
     2127        /* Reply the packets */
     2128        rc = socket_reply_packets(packet, &length);
     2129        if (rc != EOK)
     2130                return rc;
     2131
     2132        /* Release the packet */
     2133        dyn_fifo_pop(&socket->received);
     2134        pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     2135
     2136        /* Return the total length */
     2137        return (int) length;
     2138}
     2139
     2140int tcp_send_message(socket_cores_t *local_sockets, int socket_id,
     2141    int fragments, size_t *data_fragment_size, int flags)
     2142{
     2143        socket_core_t *socket;
     2144        tcp_socket_data_t *socket_data;
     2145        packet_dimension_t *packet_dimension;
     2146        packet_t *packet;
     2147        size_t total_length;
     2148        tcp_header_t *header;
     2149        int index;
     2150        int result;
     2151        int rc;
     2152
     2153        assert(local_sockets);
     2154        assert(data_fragment_size);
     2155
     2156        /* Find the socket */
     2157        socket = socket_cores_find(local_sockets, socket_id);
     2158        if (!socket)
     2159                return ENOTSOCK;
     2160
     2161        /* Get the socket specific data */
     2162        if (!socket->specific_data)
     2163                return NO_DATA;
     2164
     2165        socket_data = (tcp_socket_data_t *) socket->specific_data;
     2166
     2167        /* Check state */
     2168        if ((socket_data->state != TCP_SOCKET_ESTABLISHED) &&
     2169            (socket_data->state != TCP_SOCKET_CLOSE_WAIT))
     2170                return ENOTCONN;
     2171
     2172        rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
     2173            &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
     2174        if (rc != EOK)
     2175                return rc;
     2176
     2177        *data_fragment_size =
     2178            ((packet_dimension->content < socket_data->data_fragment_size) ?
     2179            packet_dimension->content : socket_data->data_fragment_size);
     2180
     2181        for (index = 0; index < fragments; index++) {
     2182                /* Read the data fragment */
     2183                result = tl_socket_read_packet_data(tcp_globals.net_sess,
     2184                    &packet, TCP_HEADER_SIZE, packet_dimension,
     2185                    socket_data->addr, socket_data->addrlen);
     2186                if (result < 0)
     2187                        return result;
     2188
     2189                total_length = (size_t) result;
     2190
     2191                /* Prefix the TCP header */
     2192                header = PACKET_PREFIX(packet, tcp_header_t);
     2193                if (!header)
     2194                        return tcp_release_and_return(packet, ENOMEM);
     2195
     2196                tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
     2197                rc = tcp_queue_packet(socket, socket_data, packet, total_length);
     2198                if (rc != EOK)
     2199                        return rc;
     2200        }
     2201
     2202        /* Flush packets */
     2203        packet = tcp_get_packets_to_send(socket, socket_data);
     2204        fibril_rwlock_write_unlock(socket_data->local_lock);
     2205        fibril_rwlock_read_unlock(&tcp_globals.lock);
     2206
     2207        if (packet) {
     2208                /* Send the packet */
     2209                tcp_send_packets(socket_data->device_id, packet);
     2210        }
     2211
     2212        return EOK;
     2213}
     2214
     2215int
     2216tcp_close_message(socket_cores_t *local_sockets, int socket_id)
     2217{
     2218        socket_core_t *socket;
     2219        tcp_socket_data_t *socket_data;
     2220        packet_t *packet;
     2221        int rc;
     2222
     2223        /* Find the socket */
     2224        socket = socket_cores_find(local_sockets, socket_id);
     2225        if (!socket)
     2226                return ENOTSOCK;
     2227
     2228        /* Get the socket specific data */
     2229        socket_data = (tcp_socket_data_t *) socket->specific_data;
     2230        assert(socket_data);
     2231
     2232        /* Check state */
     2233        switch (socket_data->state) {
     2234        case TCP_SOCKET_ESTABLISHED:
     2235                socket_data->state = TCP_SOCKET_FIN_WAIT_1;
     2236                break;
     2237
     2238        case TCP_SOCKET_CLOSE_WAIT:
     2239                socket_data->state = TCP_SOCKET_LAST_ACK;
     2240                break;
     2241
     2242//      case TCP_SOCKET_LISTEN:
     2243
     2244        default:
     2245                /* Just destroy */
     2246                rc = socket_destroy(tcp_globals.net_sess, socket_id,
     2247                    local_sockets, &tcp_globals.sockets,
     2248                    tcp_free_socket_data);
     2249                if (rc == EOK) {
     2250                        fibril_rwlock_write_unlock(socket_data->local_lock);
     2251                        fibril_rwlock_write_unlock(&tcp_globals.lock);
     2252                }
     2253                return rc;
     2254        }
     2255
     2256        /*
     2257         * Send FIN.
     2258         * TODO should I wait to complete?
     2259         */
     2260
     2261        /* Create the notification packet */
     2262        rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1);
     2263        if (rc != EOK)
     2264                return rc;
     2265
     2266        /* Send the packet */
     2267        rc = tcp_queue_packet(socket, socket_data, packet, 1);
     2268        if (rc != EOK)
     2269                return rc;
     2270
     2271        /* Flush packets */
     2272        packet = tcp_get_packets_to_send(socket, socket_data);
     2273        fibril_rwlock_write_unlock(socket_data->local_lock);
     2274        fibril_rwlock_write_unlock(&tcp_globals.lock);
     2275
     2276        if (packet) {
     2277                /* Send the packet */
     2278                tcp_send_packets(socket_data->device_id, packet);
     2279        }
     2280
     2281        return EOK;
     2282}
     2283
     2284int tcp_create_notification_packet(packet_t **packet, socket_core_t *socket,
     2285    tcp_socket_data_t *socket_data, int synchronize, int finalize)
     2286{
     2287        packet_dimension_t *packet_dimension;
     2288        tcp_header_t *header;
     2289        int rc;
     2290
     2291        assert(packet);
     2292
     2293        /* Get the device packet dimension */
     2294        rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
     2295            &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
     2296        if (rc != EOK)
     2297                return rc;
     2298
     2299        /* Get a new packet */
     2300        *packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE,
     2301            packet_dimension->addr_len, packet_dimension->prefix,
     2302            packet_dimension->suffix);
     2303       
     2304        if (!*packet)
     2305                return ENOMEM;
     2306
     2307        /* Allocate space in the packet */
     2308        header = PACKET_SUFFIX(*packet, tcp_header_t);
     2309        if (!header)
     2310                tcp_release_and_return(*packet, ENOMEM);
     2311
     2312        tcp_prepare_operation_header(socket, socket_data, header, synchronize,
     2313            finalize);
     2314
     2315        return EOK;
     2316}
     2317
     2318int tcp_accept_message(socket_cores_t *local_sockets, int socket_id,
     2319    int new_socket_id, size_t *data_fragment_size, size_t *addrlen)
     2320{
     2321        socket_core_t *accepted;
     2322        socket_core_t *socket;
     2323        tcp_socket_data_t *socket_data;
     2324        packet_dimension_t *packet_dimension;
     2325        int rc;
     2326
     2327        assert(local_sockets);
     2328        assert(data_fragment_size);
     2329        assert(addrlen);
     2330
     2331        /* Find the socket */
     2332        socket = socket_cores_find(local_sockets, socket_id);
     2333        if (!socket)
     2334                return ENOTSOCK;
     2335
     2336        /* Get the socket specific data */
     2337        socket_data = (tcp_socket_data_t *) socket->specific_data;
     2338        assert(socket_data);
     2339
     2340        /* Check state */
     2341        if (socket_data->state != TCP_SOCKET_LISTEN)
     2342                return EINVAL;
     2343
     2344        do {
     2345                socket_id = dyn_fifo_value(&socket->accepted);
     2346                if (socket_id < 0)
     2347                        return ENOTSOCK;
     2348                socket_id *= -1;
     2349
     2350                accepted = socket_cores_find(local_sockets, socket_id);
     2351                if (!accepted)
     2352                        return ENOTSOCK;
     2353
     2354                /* Get the socket specific data */
     2355                socket_data = (tcp_socket_data_t *) accepted->specific_data;
     2356                assert(socket_data);
     2357                /* TODO can it be in another state? */
     2358                if (socket_data->state == TCP_SOCKET_ESTABLISHED) {
     2359                        rc = data_reply(socket_data->addr,
     2360                            socket_data->addrlen);
     2361                        if (rc != EOK)
     2362                                return rc;
     2363                        rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
     2364                            &tcp_globals.dimensions, socket_data->device_id,
     2365                            &packet_dimension);
     2366                        if (rc != EOK)
     2367                                return rc;
     2368                        *addrlen = socket_data->addrlen;
     2369
     2370                        *data_fragment_size =
     2371                            ((packet_dimension->content <
     2372                            socket_data->data_fragment_size) ?
     2373                            packet_dimension->content :
     2374                            socket_data->data_fragment_size);
     2375       
     2376                        if (new_socket_id > 0) {
     2377                                rc = socket_cores_update(local_sockets,
     2378                                    accepted->socket_id, new_socket_id);
     2379                                if (rc != EOK)
     2380                                        return rc;
     2381                                accepted->socket_id = new_socket_id;
     2382                        }
     2383                }
     2384                dyn_fifo_pop(&socket->accepted);
     2385        } while (socket_data->state != TCP_SOCKET_ESTABLISHED);
     2386
     2387        printf("ret accept %d\n", accepted->socket_id);
     2388        return accepted->socket_id;
     2389}
     2390
     2391void tcp_free_socket_data(socket_core_t *socket)
     2392{
     2393        tcp_socket_data_t *socket_data;
     2394
     2395        assert(socket);
     2396
     2397        printf("destroy_socket %d\n", socket->socket_id);
     2398
     2399        /* Get the socket specific data */
     2400        socket_data = (tcp_socket_data_t *) socket->specific_data;
     2401        assert(socket_data);
     2402
     2403        /* Free the pseudo header */
     2404        if (socket_data->pseudo_header) {
     2405                if (socket_data->headerlen) {
     2406                        printf("d pseudo\n");
     2407                        free(socket_data->pseudo_header);
     2408                        socket_data->headerlen = 0;
     2409                }
     2410                socket_data->pseudo_header = NULL;
     2411        }
     2412
     2413        socket_data->headerlen = 0;
     2414
     2415        /* Free the address */
     2416        if (socket_data->addr) {
     2417                if (socket_data->addrlen) {
     2418                        printf("d addr\n");
     2419                        free(socket_data->addr);
     2420                        socket_data->addrlen = 0;
     2421                }
     2422                socket_data->addr = NULL;
     2423        }
     2424        socket_data->addrlen = 0;
     2425}
     2426
     2427/** Releases the packet and returns the result.
     2428 *
     2429 * @param[in] packet    The packet queue to be released.
     2430 * @param[in] result    The result to be returned.
     2431 * @return              The result parameter.
     2432 */
     2433int tcp_release_and_return(packet_t *packet, int result)
     2434{
     2435        pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
     2436        return result;
     2437}
     2438
     2439/** Process IPC messages from the IP module
     2440 *
     2441 * @param[in]     iid   Message identifier.
     2442 * @param[in,out] icall Message parameters.
     2443 * @param[in]     arg   Local argument.
     2444 *
     2445 */
     2446static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     2447{
     2448        packet_t *packet;
     2449        int rc;
     2450       
    2342451        while (true) {
    2352452                switch (IPC_GET_IMETHOD(*icall)) {
    2362453                case NET_TL_RECEIVED:
    237                         log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
    238                         rc = packet_translate_remote(net_sess, &packet,
     2454                        rc = packet_translate_remote(tcp_globals.net_sess, &packet,
    2392455                            IPC_GET_PACKET(*icall));
    240                         if (rc != EOK) {
    241                                 log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
    242                                 async_answer_0(iid, (sysarg_t)rc);
    243                                 break;
    244                         }
    245                         rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
    246                             IPC_GET_ERROR(*icall));
    247                         async_answer_0(iid, (sysarg_t)rc);
     2456                        if (rc == EOK)
     2457                                rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
     2458                                    SERVICE_TCP, IPC_GET_ERROR(*icall));
     2459                       
     2460                        async_answer_0(iid, (sysarg_t) rc);
    2482461                        break;
    2492462                default:
    250                         log_msg(LVL_DEBUG, "method = %u",
    251                             (unsigned)IPC_GET_IMETHOD(*icall));
    252                         async_answer_0(iid, ENOTSUP);
    253                         break;
    254                 }
    255 
     2463                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     2464                }
     2465               
    2562466                iid = async_get_call(icall);
    2572467        }
    2582468}
    2592469
    260 /** Transmit PDU over network layer. */
    261 void tcp_transmit_pdu(tcp_pdu_t *pdu)
    262 {
    263         struct sockaddr_in dest;
    264         nic_device_id_t dev_id;
    265         void *phdr;
    266         size_t phdr_len;
    267         packet_dimension_t *pkt_dim;
    268         int rc;
    269         packet_t *packet;
    270         void *pkt_data;
    271         size_t pdu_size;
    272 
    273         dest.sin_family = AF_INET;
    274         dest.sin_port = 0; /* not needed */
    275         dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
    276 
    277         /* Find route. Obtained pseudo-header is not used. */
    278         rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
    279             sizeof(dest), &dev_id, &phdr, &phdr_len);
     2470/** Initialize the TCP module.
     2471 *
     2472 * @param[in] sess Network module session.
     2473 *
     2474 * @return EOK on success.
     2475 * @return ENOMEM if there is not enough memory left.
     2476 *
     2477 */
     2478int tl_initialize(async_sess_t *sess)
     2479{
     2480        fibril_rwlock_initialize(&tcp_globals.lock);
     2481        fibril_rwlock_write_lock(&tcp_globals.lock);
     2482       
     2483        tcp_globals.net_sess = sess;
     2484       
     2485        tcp_globals.icmp_sess = icmp_connect_module();
     2486        tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
     2487            SERVICE_TCP, tcp_receiver);
     2488        if (tcp_globals.ip_sess == NULL) {
     2489                fibril_rwlock_write_unlock(&tcp_globals.lock);
     2490                return ENOENT;
     2491        }
     2492       
     2493        int rc = socket_ports_initialize(&tcp_globals.sockets);
     2494        if (rc != EOK)
     2495                goto out;
     2496
     2497        rc = packet_dimensions_initialize(&tcp_globals.dimensions);
    2802498        if (rc != EOK) {
    281                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
    282                 return;
    283         }
    284 
    285         rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
    286         if (rc != EOK) {
    287                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
    288                 return;
    289         }
    290 
    291         pdu_size = pdu->header_size + pdu->text_size;
    292 
    293         packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
    294             pkt_dim->prefix, pkt_dim->suffix);
    295         if (!packet) {
    296                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
    297                 return;
    298         }
    299 
    300         pkt_data = packet_suffix(packet, pdu_size);
    301         if (!pkt_data) {
    302                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
    303                 pq_release_remote(net_sess, packet_get_id(packet));
    304                 return;
    305         }
    306 
    307         rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
    308         if (rc != EOK) {
    309                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
    310                 pq_release_remote(net_sess, packet_get_id(packet));
    311                 return;
    312         }
    313 
    314         rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
    315         if (rc != EOK) {
    316                 log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
    317                 pq_release_remote(net_sess, packet_get_id(packet));
    318                 return;
    319         }
    320 
    321         /* Copy PDU data to packet */
    322         memcpy(pkt_data, pdu->header, pdu->header_size);
    323         memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
    324             pdu->text_size);
    325 
    326         /* Transmit packet. XXX Transfers packet ownership to IP? */
    327         ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
    328 }
    329 
    330 /** Process received PDU. */
    331 static void tcp_received_pdu(tcp_pdu_t *pdu)
    332 {
    333         tcp_segment_t *dseg;
    334         tcp_sockpair_t rident;
    335 
    336         log_msg(LVL_DEBUG, "tcp_received_pdu()");
    337 
    338         if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
    339                 log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
    340                 return;
    341         }
    342 
    343         /* Insert decoded segment into rqueue */
    344         tcp_rqueue_insert_seg(&rident, dseg);
    345 }
    346 
    347 /* Called from libnet */
    348 void tl_connection(void)
    349 {
    350         log_msg(LVL_DEBUG, "tl_connection()");
    351 }
    352 
    353 /* Called from libnet */
    354 int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    355     size_t *answer_count)
    356 {
    357         async_sess_t *callback;
    358 
    359         log_msg(LVL_DEBUG, "tl_message()");
    360 
    361         *answer_count = 0;
    362         callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
    363         if (callback)
    364                 return tcp_sock_connection(callback, callid, *call);
    365 
    366         return ENOTSUP;
    367 }
    368 
    369 /* Called from libnet */
    370 int tl_initialize(async_sess_t *sess)
    371 {
    372         int rc;
    373 
    374         net_sess = sess;
    375         icmp_sess = icmp_connect_module();
    376 
    377         log_msg(LVL_DEBUG, "tl_initialize()");
    378 
    379         tcp_sock_init();
    380 
    381         ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
    382             tcp_receiver);
    383         if (ip_sess == NULL)
    384                 return ENOENT;
    385 
    386         rc = packet_dimensions_initialize(&pkt_dims);
    387         if (rc != EOK)
    388                 return rc;
    389 
    390         return EOK;
    391 }
    392 
    393 int main(int argc, char **argv)
    394 {
    395         int rc;
    396 
    397         printf(NAME ": TCP (Transmission Control Protocol) network module\n");
    398 
    399         rc = log_init(NAME, LVL_ERROR);
    400         if (rc != EOK) {
    401                 printf(NAME ": Failed to initialize log.\n");
    402                 return 1;
    403         }
    404 
    405 //      printf(NAME ": Accepting connections\n");
    406 //      task_retval(0);
    407 
    408         tcp_rqueue_init();
    409         tcp_rqueue_thread_start();
    410 
    411         tcp_ncsim_init();
    412         tcp_ncsim_thread_start();
    413 
    414         if (0) tcp_test();
    415 /*
    416         async_manager();
    417 */
    418         tl_module_start(SERVICE_TCP);
    419 
    420         /* Not reached */
    421         return 0;
    422 }
    423 
    424 /**
    425  * @}
     2499                socket_ports_destroy(&tcp_globals.sockets, free);
     2500                goto out;
     2501        }
     2502
     2503        tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
     2504
     2505out:
     2506        fibril_rwlock_write_unlock(&tcp_globals.lock);
     2507        return rc;
     2508}
     2509
     2510int main(int argc, char *argv[])
     2511{
     2512        return tl_module_start(SERVICE_TCP);
     2513}
     2514
     2515/** @}
    4262516 */
Note: See TracChangeset for help on using the changeset viewer.