Changes in / [4c67e52:899f1a9] in mainline


Ignore:
Files:
29 added
1 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r4c67e52 r899f1a9  
    174174        $(USPACE_PATH)/app/nettest1/nettest1 \
    175175        $(USPACE_PATH)/app/nettest2/nettest2 \
     176        $(USPACE_PATH)/app/nettest3/nettest3 \
    176177        $(USPACE_PATH)/app/netecho/netecho \
    177178        $(USPACE_PATH)/app/ping/ping \
  • uspace/Makefile

    r4c67e52 r899f1a9  
    6464        app/nettest1 \
    6565        app/nettest2 \
     66        app/nettest3 \
    6667        app/ping \
    6768        app/websrv \
  • uspace/app/netecho/netecho.c

    r4c67e52 r899f1a9  
    241241                /* Accept a socket if a stream socket is used */
    242242                addrlen = sizeof(address_buf);
     243                if (verbose)
     244                        printf("accept()\n");
    243245                socket_id = accept(listening_id, (void *) address_buf, &addrlen);
    244246                if (socket_id <= 0) {
     
    258260
    259261                /* Receive a message to echo */
     262                if (verbose)
     263                        printf("recvfrom()\n");
    260264                rcv_size = recvfrom(socket_id, data, size, 0, address,
    261265                    &addrlen);
     
    297301
    298302                        /* Answer the request either with the static reply or the original data */
    299                         rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
    300                         if (rc != EOK)
    301                                 socket_print_error(stderr, rc, "Socket send: ", "\n");
     303                        if (type == SOCK_STREAM) {
     304                                if (verbose)
     305                                        printf("send()\n");
     306                                rc = send(socket_id, reply ? reply : data, reply ? reply_length : length, 0);
     307                                if (rc != EOK)
     308                                        socket_print_error(stderr, rc, "Socket send: ", "\n");
     309                        } else {
     310                                if (verbose)
     311                                        printf("sendto()\n");
     312                                rc = sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen);
     313                                if (rc != EOK)
     314                                        socket_print_error(stderr, rc, "Socket send: ", "\n");
     315                        }
    302316                }
    303317
  • uspace/app/websrv/websrv.c

    r4c67e52 r899f1a9  
    11/*
    2  * Copyright (c) 2010 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/**
    33  * @file (Less-than-skeleton) web server.
     33 * @file Skeletal web server.
    3434 */
    3535
     36#include <bool.h>
     37#include <errno.h>
    3638#include <stdio.h>
     39#include <sys/types.h>
     40#include <sys/stat.h>
     41#include <stdlib.h>
     42#include <fcntl.h>
    3743
    3844#include <net/in.h>
     
    4450#define PORT_NUMBER 8080
    4551
     52#define WEB_ROOT "/data/web"
     53
    4654/** Buffer for receiving the request. */
    4755#define BUFFER_SIZE 1024
    48 static char buf[BUFFER_SIZE];
     56static char rbuf[BUFFER_SIZE];
     57static size_t rbuf_out, rbuf_in;
     58
     59static char lbuf[BUFFER_SIZE + 1];
     60static size_t lbuf_used;
     61
     62static char fbuf[BUFFER_SIZE];
    4963
    5064/** Response to send to client. */
    51 static const char *response_msg =
     65static const char *ok_msg =
    5266    "HTTP/1.0 200 OK\r\n"
    53     "\r\n"
    54     "<h1>Hello from HelenOS!</h1>\r\n";
     67    "\r\n";
     68
     69/** Receive one character (with buffering) */
     70static int recv_char(int fd, char *c)
     71{
     72        ssize_t rc;
     73
     74        if (rbuf_out == rbuf_in) {
     75                rbuf_out = 0;
     76                rbuf_in = 0;
     77
     78                rc = recv(fd, rbuf, BUFFER_SIZE, 0);
     79                if (rc <= 0) {
     80                        printf("recv() failed (%zd)\n", rc);
     81                        return rc;
     82                }
     83
     84                rbuf_in = rc;
     85        }
     86
     87        *c = rbuf[rbuf_out++];
     88        return EOK;
     89}
     90
     91/** Receive one line with length limit. */
     92static int recv_line(int fd)
     93{
     94        char c, prev;
     95        int rc;
     96        char *bp;
     97
     98        bp = lbuf; c = '\0';
     99        while (bp < lbuf + BUFFER_SIZE) {
     100                prev = c;
     101                rc = recv_char(fd, &c);
     102                if (rc != EOK)
     103                        return rc;
     104
     105                *bp++ = c;
     106                if (prev == '\r' && c == '\n')
     107                        break;
     108        }
     109
     110        lbuf_used = bp - lbuf;
     111        *bp = '\0';
     112
     113        if (bp == lbuf + BUFFER_SIZE)
     114                return ELIMIT;
     115
     116        return EOK;
     117}
     118
     119static bool uri_is_valid(char *uri)
     120{
     121        char *cp;
     122        char c;
     123
     124        if (uri[0] != '/')
     125                return false;
     126        if (uri[1] == '.')
     127                return false;
     128
     129        cp = uri + 1;
     130        while (*cp != '\0') {
     131                c = *cp++;
     132                if (c == '/')
     133                        return false;
     134        }
     135
     136        return true;
     137}
     138
     139static int send_response(int conn_sd, const char *msg)
     140{
     141        size_t response_size;
     142        ssize_t rc;
     143
     144        response_size = str_size(msg);
     145
     146        /* Send a canned response. */
     147        printf("Send response...\n");
     148        rc = send(conn_sd, (void *) msg, response_size, 0);
     149        if (rc < 0) {
     150                printf("send() failed.\n");
     151                return rc;
     152        }
     153
     154        return EOK;
     155}
     156
     157static int uri_get(const char *uri, int conn_sd)
     158{
     159        int rc;
     160        char *fname;
     161        int fd;
     162        ssize_t nr;
     163
     164        if (str_cmp(uri, "/") == 0)
     165                uri = "/index.htm";
     166
     167        rc = asprintf(&fname, "%s%s", WEB_ROOT, uri);
     168        if (rc < 0)
     169                return ENOMEM;
     170
     171        fd = open(fname, O_RDONLY);
     172        if (fd < 0) {
     173                printf("File '%s' not found.\n", fname);
     174                free(fname);
     175                return ENOENT;
     176        }
     177
     178        free(fname);
     179
     180        rc = send_response(conn_sd, ok_msg);
     181        if (rc != EOK)
     182                return rc;
     183
     184        while (true) {
     185                nr = read(fd, fbuf, BUFFER_SIZE);
     186                if (nr == 0)
     187                        break;
     188
     189                if (nr < 0) {
     190                        close(fd);
     191                        return EIO;
     192                }
     193
     194                rc = send(conn_sd, fbuf, nr, 0);
     195                if (rc < 0) {
     196                        printf("send() failed\n");
     197                        close(fd);
     198                        return rc;
     199                }
     200        }
     201
     202        close(fd);
     203
     204        return EOK;
     205}
     206
     207static int req_process(int conn_sd)
     208{
     209        int rc;
     210        char *uri, *end_uri;
     211
     212        rc = recv_line(conn_sd);
     213        if (rc != EOK) {
     214                printf("recv_line() failed\n");
     215                return rc;
     216        }
     217
     218        printf("%s", lbuf);
     219
     220        if (str_lcmp(lbuf, "GET ", 4) != 0) {
     221                printf("Invalid HTTP method.\n");
     222                return EINVAL;
     223        }
     224
     225        uri = lbuf + 4;
     226        end_uri = str_chr(uri, ' ');
     227        if (end_uri == NULL) {
     228                end_uri = lbuf + lbuf_used - 2;
     229                assert(*end_uri == '\r');
     230        }
     231
     232        *end_uri = '\0';
     233        printf("Requested URI '%s'.\n", uri);
     234
     235        if (!uri_is_valid(uri)) {
     236                printf("Invalid request URI.\n");
     237                return EINVAL;
     238        }
     239
     240        return uri_get(uri, conn_sd);
     241}
    55242
    56243int main(int argc, char *argv[])
     
    64251        int rc;
    65252
    66         size_t response_size;
    67253
    68254        addr.sin_family = AF_INET;
     
    94280                return 1;
    95281        }
    96 
    97         response_size = str_size(response_msg);
    98282
    99283        printf("Listening for connections at port number %u.\n", PORT_NUMBER);
     
    105289                if (conn_sd < 0) {
    106290                        printf("accept() failed.\n");
    107                         return 1;
     291                        continue;
    108292                }
    109293
     
    111295
    112296                printf("Wait for client request\n");
    113 
    114                 /* Really we should wait for a blank line. */
    115                 rc = recv(conn_sd, buf, BUFFER_SIZE, 0);
    116                 if (rc < 0) {
    117                         printf("recv() failed\n");
    118                         return 1;
    119                 }
    120 
    121                 /* Send a canned response. */
    122                 printf("Send response...\n");
    123                 rc = send(conn_sd, (void *) response_msg, response_size, 0);
    124                 if (rc < 0) {
    125                         printf("send() failed.\n");
    126                         return 1;
    127                 }
     297                rbuf_out = rbuf_in = 0;
     298
     299                rc = req_process(conn_sd);
     300                if (rc != EOK)
     301                        printf("Error processing request.\n");
    128302
    129303                rc = closesocket(conn_sd);
  • uspace/drv/bus/isa/isa.dev

    r4c67e52 r899f1a9  
    1313        irq 1
    1414        io_range 060 10
    15        
     15
     16ne2k:
     17        match 100 isa/ne2k
     18        irq 5
     19        io_range 300 20
  • uspace/drv/nic/ne2k/dp8390.c

    r4c67e52 r899f1a9  
    142142static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
    143143{
     144        size_t esize_ru = (size + 1) & ~1;
    144145        size_t esize = size & ~1;
    145146       
    146         pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
    147         pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
     147        pio_write_8(ne2k->port + DP_RBCR0, esize_ru & 0xff);
     148        pio_write_8(ne2k->port + DP_RBCR1, (esize_ru >> 8) & 0xff);
    148149        pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
    149150        pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
  • uspace/lib/c/generic/fibril_synch.c

    r4c67e52 r899f1a9  
    447447}
    448448
     449/** Timer fibril.
     450 *
     451 * @param arg   Timer
     452 */
     453static int fibril_timer_func(void *arg)
     454{
     455        fibril_timer_t *timer = (fibril_timer_t *) arg;
     456        int rc;
     457
     458        fibril_mutex_lock(&timer->lock);
     459
     460        while (true) {
     461                while (timer->state != fts_active &&
     462                    timer->state != fts_cleanup) {
     463
     464                        if (timer->state == fts_cleanup)
     465                                break;
     466
     467                        fibril_condvar_wait(&timer->cv, &timer->lock);
     468                }
     469
     470                if (timer->state == fts_cleanup)
     471                        break;
     472
     473                rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock,
     474                    timer->delay);
     475                if (rc == ETIMEOUT) {
     476                        timer->state = fts_fired;
     477                        fibril_mutex_unlock(&timer->lock);
     478                        timer->fun(timer->arg);
     479                        fibril_mutex_lock(&timer->lock);
     480                }
     481        }
     482
     483        fibril_mutex_unlock(&timer->lock);
     484        return 0;
     485}
     486
     487/** Create new timer.
     488 *
     489 * @return              New timer on success, @c NULL if out of memory.
     490 */
     491fibril_timer_t *fibril_timer_create(void)
     492{
     493        fid_t fid;
     494        fibril_timer_t *timer;
     495
     496        timer = calloc(1, sizeof(fibril_timer_t));
     497        if (timer == NULL)
     498                return NULL;
     499
     500        fid = fibril_create(fibril_timer_func, (void *) timer);
     501        if (fid == 0) {
     502                free(timer);
     503                return NULL;
     504        }
     505
     506        fibril_mutex_initialize(&timer->lock);
     507        fibril_condvar_initialize(&timer->cv);
     508
     509        timer->fibril = fid;
     510        timer->state = fts_not_set;
     511
     512        fibril_add_ready(fid);
     513
     514        return timer;
     515}
     516
     517/** Destroy timer.
     518 *
     519 * @param timer         Timer, must not be active or accessed by other threads.
     520 */
     521void fibril_timer_destroy(fibril_timer_t *timer)
     522{
     523        fibril_mutex_lock(&timer->lock);
     524        assert(timer->state != fts_active);
     525        timer->state = fts_cleanup;
     526        fibril_condvar_broadcast(&timer->cv);
     527        fibril_mutex_unlock(&timer->lock);
     528}
     529
     530/** Set timer.
     531 *
     532 * Set timer to execute a callback function after the specified
     533 * interval.
     534 *
     535 * @param timer         Timer
     536 * @param delay         Delay in microseconds
     537 * @param fun           Callback function
     538 * @param arg           Argument for @a fun
     539 */
     540void fibril_timer_set(fibril_timer_t *timer, suseconds_t delay,
     541    fibril_timer_fun_t fun, void *arg)
     542{
     543        fibril_mutex_lock(&timer->lock);
     544        timer->state = fts_active;
     545        timer->delay = delay;
     546        timer->fun = fun;
     547        timer->arg = arg;
     548        fibril_condvar_broadcast(&timer->cv);
     549        fibril_mutex_unlock(&timer->lock);
     550}
     551
     552/** Clear timer.
     553 *
     554 * Clears (cancels) timer and returns last state of the timer.
     555 * This can be one of:
     556 *    - fts_not_set     If the timer has not been set or has been cleared
     557 *    - fts_active      Timer was set but did not fire
     558 *    - fts_fired       Timer fired
     559 *
     560 * @param timer         Timer
     561 * @return              Last timer state
     562 */
     563fibril_timer_state_t fibril_timer_clear(fibril_timer_t *timer)
     564{
     565        fibril_timer_state_t old_state;
     566
     567        fibril_mutex_lock(&timer->lock);
     568        old_state = timer->state;
     569        timer->state = fts_not_set;
     570
     571        timer->delay = 0;
     572        timer->fun = NULL;
     573        timer->arg = NULL;
     574        fibril_condvar_broadcast(&timer->cv);
     575        fibril_mutex_unlock(&timer->lock);
     576
     577        return old_state;
     578}
     579
    449580/** @}
    450581 */
  • uspace/lib/c/include/bitops.h

    r4c67e52 r899f1a9  
    4040/** Mask with bit @a n set. */
    4141#define BIT_V(type, n) \
    42     ((type)1 << ((n) - 1))
     42    ((type)1 << (n))
    4343
    4444/** Mask with rightmost @a n bits set. */
    4545#define BIT_RRANGE(type, n) \
    46     (BIT_V(type, (n) + 1) - 1)
     46    (BIT_V(type, (n)) - 1)
    4747
    4848/** Mask with bits @a hi .. @a lo set. @a hi >= @a lo. */
  • uspace/lib/c/include/errno.h

    r4c67e52 r899f1a9  
    9696#define ENOTCONN  (-10057)
    9797
     98#define ECONNREFUSED  (-10058)
     99
     100#define ECONNABORTED  (-10059)
     101
    98102/** The requested operation was not performed. Try again later. */
    99103#define EAGAIN  (-11002)
  • uspace/lib/c/include/fibril_synch.h

    r4c67e52 r899f1a9  
    107107        fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name)
    108108
     109typedef void (*fibril_timer_fun_t)(void *);
     110
     111typedef enum {
     112        /** Timer has not been set or has been cleared */
     113        fts_not_set,
     114        /** Timer was set but did not fire yet */
     115        fts_active,
     116        /** Timer has fired and has not been cleared since */
     117        fts_fired,
     118        /** Timer is being destroyed */
     119        fts_cleanup
     120} fibril_timer_state_t;
     121
     122/** Fibril timer.
     123 *
     124 * When a timer is set it executes a callback function (in a separate
     125 * fibril) after a specified time interval. The timer can be cleared
     126 * (canceled) before that. From the return value of fibril_timer_clear()
     127 * one can tell whether the timer fired or not.
     128 */
     129typedef struct {
     130        fibril_mutex_t lock;
     131        fibril_condvar_t cv;
     132        fid_t fibril;
     133        fibril_timer_state_t state;
     134
     135        suseconds_t delay;
     136        fibril_timer_fun_t fun;
     137        void *arg;
     138} fibril_timer_t;
     139
    109140extern void fibril_mutex_initialize(fibril_mutex_t *);
    110141extern void fibril_mutex_lock(fibril_mutex_t *);
     
    129160extern void fibril_condvar_broadcast(fibril_condvar_t *);
    130161
     162extern fibril_timer_t *fibril_timer_create(void);
     163extern void fibril_timer_destroy(fibril_timer_t *);
     164extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
     165    void *);
     166extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
     167
    131168#endif
    132169
  • uspace/srv/fs/exfat/exfat_directory.c

    r4c67e52 r899f1a9  
    9292        int rc = EOK;
    9393       
    94         if (di->b)
     94        if (di->b) {
    9595                rc = block_put(di->b);
     96                di->b = NULL;
     97        }
    9698       
    9799        return rc;
     
    285287        for (i = 0; i < count; i++) {
    286288                rc = exfat_directory_get(di, &de);
    287                 if (rc != EOK)
    288                         return rc;
     289                if (rc != EOK) {
     290                        free(array);
     291                        return rc;
     292                }
    289293                array[i] = *de;
    290294                rc = exfat_directory_next(di);
     
    312316        for (i = 0; i < count; i++) {
    313317                rc = exfat_directory_get(di, &de);
    314                 if (rc != EOK)
    315                         return rc;
     318                if (rc != EOK) {
     319                        free(array);
     320                        return rc;
     321                }
    316322                *de = array[i];
    317323                di->b->dirty = true;
     
    424430
    425431                di->b->dirty = true;
    426                 sname += chars;
    427432        }
    428433       
  • uspace/srv/net/tl/tcp/Makefile

    r4c67e52 r899f1a9  
    11#
    2 # Copyright (c) 2005 Martin Decky
    3 # Copyright (c) 2007 Jakub Jermar
     2# Copyright (c) 2011 Jiri Svoboda
    43# All rights reserved.
    54#
     
    3433
    3534SOURCES = \
    36         tcp.c
     35        conn.c \
     36        iqueue.c \
     37        ncsim.c \
     38        pdu.c \
     39        rqueue.c \
     40        segment.c \
     41        seq_no.c \
     42        sock.c \
     43        tcp.c \
     44        test.c \
     45        tqueue.c \
     46        ucall.c
    3747
    3848include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/tcp/tcp.c

    r4c67e52 r899f1a9  
    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 <byteorder.h>
     39#include <errno.h>
     40#include <io/log.h>
    4341#include <stdio.h>
    44 #include <errno.h>
    45 
     42#include <task.h>
     43
     44#include <icmp_remote.h>
     45#include <ip_client.h>
     46#include <ip_interface.h>
    4647#include <ipc/services.h>
    47 #include <ipc/net.h>
    4848#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>
     49#include <tl_common.h>
     50#include <tl_skel.h>
    5951#include <packet_client.h>
    6052#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 
     53
     54#include "ncsim.h"
     55#include "pdu.h"
     56#include "rqueue.h"
     57#include "sock.h"
     58#include "std.h"
    7259#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)
     60#include "test.h"
     61
     62#define NAME       "tcp"
     63
     64async_sess_t *net_sess;
     65static async_sess_t *icmp_sess;
     66async_sess_t *ip_sess;
     67packet_dimensions_t pkt_dims;
     68
     69static void tcp_received_pdu(tcp_pdu_t *pdu);
     70
     71/* Pull up packets into a single memory block. */
     72static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
     73{
     74        packet_t *npacket;
     75        size_t tot_len;
     76        int length;
     77
     78        npacket = packet;
     79        tot_len = 0;
     80        do {
     81                length = packet_get_data_length(packet);
     82                if (length <= 0)
     83                        return EINVAL;
     84
     85                tot_len += length;
     86        } while ((npacket = pq_next(npacket)) != NULL);
     87
     88        uint8_t *buf;
     89        uint8_t *dp;
     90
     91        buf = calloc(tot_len, 1);
     92        if (buf == NULL) {
     93                free(buf);
     94                return ENOMEM;
     95        }
     96
     97        npacket = packet;
     98        dp = buf;
     99        do {
     100                length = packet_get_data_length(packet);
     101                if (length <= 0) {
     102                        free(buf);
     103                        return EINVAL;
     104                }
     105
     106                memcpy(dp, packet_get_data(packet), length);
     107                dp += length;
     108        } while ((npacket = pq_next(npacket)) != NULL);
     109
     110        *data = buf;
     111        *dsize = tot_len;
     112        return EOK;
     113}
     114
     115/** Process packet received from network layer. */
     116static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
     117    services_t error)
    224118{
    225119        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;
    243120        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;
     121        int length;
     122        struct sockaddr_in *src_addr;
     123        struct sockaddr_in *dest_addr;
     124        size_t addr_len;
     125
     126        log_msg(LVL_DEBUG, "tcp_received_msg()");
    258127
    259128        switch (error) {
     
    261130                break;
    262131        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;
    274132        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 
     133                log_msg(LVL_WARN, "Unsupported service number %u",
     134                    (unsigned)error);
     135                pq_release_remote(net_sess, packet_get_id(packet));
     136                return ENOTSUP;
     137        }
     138
     139        /* Process and trim off IP header */
     140        log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
     141
     142        rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
     143        if (rc < 0) {
     144                log_msg(LVL_WARN, "ip_client_process_packet() failed");
     145                pq_release_remote(net_sess, packet_get_id(packet));
     146                return rc;
     147        }
     148
     149        offset = (size_t)rc;
    285150        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 */
     151
     152        if (length < 0 || (size_t)length < offset) {
     153                log_msg(LVL_WARN, "length=%d, dropping.", length);
     154                pq_release_remote(net_sess, packet_get_id(packet));
     155                return EINVAL;
     156        }
     157
     158        addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
     159            (uint8_t **)&dest_addr);
     160        if (addr_len <= 0) {
     161                log_msg(LVL_WARN, "Failed to get packet address.");
     162                pq_release_remote(net_sess, packet_get_id(packet));
     163                return EINVAL;
     164        }
     165
     166        if (addr_len != sizeof(struct sockaddr_in)) {
     167                log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
     168                    addr_len, sizeof(struct sockaddr_in));
     169                pq_release_remote(net_sess, packet_get_id(packet));
     170                return EINVAL;
     171        }
     172
    293173        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 
     174        if (rc != EOK) {
     175                log_msg(LVL_WARN, "Failed to trim packet.");
     176                pq_release_remote(net_sess, packet_get_id(packet));
     177                return rc;
     178        }
     179
     180        /* Pull up packets into a single memory block, pdu_raw. */
     181        log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
     182        uint8_t *pdu_raw;
     183        size_t pdu_raw_size = 0;
     184
     185        pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
     186
     187        /* Split into header and payload. */
     188
     189        log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
     190
     191        tcp_pdu_t *pdu;
     192        size_t hdr_size;
     193
     194        /* XXX Header options */
     195        hdr_size = sizeof(tcp_header_t);
     196
     197        if (pdu_raw_size < hdr_size) {
     198                log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
     199                    pdu_raw_size, hdr_size);
     200                pq_release_remote(net_sess, packet_get_id(packet));
    410201                return EINVAL;
    411202        }
    412203
    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         }
     204        log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
     205            pdu_raw_size, hdr_size);
     206        pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
     207            pdu_raw_size - hdr_size);
     208        if (pdu == NULL) {
     209                log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
     210                return ENOMEM;
     211        }
     212
     213        free(pdu_raw);
     214
     215        pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
     216        pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
     217        log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
     218            pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
     219
     220        tcp_received_pdu(pdu);
     221        tcp_pdu_delete(pdu);
    449222
    450223        return EOK;
    451224}
    452225
    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;
     226/** Receive packets from network layer. */
     227static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     228{
    1724229        packet_t *packet;
    1725230        int rc;
    1726231
    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        
     232        log_msg(LVL_DEBUG, "tcp_receiver()");
     233
    2451234        while (true) {
    2452235                switch (IPC_GET_IMETHOD(*icall)) {
    2453236                case NET_TL_RECEIVED:
    2454                         rc = packet_translate_remote(tcp_globals.net_sess, &packet,
     237                        log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
     238                        rc = packet_translate_remote(net_sess, &packet,
    2455239                            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);
     240                        if (rc != EOK) {
     241                                log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
     242                                async_answer_0(iid, (sysarg_t)rc);
     243                                break;
     244                        }
     245                        rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
     246                            IPC_GET_ERROR(*icall));
     247                        async_answer_0(iid, (sysarg_t)rc);
    2461248                        break;
    2462249                default:
    2463                         async_answer_0(iid, (sysarg_t) ENOTSUP);
     250                        log_msg(LVL_DEBUG, "method = %u",
     251                            (unsigned)IPC_GET_IMETHOD(*icall));
     252                        async_answer_0(iid, ENOTSUP);
     253                        break;
    2464254                }
    2465                
     255
    2466256                iid = async_get_call(icall);
    2467257        }
    2468258}
    2469259
    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  *
     260/** Transmit PDU over network layer. */
     261void tcp_transmit_pdu(tcp_pdu_t *pdu)
     262{
     263        struct sockaddr_in dest;
     264        nic_device_id_t dev_id;
     265        void *phdr;
     266        size_t phdr_len;
     267        packet_dimension_t *pkt_dim;
     268        int rc;
     269        packet_t *packet;
     270        void *pkt_data;
     271        size_t pdu_size;
     272
     273        dest.sin_family = AF_INET;
     274        dest.sin_port = 0; /* not needed */
     275        dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
     276
     277        /* Find route. Obtained pseudo-header is not used. */
     278        rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
     279            sizeof(dest), &dev_id, &phdr, &phdr_len);
     280        if (rc != EOK) {
     281                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
     282                return;
     283        }
     284
     285        rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
     286        if (rc != EOK) {
     287                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
     288                return;
     289        }
     290
     291        pdu_size = pdu->header_size + pdu->text_size;
     292
     293        packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
     294            pkt_dim->prefix, pkt_dim->suffix);
     295        if (!packet) {
     296                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
     297                return;
     298        }
     299
     300        pkt_data = packet_suffix(packet, pdu_size);
     301        if (!pkt_data) {
     302                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
     303                pq_release_remote(net_sess, packet_get_id(packet));
     304                return;
     305        }
     306
     307        rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
     308        if (rc != EOK) {
     309                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
     310                pq_release_remote(net_sess, packet_get_id(packet));
     311                return;
     312        }
     313
     314        rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
     315        if (rc != EOK) {
     316                log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
     317                pq_release_remote(net_sess, packet_get_id(packet));
     318                return;
     319        }
     320
     321        /* Copy PDU data to packet */
     322        memcpy(pkt_data, pdu->header, pdu->header_size);
     323        memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
     324            pdu->text_size);
     325
     326        /* Transmit packet. XXX Transfers packet ownership to IP? */
     327        ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
     328}
     329
     330/** Process received PDU. */
     331static void tcp_received_pdu(tcp_pdu_t *pdu)
     332{
     333        tcp_segment_t *dseg;
     334        tcp_sockpair_t rident;
     335
     336        log_msg(LVL_DEBUG, "tcp_received_pdu()");
     337
     338        if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
     339                log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
     340                return;
     341        }
     342
     343        /* Insert decoded segment into rqueue */
     344        tcp_rqueue_insert_seg(&rident, dseg);
     345}
     346
     347/* Called from libnet */
     348void tl_connection(void)
     349{
     350        log_msg(LVL_DEBUG, "tl_connection()");
     351}
     352
     353/* Called from libnet */
     354int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     355    size_t *answer_count)
     356{
     357        async_sess_t *callback;
     358
     359        log_msg(LVL_DEBUG, "tl_message()");
     360
     361        *answer_count = 0;
     362        callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
     363        if (callback)
     364                return tcp_sock_connection(callback, callid, *call);
     365
     366        return ENOTSUP;
     367}
     368
     369/* Called from libnet */
     370int tl_initialize(async_sess_t *sess)
     371{
     372        int rc;
     373
     374        net_sess = sess;
     375        icmp_sess = icmp_connect_module();
     376
     377        log_msg(LVL_DEBUG, "tl_initialize()");
     378
     379        tcp_sock_init();
     380
     381        ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
     382            tcp_receiver);
     383        if (ip_sess == NULL)
     384                return ENOENT;
     385
     386        rc = packet_dimensions_initialize(&pkt_dims);
     387        if (rc != EOK)
     388                return rc;
     389
     390        return EOK;
     391}
     392
     393int main(int argc, char **argv)
     394{
     395        int rc;
     396
     397        printf(NAME ": TCP (Transmission Control Protocol) network module\n");
     398
     399        rc = log_init(NAME, LVL_ERROR);
     400        if (rc != EOK) {
     401                printf(NAME ": Failed to initialize log.\n");
     402                return 1;
     403        }
     404
     405//      printf(NAME ": Accepting connections\n");
     406//      task_retval(0);
     407
     408        tcp_rqueue_init();
     409        tcp_rqueue_thread_start();
     410
     411        tcp_ncsim_init();
     412        tcp_ncsim_thread_start();
     413
     414        if (0) tcp_test();
     415/*
     416        async_manager();
     417*/
     418        tl_module_start(SERVICE_TCP);
     419
     420        /* Not reached */
     421        return 0;
     422}
     423
     424/**
     425 * @}
    2477426 */
    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  */
  • uspace/srv/net/tl/tcp/tcp.h

    r4c67e52 r899f1a9  
    11/*
    2  * Copyright (c) 2008 Lukas Mejdrech
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3030 * @{
    3131 */
    32 
    33 /** @file
    34  * TCP module.
     32/** @file TCP (Transmission Control Protocol) network module
    3533 */
    3634
    37 #ifndef NET_TCP_H_
    38 #define NET_TCP_H_
     35#ifndef TCP_H
     36#define TCP_H
    3937
    4038#include <async.h>
    41 #include <fibril_synch.h>
    42 #include <net/packet.h>
    43 #include <net/device.h>
    44 #include <socket_core.h>
    45 #include <tl_common.h>
     39#include <packet_remote.h>
     40#include "tcp_type.h"
    4641
    47 /** Type definition of the TCP global data.
    48  * @see tcp_globals
    49  */
    50 typedef struct tcp_globals tcp_globals_t;
    51 
    52 /** Type definition of the TCP socket specific data.
    53  * @see tcp_socket_data
    54  */
    55 typedef struct tcp_socket_data tcp_socket_data_t;
    56 
    57 /** Type definition of the TCP operation data.
    58  * @see tcp_operation
    59  */
    60 typedef struct tcp_operation tcp_operation_t;
    61 
    62 /** TCP socket state type definition.
    63  * @see tcp_socket_state
    64  */
    65 typedef enum tcp_socket_state tcp_socket_state_t;
    66 
    67 /** TCP socket state. */
    68 enum tcp_socket_state {
    69         /** Initial.
    70          *
    71          * Not connected or bound.
    72          */
    73         TCP_SOCKET_INITIAL,
    74        
    75         /** Listening.
    76          *
    77          * Awaiting a connection request from another TCP layer.
    78          * When SYN is received a new bound socket in the
    79          * TCP_SOCKET_SYN_RECEIVED state should be created.
    80          */
    81         TCP_SOCKET_LISTEN,
    82        
    83         /** Connecting issued.
    84          *
    85          * A SYN has been sent, and TCP is awaiting the response SYN.
    86          * Should continue to the TCP_SOCKET_ESTABLISHED state.
    87          */
    88         TCP_SOCKET_SYN_SENT,
    89        
    90         /** Connecting received.
    91          *
    92          * A SYN has been received, a SYN has been sent, and TCP is awaiting an
    93          * ACK. Should continue to the TCP_SOCKET_ESTABLISHED state.
    94          */
    95         TCP_SOCKET_SYN_RECEIVED,
    96        
    97         /** Connected.
    98          *
    99          * The three-way handshake has been completed.
    100          */
    101         TCP_SOCKET_ESTABLISHED,
    102        
    103         /** Closing started.
    104          *
    105          * The local application has issued a CLOSE.
    106          * TCP has sent a FIN, and is awaiting an ACK or a FIN.
    107          * Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is
    108          * received.
    109          * Should continue to the TCP_SOCKET_CLOSING state when a FIN is
    110          * received.
    111          */
    112         TCP_SOCKET_FIN_WAIT_1,
    113        
    114         /** Closing confirmed.
    115          *
    116          * A FIN has been sent, and an ACK received.
    117          * TCP is awaiting a~FIN from the remote TCP layer.
    118          * Should continue to the TCP_SOCKET_CLOSING state.
    119          */
    120         TCP_SOCKET_FIN_WAIT_2,
    121        
    122         /** Closing.
    123          *
    124          * A FIN has been sent, a FIN has been received, and an ACK has been
    125          * sent.
    126          * TCP is awaiting an ACK for the FIN that was sent.
    127          * Should continue to the TCP_SOCKET_TIME_WAIT state.
    128          */
    129         TCP_SOCKET_CLOSING,
    130        
    131         /** Closing received.
    132          *
    133          * TCP has received a FIN, and has sent an ACK.
    134          * It is awaiting a close request from the local application before
    135          * sending a FIN.
    136          * Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state.
    137          */
    138         TCP_SOCKET_CLOSE_WAIT,
    139        
    140         /**
    141          * A FIN has been received, and an ACK and a FIN have been sent.
    142          * TCP is awaiting an ACK.
    143          * Should continue to the TCP_SOCKET_TIME_WAIT state.
    144          */
    145         TCP_SOCKET_LAST_ACK,
    146        
    147         /** Closing finished.
    148          *
    149          * FINs have been received and ACK’d, and TCP is waiting two MSLs to
    150          * remove the connection from the table.
    151          */
    152         TCP_SOCKET_TIME_WAIT,
    153        
    154         /** Closed.
    155          *
    156          * Imaginary, this indicates that a connection has been removed from
    157          * the connection table.
    158          */
    159         TCP_SOCKET_CLOSED
    160 };
    161 
    162 /** TCP operation data. */
    163 struct tcp_operation {
    164         /** Operation result. */
    165         int result;
    166         /** Safety lock. */
    167         fibril_mutex_t mutex;
    168         /** Operation result signaling. */
    169         fibril_condvar_t condvar;
    170 };
    171 
    172 /** TCP socket specific data. */
    173 struct tcp_socket_data {
    174         /** TCP socket state. */
    175         tcp_socket_state_t state;
    176        
    177         /**
    178          * Data fragment size.
    179          * Sending optimalization.
    180          */
    181         size_t data_fragment_size;
    182        
    183         /** Device identifier. */
    184         nic_device_id_t device_id;
    185        
    186         /**
    187          * Listening backlog.
    188          * The maximal number of connected but not yet accepted sockets.
    189          */
    190         int backlog;
    191        
    192         /**
    193          * Parent listening socket identifier.
    194          * Set if this socket is an accepted one.
    195          */
    196         int listening_socket_id;
    197        
    198         /** Treshold size in bytes. */
    199         size_t treshold;
    200         /** Window size in bytes. */
    201         size_t window;
    202         /** Acknowledgement timeout. */
    203         suseconds_t timeout;
    204         /** Last acknowledged byte. */
    205         uint32_t acknowledged;
    206         /** Next incoming sequence number. */
    207         uint32_t next_incoming;
    208         /** Incoming FIN. */
    209         uint32_t fin_incoming;
    210         /** Next outgoing sequence number. */
    211         uint32_t next_outgoing;
    212         /** Last outgoing sequence number. */
    213         uint32_t last_outgoing;
    214         /** Outgoing FIN. */
    215         uint32_t fin_outgoing;
    216        
    217         /**
    218          * Expected sequence number by the remote host.
    219          * The sequence number the other host expects.
    220          * The notification is sent only upon a packet reecival.
    221          */
    222         uint32_t expected;
    223        
    224         /**
    225          * Expected sequence number counter.
    226          * Counts the number of received notifications for the same sequence
    227          * number.
    228          */
    229         int expected_count;
    230        
    231         /** Incoming packet queue.
    232          *
    233          * Packets are buffered until received in the right order.
    234          * The packets are excluded after successfully read.
    235          * Packets are sorted by their starting byte.
    236          * Packets metric is set as their data length.
    237          */
    238         packet_t *incoming;
    239        
    240         /** Outgoing packet queue.
    241          *
    242          * Packets are buffered until acknowledged by the remote host in the
    243          * right order.
    244          * The packets are excluded after acknowledged.
    245          * Packets are sorted by their starting byte.
    246          * Packets metric is set as their data length.
    247          */
    248         packet_t *outgoing;
    249        
    250         /** IP pseudo header. */
    251         void *pseudo_header;
    252         /** IP pseudo header length. */
    253         size_t headerlen;
    254         /** Remote host address. */
    255         struct sockaddr *addr;
    256         /** Remote host address length. */
    257         socklen_t addrlen;
    258         /** Remote host port. */
    259         uint16_t dest_port;
    260         /** Parent local sockets. */
    261         socket_cores_t *local_sockets;
    262        
    263         /** Local sockets safety lock.
    264          *
    265          * May be locked for writing while holding the global lock for reading
    266          * when changing the local sockets only.
    267          * The global lock may be locked only before locking the local lock.
    268          * The global lock may be locked more weakly than the local lock.
    269          * The global lock may be released before releasing the local lock.
    270          * @see tcp_globals:lock
    271          */
    272         fibril_rwlock_t *local_lock;
    273        
    274         /** Pending operation data. */
    275         tcp_operation_t operation;
    276        
    277         /**
    278          * Timeouts in a row counter.
    279          * If TCP_MAX_TIMEOUTS is reached, the connection is lost.
    280          */
    281         int timeout_count;
    282 };
    283 
    284 /** TCP global data. */
    285 struct tcp_globals {
    286         /** Networking module session. */
    287         async_sess_t *net_sess;
    288         /** IP module session. */
    289         async_sess_t *ip_sess;
    290         /** ICMP module session. */
    291         async_sess_t *icmp_sess;
    292         /** Last used free port. */
    293         int last_used_port;
    294         /** Active sockets. */
    295         socket_ports_t sockets;
    296         /** Device packet dimensions. */
    297         packet_dimensions_t dimensions;
    298        
    299         /**
    300          * Safety lock.
    301          * Write lock is used only for adding or removing socket ports.
    302          */
    303         fibril_rwlock_t lock;
    304 };
     42extern async_sess_t *net_sess;
     43extern async_sess_t *ip_sess;
     44extern void tcp_transmit_pdu(tcp_pdu_t *);
    30545
    30646#endif
Note: See TracChangeset for help on using the changeset viewer.