Changeset b7068da in mainline for uspace/srv/net/tl/tcp/tcp.c


Ignore:
Timestamp:
2012-02-09T20:35:12Z (12 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
591762c6
Parents:
7cede12c (diff), 3d4750f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

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