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


Ignore:
Files:
1 added
29 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

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

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

    r899f1a9 r4c67e52  
    241241                /* Accept a socket if a stream socket is used */
    242242                addrlen = sizeof(address_buf);
    243                 if (verbose)
    244                         printf("accept()\n");
    245243                socket_id = accept(listening_id, (void *) address_buf, &addrlen);
    246244                if (socket_id <= 0) {
     
    260258
    261259                /* Receive a message to echo */
    262                 if (verbose)
    263                         printf("recvfrom()\n");
    264260                rcv_size = recvfrom(socket_id, data, size, 0, address,
    265261                    &addrlen);
     
    301297
    302298                        /* Answer the request either with the static reply or the original data */
    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                         }
     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");
    316302                }
    317303
  • uspace/app/websrv/websrv.c

    r899f1a9 r4c67e52  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2010 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/**
    33  * @file Skeletal web server.
     33 * @file (Less-than-skeleton) web server.
    3434 */
    3535
    36 #include <bool.h>
    37 #include <errno.h>
    3836#include <stdio.h>
    39 #include <sys/types.h>
    40 #include <sys/stat.h>
    41 #include <stdlib.h>
    42 #include <fcntl.h>
    4337
    4438#include <net/in.h>
     
    5044#define PORT_NUMBER 8080
    5145
    52 #define WEB_ROOT "/data/web"
    53 
    5446/** Buffer for receiving the request. */
    5547#define BUFFER_SIZE 1024
    56 static char rbuf[BUFFER_SIZE];
    57 static size_t rbuf_out, rbuf_in;
    58 
    59 static char lbuf[BUFFER_SIZE + 1];
    60 static size_t lbuf_used;
    61 
    62 static char fbuf[BUFFER_SIZE];
     48static char buf[BUFFER_SIZE];
    6349
    6450/** Response to send to client. */
    65 static const char *ok_msg =
     51static const char *response_msg =
    6652    "HTTP/1.0 200 OK\r\n"
    67     "\r\n";
    68 
    69 /** Receive one character (with buffering) */
    70 static 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. */
    92 static 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 
    119 static 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 
    139 static 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 
    157 static 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 
    207 static 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 }
     53    "\r\n"
     54    "<h1>Hello from HelenOS!</h1>\r\n";
    24255
    24356int main(int argc, char *argv[])
     
    25164        int rc;
    25265
     66        size_t response_size;
    25367
    25468        addr.sin_family = AF_INET;
     
    28195        }
    28296
     97        response_size = str_size(response_msg);
     98
    28399        printf("Listening for connections at port number %u.\n", PORT_NUMBER);
    284100        while (true) {
     
    289105                if (conn_sd < 0) {
    290106                        printf("accept() failed.\n");
    291                         continue;
     107                        return 1;
    292108                }
    293109
     
    295111
    296112                printf("Wait for client request\n");
    297                 rbuf_out = rbuf_in = 0;
    298113
    299                 rc = req_process(conn_sd);
    300                 if (rc != EOK)
    301                         printf("Error processing request.\n");
     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                }
    302128
    303129                rc = closesocket(conn_sd);
  • uspace/drv/bus/isa/isa.dev

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

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

    r899f1a9 r4c67e52  
    447447}
    448448
    449 /** Timer fibril.
    450  *
    451  * @param arg   Timer
    452  */
    453 static 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  */
    491 fibril_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  */
    521 void 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  */
    540 void 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  */
    563 fibril_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 
    580449/** @}
    581450 */
  • uspace/lib/c/include/bitops.h

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

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

    r899f1a9 r4c67e52  
    107107        fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name)
    108108
    109 typedef void (*fibril_timer_fun_t)(void *);
    110 
    111 typedef 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  */
    129 typedef 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 
    140109extern void fibril_mutex_initialize(fibril_mutex_t *);
    141110extern void fibril_mutex_lock(fibril_mutex_t *);
     
    160129extern void fibril_condvar_broadcast(fibril_condvar_t *);
    161130
    162 extern fibril_timer_t *fibril_timer_create(void);
    163 extern void fibril_timer_destroy(fibril_timer_t *);
    164 extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
    165     void *);
    166 extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
    167 
    168131#endif
    169132
  • uspace/srv/fs/exfat/exfat_directory.c

    r899f1a9 r4c67e52  
    9292        int rc = EOK;
    9393       
    94         if (di->b) {
     94        if (di->b)
    9595                rc = block_put(di->b);
    96                 di->b = NULL;
    97         }
    9896       
    9997        return rc;
     
    287285        for (i = 0; i < count; i++) {
    288286                rc = exfat_directory_get(di, &de);
    289                 if (rc != EOK) {
    290                         free(array);
    291                         return rc;
    292                 }
     287                if (rc != EOK)
     288                        return rc;
    293289                array[i] = *de;
    294290                rc = exfat_directory_next(di);
     
    316312        for (i = 0; i < count; i++) {
    317313                rc = exfat_directory_get(di, &de);
    318                 if (rc != EOK) {
    319                         free(array);
    320                         return rc;
    321                 }
     314                if (rc != EOK)
     315                        return rc;
    322316                *de = array[i];
    323317                di->b->dirty = true;
     
    430424
    431425                di->b->dirty = true;
     426                sname += chars;
    432427        }
    433428       
  • uspace/srv/net/tl/tcp/Makefile

    r899f1a9 r4c67e52  
    11#
    2 # Copyright (c) 2011 Jiri Svoboda
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    3334
    3435SOURCES = \
    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
     36        tcp.c
    4737
    4838include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/tcp/tcp.c

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

    r899f1a9 r4c67e52  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2008 Lukas Mejdrech
    33 * All rights reserved.
    44 *
     
    3030 * @{
    3131 */
    32 /** @file TCP (Transmission Control Protocol) network module
    33  */
    34 
    35 #ifndef TCP_H
    36 #define TCP_H
     32
     33/** @file
     34 * TCP module.
     35 */
     36
     37#ifndef NET_TCP_H_
     38#define NET_TCP_H_
    3739
    3840#include <async.h>
    39 #include <packet_remote.h>
    40 #include "tcp_type.h"
    41 
    42 extern async_sess_t *net_sess;
    43 extern async_sess_t *ip_sess;
    44 extern void tcp_transmit_pdu(tcp_pdu_t *);
     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>
     46
     47/** Type definition of the TCP global data.
     48 * @see tcp_globals
     49 */
     50typedef struct tcp_globals tcp_globals_t;
     51
     52/** Type definition of the TCP socket specific data.
     53 * @see tcp_socket_data
     54 */
     55typedef struct tcp_socket_data tcp_socket_data_t;
     56
     57/** Type definition of the TCP operation data.
     58 * @see tcp_operation
     59 */
     60typedef struct tcp_operation tcp_operation_t;
     61
     62/** TCP socket state type definition.
     63 * @see tcp_socket_state
     64 */
     65typedef enum tcp_socket_state tcp_socket_state_t;
     66
     67/** TCP socket state. */
     68enum 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. */
     163struct 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. */
     173struct 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. */
     285struct 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};
    45305
    46306#endif
Note: See TracChangeset for help on using the changeset viewer.