Ignore:
File:
1 edited

Legend:

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

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