Subversion Repositories HelenOS

Rev

Rev 4708 | Rev 4750 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4708 Rev 4742
Line 29... Line 29...
29
/** @addtogroup tcp
29
/** @addtogroup tcp
30
 *  @{
30
 *  @{
31
 */
31
 */
32
 
32
 
33
/** @file
33
/** @file
-
 
34
 *  TCP module implementation.
-
 
35
 *  @see tcp.h
34
 *  \todo
36
 *  \todo
35
 */
37
 */
36
 
38
 
-
 
39
#include <assert.h>
37
#include <async.h>
40
#include <async.h>
-
 
41
#include <fibril_sync.h>
-
 
42
#include <malloc.h>
-
 
43
//TODO remove stdio
38
#include <stdio.h>
44
#include <stdio.h>
39
 
45
 
40
#include <ipc/ipc.h>
46
#include <ipc/ipc.h>
41
#include <ipc/services.h>
47
#include <ipc/services.h>
42
 
48
 
43
#include "../../err.h"
49
#include "../../err.h"
44
#include "../../messages.h"
50
#include "../../messages.h"
45
#include "../../modules.h"
51
#include "../../modules.h"
-
 
52
 
-
 
53
#include "../../structures/dynamic_fifo.h"
46
#include "../../structures/packet/packet_client.h"
54
#include "../../structures/packet/packet_client.h"
47
 
55
 
-
 
56
#include "../../include/checksum.h"
-
 
57
#include "../../include/in.h"
-
 
58
#include "../../include/in6.h"
-
 
59
#include "../../include/inet.h"
48
#include "../../include/ip_client.h"
60
#include "../../include/ip_client.h"
49
#include "../../include/ip_interface.h"
61
#include "../../include/ip_interface.h"
50
#include "../../include/ip_protocols.h"
62
#include "../../include/ip_protocols.h"
-
 
63
#include "../../include/icmp_client.h"
51
#include "../../include/icmp_interface.h"
64
#include "../../include/icmp_interface.h"
-
 
65
#include "../../include/net_interface.h"
-
 
66
#include "../../include/socket_codes.h"
-
 
67
#include "../../include/socket_errno.h"
-
 
68
#include "../../include/tcp_codes.h"
52
 
69
 
53
#include "../../socket/socket_core.h"
70
#include "../../socket/socket_core.h"
-
 
71
#include "../../socket/socket_messages.h"
54
 
72
 
-
 
73
#include "../tl_common.h"
55
#include "../tl_messages.h"
74
#include "../tl_messages.h"
56
 
75
 
57
#include "tcp.h"
76
#include "tcp.h"
-
 
77
#include "tcp_header.h"
58
#include "tcp_module.h"
78
#include "tcp_module.h"
59
 
79
 
-
 
80
/** The TCP window default value.
-
 
81
 */
-
 
82
#define NET_DEFAULT_TCP_WINDOW  10240
-
 
83
 
-
 
84
/** \todo
-
 
85
 */
-
 
86
#define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
-
 
87
 
-
 
88
/** \todo
-
 
89
 */
-
 
90
#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT   2000L
-
 
91
 
-
 
92
/** The initial outgoing sequence number.
-
 
93
 */
-
 
94
#define TCP_INITIAL_SEQUENCE_NUMBER     2999
-
 
95
 
-
 
96
/** Maximum TCP fragment size.
-
 
97
 */
-
 
98
#define MAX_TCP_FRAGMENT_SIZE   65535
-
 
99
 
60
/** Free ports pool start.
100
/** Free ports pool start.
61
 */
101
 */
62
#define TCP_FREE_PORTS_START    1025
102
#define TCP_FREE_PORTS_START    1025
63
 
103
 
64
/** Free ports pool end.
104
/** Free ports pool end.
65
 */
105
 */
66
#define TCP_FREE_PORTS_END      65535
106
#define TCP_FREE_PORTS_END      65535
67
 
107
 
68
/** TCP global data.
108
/** \todo
69
 */
109
 */
-
 
110
#define TCP_SYN_SENT_TIMEOUT    1000000L
-
 
111
 
-
 
112
/** The maximum number of timeouts in a row before singaling connection lost.
-
 
113
 */
-
 
114
#define TCP_MAX_TIMEOUTS        8
-
 
115
 
-
 
116
/** The number of acknowledgements before retransmit.
-
 
117
 */
-
 
118
#define TCP_FAST_RETRANSMIT_COUNT   3
-
 
119
 
-
 
120
/** \todo
-
 
121
 */
-
 
122
#define IS_IN_INTERVAL_OVERFLOW( lower, value, higher_equal )   (((( lower ) < ( value )) && ((( value ) <= ( higher_equal )) || (( higher_equal ) < ( lower )))) || ((( value ) <= ( higher_equal )) && (( higher_equal ) < ( lower ))))
-
 
123
 
-
 
124
/** Type definition of the TCP timeout.
-
 
125
 *  @see tcp_timeout
-
 
126
 */
-
 
127
typedef struct tcp_timeout  tcp_timeout_t;
-
 
128
 
-
 
129
/** Type definition of the TCP timeout pointer.
-
 
130
 *  @see tcp_timeout
-
 
131
 */
-
 
132
typedef tcp_timeout_t * tcp_timeout_ref;
-
 
133
 
-
 
134
/** TCP reply timeout data.
-
 
135
 *  Used as a timeouting fibril argument.
-
 
136
 *  @see tcp_timeout()
-
 
137
 */
-
 
138
struct tcp_timeout{
-
 
139
    /** TCP global data are going to be read only.
-
 
140
     */
-
 
141
    int                 globals_read_only;
-
 
142
    /** Socket port.
-
 
143
     */
-
 
144
    int                 port;
-
 
145
    /** Local sockets.
-
 
146
     */
-
 
147
    socket_cores_ref    local_sockets;
-
 
148
    /** Socket identifier.
-
 
149
     */
-
 
150
    int                 socket_id;
-
 
151
    /** Socket state.
-
 
152
     */
70
tcp_globals_t   tcp_globals;
153
    tcp_socket_state_t  state;
-
 
154
    /** Sent packet sequence number.
-
 
155
     */
-
 
156
    int                 sequence_number;
-
 
157
    /** Timeout in microseconds.
-
 
158
     */
-
 
159
    suseconds_t         timeout;
-
 
160
    /** Port map key.
-
 
161
     */
-
 
162
    char *              key;
-
 
163
    /** Port map key length.
-
 
164
     */
-
 
165
    size_t              key_length;
-
 
166
};
-
 
167
 
-
 
168
/** Releases the packet and returns the result.
-
 
169
 *  @param packet The packet queue to be released. Input parameter.
-
 
170
 *  @param result The result to be returned. Input parameter.
-
 
171
 *  @return The result parameter.
-
 
172
 */
-
 
173
int tcp_release_and_return( packet_t packet, int result );
-
 
174
 
-
 
175
int tcp_get_packet_dimension( device_id_t device_id, packet_dimension_ref * packet_dimension );
-
 
176
void    tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize );
-
 
177
int tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only );
-
 
178
void    tcp_free_socket_data( socket_core_ref socket );
-
 
179
int tcp_timeout( void * data );
-
 
180
int tcp_release_after_timeout( void * data );
-
 
181
int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error );
-
 
182
int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen );
-
 
183
int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
-
 
184
int tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
-
 
185
packet_t    tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data );
-
 
186
void    tcp_send_packets( device_id_t device_id, packet_t packet );
-
 
187
void    tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header );
-
 
188
packet_t    tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number );
-
 
189
packet_t    tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number );
-
 
190
void    tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number );
-
 
191
int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize );
-
 
192
void    tcp_refresh_socket_data( tcp_socket_data_ref socket_data );
-
 
193
void    tcp_initialize_socket_data( tcp_socket_data_ref socket_data );
-
 
194
int tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen );
-
 
195
int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
-
 
196
int tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
-
 
197
int tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length );
-
 
198
int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length );
71
 
199
 
72
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
200
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
-
 
201
int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
-
 
202
int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog );
-
 
203
int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen );
-
 
204
int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
-
 
205
int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags );
-
 
206
int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen );
-
 
207
int tcp_close_message( socket_cores_ref local_sockets, int socket_id );
-
 
208
 
-
 
209
DEVICE_MAP_IMPLEMENT( packet_dimensions, packet_dimension_t );
-
 
210
 
-
 
211
/** TCP global data.
-
 
212
 */
-
 
213
tcp_globals_t   tcp_globals;
73
 
214
 
74
/** Initializes the module.
215
/** Initializes the module.
75
 */
216
 */
76
int tcp_initialize( async_client_conn_t client_connection ){
217
int tcp_initialize( async_client_conn_t client_connection ){
77
    ERROR_DECLARE;
218
    ERROR_DECLARE;
78
 
219
 
-
 
220
    assert( client_connection );
79
    fibril_rwlock_initialize( & tcp_globals.lock );
221
    fibril_rwlock_initialize( & tcp_globals.lock );
80
    fibril_rwlock_write_lock( & tcp_globals.lock );
222
    fibril_rwlock_write_lock( & tcp_globals.lock );
81
    tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP );
223
    tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP );
82
    if( tcp_globals.icmp_phone < 0 ){
224
    if( tcp_globals.icmp_phone < 0 ){
83
        return tcp_globals.icmp_phone;
225
        return tcp_globals.icmp_phone;
Line 85... Line 227...
85
    tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg );
227
    tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg );
86
    if( tcp_globals.ip_phone < 0 ){
228
    if( tcp_globals.ip_phone < 0 ){
87
        return tcp_globals.ip_phone;
229
        return tcp_globals.ip_phone;
88
    }
230
    }
89
    ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets ));
231
    ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets ));
-
 
232
    if( ERROR_OCCURRED( packet_dimensions_initialize( & tcp_globals.dimensions ))){
-
 
233
        socket_ports_destroy( & tcp_globals.sockets );
-
 
234
        return ERROR_CODE;
-
 
235
    }
90
    tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
236
    tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
91
    fibril_rwlock_write_unlock( & tcp_globals.lock );
237
    fibril_rwlock_write_unlock( & tcp_globals.lock );
92
    return EOK;
238
    return EOK;
93
}
239
}
94
 
240
 
95
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
241
int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
96
    // TODO received
242
    ERROR_DECLARE;
-
 
243
 
-
 
244
    if( receiver != SERVICE_TCP ) return EREFUSED;
-
 
245
    fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
246
    if( ERROR_OCCURRED( tcp_process_packet( device_id, packet, error ))){
-
 
247
        fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
248
    }
97
    //  TODO remove debug dump:
249
    printf( "receive %d \n", ERROR_CODE );
-
 
250
 
-
 
251
    return ERROR_CODE;
-
 
252
}
-
 
253
 
-
 
254
int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error ){
-
 
255
    ERROR_DECLARE;
-
 
256
 
98
    uint8_t *   data;
257
    size_t              length;
-
 
258
    size_t              offset;
-
 
259
    int                 result;
99
    data = packet_get_data( packet );
260
    tcp_header_ref      header;
100
    printf( "Receiving packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ], data[ 16 ], data[ 17 ], data[ 18 ], data[ 19 ], data[ 20 ], data[ 21 ], data[ 22 ], data[ 23 ], data[ 24 ], data[ 25 ], data[ 26 ], data[ 27 ], data[ 28 ], data[ 29 ], data[ 30 ], data[ 31 ], data[ 32 ], data[ 33 ], data[ 34 ], data[ 35 ], data[ 36 ], data[ 37 ], data[ 38 ], data[ 39 ], data[ 40 ], data[ 41 ], data[ 42 ], data[ 43 ], data[ 44 ], data[ 45 ], data[ 46 ], data[ 47 ], data[ 48 ], data[ 49 ], data[ 50 ], data[ 51 ], data[ 52 ], data[ 53 ], data[ 54 ], data[ 55 ], data[ 56 ], data[ 57 ], data[ 58 ], data[ 59 ] );
261
    socket_core_ref     socket;
101
    pq_release( tcp_globals.net_phone, packet_get_id( packet ));
262
    tcp_socket_data_ref socket_data;
-
 
263
    packet_t            next_packet;
-
 
264
    size_t              total_length;
-
 
265
    uint32_t            checksum;
-
 
266
    int                 fragments;
-
 
267
    icmp_type_t         type;
-
 
268
    icmp_code_t         code;
-
 
269
    struct sockaddr *   src;
-
 
270
    struct sockaddr *   dest;
-
 
271
    size_t              addrlen;
102
 
272
 
-
 
273
    printf( "p1 \n" );
-
 
274
    if( error ){
-
 
275
        switch( error ){
-
 
276
            case SERVICE_ICMP:
-
 
277
                // process error
-
 
278
                result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
-
 
279
                if( result < 0 ){
-
 
280
                    return tcp_release_and_return( packet, result );
-
 
281
                }
-
 
282
                length = ( size_t ) result;
-
 
283
                if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
-
 
284
                    return tcp_release_and_return( packet, ERROR_CODE );
-
 
285
                }
-
 
286
                break;
-
 
287
            default:
-
 
288
                return tcp_release_and_return( packet, ENOTSUP );
-
 
289
        }
-
 
290
    }
-
 
291
 
-
 
292
    // TODO process received ipopts?
-
 
293
    result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
-
 
294
//  printf("ip len %d\n", result );
-
 
295
    if( result < 0 ){
-
 
296
        return tcp_release_and_return( packet, result );
-
 
297
    }
-
 
298
    offset = ( size_t ) result;
-
 
299
 
-
 
300
    length = packet_get_data_length( packet );
-
 
301
//  printf("packet len %d\n", length );
-
 
302
    if( length <= 0 ){
-
 
303
        return tcp_release_and_return( packet, EINVAL );
-
 
304
    }
-
 
305
    if( length < sizeof( tcp_header_t ) + offset ){
-
 
306
        return tcp_release_and_return( packet, NO_DATA );
-
 
307
    }
-
 
308
 
-
 
309
    // trim all but TCP header
-
 
310
    if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){
-
 
311
        return tcp_release_and_return( packet, ERROR_CODE );
-
 
312
    }
-
 
313
 
-
 
314
    // get tcp header
-
 
315
    header = ( tcp_header_ref ) packet_get_data( packet );
-
 
316
    if( ! header ){
-
 
317
        return tcp_release_and_return( packet, NO_DATA );
-
 
318
    }
-
 
319
//  printf( "header len %d, port %d \n", TCP_HEADER_LENGTH( header ), ntohs( header->destination_port ));
-
 
320
 
-
 
321
    result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
-
 
322
    if( result <= 0 ){
-
 
323
        return tcp_release_and_return( packet, result );
-
 
324
    }
-
 
325
    addrlen = ( size_t ) result;
-
 
326
 
-
 
327
    if( ERROR_OCCURRED( tl_set_address_port( src, addrlen, ntohs( header->source_port )))){
-
 
328
        return tcp_release_and_return( packet, ERROR_CODE );
-
 
329
    }
-
 
330
 
-
 
331
    // find the destination socket
-
 
332
    socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), ( const char * ) src, addrlen );
-
 
333
    if( ! socket ){
-
 
334
//      printf("listening?\n");
-
 
335
        // find the listening destination socket
-
 
336
        socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0 );
-
 
337
        if( ! socket ){
-
 
338
            if( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ) == EOK ){
-
 
339
                icmp_destination_unreachable_msg( tcp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
-
 
340
            }
-
 
341
            return EADDRNOTAVAIL;
-
 
342
        }
-
 
343
    }
-
 
344
    printf("socket id %d\n", socket->socket_id );
-
 
345
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
346
    assert( socket_data );
-
 
347
 
-
 
348
    // some data received, clear the timeout counter
-
 
349
    socket_data->timeout_count = 0;
-
 
350
 
-
 
351
    // count the received packet fragments
-
 
352
    next_packet = packet;
-
 
353
    fragments = 0;
-
 
354
    checksum = 0;
-
 
355
    total_length = 0;
-
 
356
    do{
-
 
357
        ++ fragments;
-
 
358
        length = packet_get_data_length( next_packet );
-
 
359
        if( length <= 0 ){
-
 
360
            return tcp_release_and_return( packet, NO_DATA );
-
 
361
        }
-
 
362
        total_length += length;
-
 
363
        // add partial checksum if set
-
 
364
        if( ! error ){
-
 
365
            checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
-
 
366
        }
-
 
367
    }while(( next_packet = pq_next( next_packet )));
-
 
368
//  printf( "fragments %d of %d bytes\n", fragments, total_length );
-
 
369
 
-
 
370
//  printf("lock?\n");
-
 
371
    fibril_rwlock_write_lock( socket_data->local_lock );
-
 
372
//  printf("locked\n");
-
 
373
    if( ! error ){
-
 
374
        if( socket_data->state == TCP_SOCKET_LISTEN ){
-
 
375
            if( socket_data->pseudo_header ){
-
 
376
                free( socket_data->pseudo_header );
-
 
377
                socket_data->pseudo_header = NULL;
-
 
378
                socket_data->headerlen = 0;
-
 
379
            }
-
 
380
            if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_TCP, src, addrlen, dest, addrlen, total_length, & socket_data->pseudo_header, & socket_data->headerlen ))){
-
 
381
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
382
                return tcp_release_and_return( packet, ERROR_CODE );
-
 
383
            }
-
 
384
        }else if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, total_length ))){
-
 
385
            fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
386
            return tcp_release_and_return( packet, ERROR_CODE );
-
 
387
        }
-
 
388
        checksum = compute_checksum( checksum, socket_data->pseudo_header, socket_data->headerlen );
-
 
389
        if( flip_checksum( compact_checksum( checksum ))){
-
 
390
            printf( "checksum err %x -> %x\n", header->checksum, flip_checksum( compact_checksum( checksum )));
-
 
391
            fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
392
            if( ! ERROR_OCCURRED( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ))){
-
 
393
                // checksum error ICMP
-
 
394
                icmp_parameter_problem_msg( tcp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet );
-
 
395
            }
-
 
396
            return EINVAL;
-
 
397
        }
-
 
398
    }
-
 
399
 
-
 
400
    fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
401
 
-
 
402
    // TODO error reporting/handling
-
 
403
//  printf( "st %d\n", socket_data->state );
-
 
404
    switch( socket_data->state ){
-
 
405
        case TCP_SOCKET_LISTEN:
-
 
406
            ERROR_CODE = tcp_process_listen( socket, socket_data, header, packet, src, dest, addrlen );
-
 
407
            break;
-
 
408
        case TCP_SOCKET_SYN_RECEIVED:
-
 
409
            ERROR_CODE = tcp_process_syn_received( socket, socket_data, header, packet );
-
 
410
            break;
-
 
411
        case TCP_SOCKET_SYN_SENT:
-
 
412
            ERROR_CODE = tcp_process_syn_sent( socket, socket_data, header, packet );
-
 
413
            break;
-
 
414
        case TCP_SOCKET_FIN_WAIT_1:
-
 
415
            // ack changing the state to FIN_WAIT_2 gets processed later
-
 
416
        case TCP_SOCKET_FIN_WAIT_2:
-
 
417
            // fin changing state to LAST_ACK gets processed later
-
 
418
        case TCP_SOCKET_LAST_ACK:
-
 
419
            // ack releasing the socket get processed later
-
 
420
        case TCP_SOCKET_CLOSING:
-
 
421
            // ack releasing the socket gets processed later
-
 
422
        case TCP_SOCKET_ESTABLISHED:
-
 
423
            ERROR_CODE = tcp_process_established( socket, socket_data, header, packet, fragments, total_length );
-
 
424
            break;
-
 
425
        default:
-
 
426
            pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
427
    }
-
 
428
 
-
 
429
    if( ERROR_CODE != EOK ){
-
 
430
        printf( "process %d\n", ERROR_CODE );
-
 
431
        fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
432
    }
103
    return EOK;
433
    return EOK;
104
}
434
}
105
 
435
 
-
 
436
int tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length ){
-
 
437
    ERROR_DECLARE;
-
 
438
 
-
 
439
    packet_t    next_packet;
-
 
440
    packet_t    tmp_packet;
-
 
441
    uint32_t    old_incoming;
-
 
442
    size_t      order;
-
 
443
    uint32_t    sequence_number;
-
 
444
    size_t      length;
-
 
445
    size_t      offset;
-
 
446
    uint32_t    new_sequence_number;
-
 
447
 
-
 
448
    assert( socket );
-
 
449
    assert( socket_data );
-
 
450
    assert( socket->specific_data == socket_data );
-
 
451
    assert( header );
-
 
452
    assert( packet );
-
 
453
 
-
 
454
    new_sequence_number = ntohl( header->sequence_number );
-
 
455
    old_incoming = socket_data->next_incoming;
-
 
456
 
-
 
457
    if( header->finalize ){
-
 
458
        socket_data->fin_incoming = new_sequence_number;
-
 
459
    }
-
 
460
 
-
 
461
//  printf( "pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length );
-
 
462
    // trim begining if containing expected data
-
 
463
    if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length )){
-
 
464
        // get the acknowledged offset
-
 
465
        if( socket_data->next_incoming < new_sequence_number ){
-
 
466
            offset = new_sequence_number - socket_data->next_incoming;
-
 
467
        }else{
-
 
468
            offset = socket_data->next_incoming - new_sequence_number;
-
 
469
        }
-
 
470
//      printf( "offset %d\n", offset );
-
 
471
        new_sequence_number += offset;
-
 
472
        total_length -= offset;
-
 
473
        length = packet_get_data_length( packet );
-
 
474
        // trim the acknowledged data
-
 
475
        while( length <= offset ){
-
 
476
            // release the acknowledged packets
-
 
477
            next_packet = pq_next( packet );
-
 
478
            pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
479
            packet = next_packet;
-
 
480
            offset -= length;
-
 
481
            length = packet_get_data_length( packet );
-
 
482
        }
-
 
483
        if(( offset > 0 )
-
 
484
        && ( ERROR_OCCURRED( packet_trim( packet, offset, 0 )))){
-
 
485
            return tcp_release_and_return( packet, ERROR_CODE );
-
 
486
        }
-
 
487
        assert( new_sequence_number == socket_data->next_incoming );
-
 
488
    }
-
 
489
 
-
 
490
    // release if overflowing the window
-
 
491
//  if( IS_IN_INTERVAL_OVERFLOW( socket_data->next_incoming + socket_data->window, new_sequence_number, new_sequence_number + total_length )){
-
 
492
//      return tcp_release_and_return( packet, EOVERFLOW );
-
 
493
//  }
-
 
494
 
-
 
495
/*
-
 
496
    // trim end if overflowing the window
-
 
497
    if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length )){
-
 
498
        // get the allowed data length
-
 
499
        if( socket_data->next_incoming + socket_data->window < new_sequence_number ){
-
 
500
            offset = new_sequence_number - socket_data->next_incoming + socket_data->window;
-
 
501
        }else{
-
 
502
            offset = socket_data->next_incoming + socket_data->window - new_sequence_number;
-
 
503
        }
-
 
504
        next_packet = packet;
-
 
505
        // trim the overflowing data
-
 
506
        while( next_packet && ( offset > 0 )){
-
 
507
            length = packet_get_data_length( packet );
-
 
508
            if( length <= offset ){
-
 
509
                next_packet = pq_next( next_packet );
-
 
510
            }else if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - offset ))){
-
 
511
                return tcp_release_and_return( packet, ERROR_CODE );
-
 
512
            }
-
 
513
            offset -= length;
-
 
514
            total_length -= length - offset;
-
 
515
        }
-
 
516
        // release the overflowing packets
-
 
517
        next_packet = pq_next( next_packet );
-
 
518
        if( next_packet ){
-
 
519
            tmp_packet = next_packet;
-
 
520
            next_packet = pq_next( next_packet );
-
 
521
            pq_insert_after( tmp_packet, next_packet );
-
 
522
            pq_release( tcp_globals.net_phone, packet_get_id( tmp_packet ));
-
 
523
        }
-
 
524
        assert( new_sequence_number + total_length == socket_data->next_incoming + socket_data->window );
-
 
525
    }
-
 
526
*/
-
 
527
    // the expected one arrived?
-
 
528
    if( new_sequence_number == socket_data->next_incoming ){
-
 
529
        printf("expected\n");
-
 
530
        // process acknowledgement
-
 
531
        tcp_process_acknowledgement( socket, socket_data, header );
-
 
532
 
-
 
533
        // remove the header
-
 
534
        total_length -= TCP_HEADER_LENGTH( header );
-
 
535
        if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){
-
 
536
            return tcp_release_and_return( packet, ERROR_CODE );
-
 
537
        }
-
 
538
 
-
 
539
        if( total_length ){
-
 
540
            ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, fragments, total_length ));
-
 
541
        }else{
-
 
542
            total_length = 1;
-
 
543
        }
-
 
544
        socket_data->next_incoming = old_incoming + total_length;
-
 
545
        packet = socket_data->incoming;
-
 
546
        while( packet ){
-
 
547
            if( ERROR_OCCURRED( pq_get_order( socket_data->incoming, & order, NULL ))){
-
 
548
                // remove the corrupted packet
-
 
549
                next_packet = pq_detach( packet );
-
 
550
                if( packet == socket_data->incoming ){
-
 
551
                    socket_data->incoming = next_packet;
-
 
552
                }
-
 
553
                pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
554
                packet = next_packet;
-
 
555
                continue;
-
 
556
            }
-
 
557
            sequence_number = ( uint32_t ) order;
-
 
558
            if( IS_IN_INTERVAL_OVERFLOW( sequence_number, old_incoming, socket_data->next_incoming )){
-
 
559
                // move to the next
-
 
560
                packet = pq_next( packet );
-
 
561
            // coninual data?
-
 
562
            }else if( IS_IN_INTERVAL_OVERFLOW( old_incoming, sequence_number, socket_data->next_incoming )){
-
 
563
                // detach the packet
-
 
564
                next_packet = pq_detach( packet );
-
 
565
                if( packet == socket_data->incoming ){
-
 
566
                    socket_data->incoming = next_packet;
-
 
567
                }
-
 
568
                // get data length
-
 
569
                length = packet_get_data_length( packet );
-
 
570
                new_sequence_number = sequence_number + length;
-
 
571
                if( length <= 0 ){
-
 
572
                    // remove the empty packet
-
 
573
                    pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
574
                    packet = next_packet;
-
 
575
                    continue;
-
 
576
                }
-
 
577
                // exactly following
-
 
578
                if( sequence_number == socket_data->next_incoming ){
-
 
579
                    // queue received data
-
 
580
                    ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet )));
-
 
581
                    socket_data->next_incoming = new_sequence_number;
-
 
582
                    packet = next_packet;
-
 
583
                    continue;
-
 
584
                // at least partly following data?
-
 
585
                }else if( IS_IN_INTERVAL_OVERFLOW( sequence_number, socket_data->next_incoming, new_sequence_number )){
-
 
586
                    if( socket_data->next_incoming < new_sequence_number ){
-
 
587
                        length = new_sequence_number - socket_data->next_incoming;
-
 
588
                    }else{
-
 
589
                        length = socket_data->next_incoming - new_sequence_number;
-
 
590
                    }
-
 
591
                    if( ! ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
-
 
592
                        // queue received data
-
 
593
                        ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet )));
-
 
594
                        socket_data->next_incoming = new_sequence_number;
-
 
595
                        packet = next_packet;
-
 
596
                        continue;
-
 
597
                    }
-
 
598
                }
-
 
599
                // remove the duplicit or corrupted packet
-
 
600
                pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
601
                packet = next_packet;
-
 
602
                continue;
-
 
603
            }else{
-
 
604
                break;
-
 
605
            }
-
 
606
        }
-
 
607
    }else if( IS_IN_INTERVAL( socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window )){
-
 
608
        printf("in window\n");
-
 
609
        // process acknowledgement
-
 
610
        tcp_process_acknowledgement( socket, socket_data, header );
-
 
611
 
-
 
612
        // remove the header
-
 
613
        total_length -= TCP_HEADER_LENGTH( header );
-
 
614
        if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){
-
 
615
            return tcp_release_and_return( packet, ERROR_CODE );
-
 
616
        }
-
 
617
 
-
 
618
        next_packet = pq_detach( packet );
-
 
619
        length = packet_get_data_length( packet );
-
 
620
        tmp_packet = pq_add( socket_data->incoming, packet, new_sequence_number, length );
-
 
621
        if( ! tmp_packet ){
-
 
622
            // remove the corrupted packets
-
 
623
            pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
624
            pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
-
 
625
        }else{
-
 
626
            socket_data->incoming = tmp_packet;
-
 
627
            while( next_packet ){
-
 
628
                new_sequence_number += length;
-
 
629
                tmp_packet = pq_detach( next_packet );
-
 
630
                length = packet_get_data_length( next_packet );
-
 
631
                if( ERROR_OCCURRED( pq_set_order( next_packet, new_sequence_number, length ))
-
 
632
                || ERROR_OCCURRED( pq_insert_after( packet, next_packet ))){
-
 
633
                    pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
-
 
634
                }
-
 
635
                next_packet = tmp_packet;
-
 
636
            }
-
 
637
        }
-
 
638
    }else{
-
 
639
        printf("unexpected\n");
-
 
640
        // release duplicite or restricted
-
 
641
        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
642
    }
-
 
643
 
-
 
644
    // change state according to the acknowledging incoming fin
-
 
645
    if( IS_IN_INTERVAL_OVERFLOW( old_incoming, socket_data->fin_incoming, socket_data->next_incoming )){
-
 
646
        switch( socket_data->state ){
-
 
647
            case TCP_SOCKET_FIN_WAIT_1:
-
 
648
            case TCP_SOCKET_FIN_WAIT_2:
-
 
649
            case TCP_SOCKET_CLOSING:
-
 
650
                socket_data->state = TCP_SOCKET_CLOSING;
-
 
651
                break;
-
 
652
            //case TCP_ESTABLISHED:
-
 
653
            default:
-
 
654
                socket_data->state = TCP_SOCKET_CLOSE_WAIT;
-
 
655
                break;
-
 
656
        }
-
 
657
    }
-
 
658
 
-
 
659
    packet = tcp_get_packets_to_send( socket, socket_data );
-
 
660
    if( ! packet ){
-
 
661
        // create the notification packet
-
 
662
        ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 0 ));
-
 
663
        ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, 1 ));
-
 
664
        packet = tcp_send_prepare_packet( socket, socket_data, packet, 1, socket_data->last_outgoing + 1 );
-
 
665
    }
-
 
666
    fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
667
    // send the packet
-
 
668
    tcp_send_packets( socket_data->device_id, packet );
-
 
669
    return EOK;
-
 
670
}
-
 
671
 
-
 
672
int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length ){
-
 
673
    ERROR_DECLARE;
-
 
674
 
-
 
675
    assert( socket );
-
 
676
    assert( socket_data );
-
 
677
    assert( socket->specific_data == socket_data );
-
 
678
    assert( packet );
-
 
679
    assert( fragments >= 1 );
-
 
680
    assert( socket_data->window > total_length );
-
 
681
 
-
 
682
    // queue the received packet
-
 
683
    if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
-
 
684
        return tcp_release_and_return( packet, ERROR_CODE );
-
 
685
    }
-
 
686
 
-
 
687
    // decrease the window size
-
 
688
    socket_data->window -= total_length;
-
 
689
 
-
 
690
    // notify the destination socket
-
 
691
    async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
-
 
692
    return EOK;
-
 
693
}
-
 
694
 
-
 
695
int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){
-
 
696
    ERROR_DECLARE;
-
 
697
 
-
 
698
    packet_t    next_packet;
-
 
699
 
-
 
700
    assert( socket );
-
 
701
    assert( socket_data );
-
 
702
    assert( socket->specific_data == socket_data );
-
 
703
    assert( header );
-
 
704
    assert( packet );
-
 
705
 
-
 
706
    if( header->synchronize ){
-
 
707
        // process acknowledgement
-
 
708
        tcp_process_acknowledgement( socket, socket_data, header );
-
 
709
 
-
 
710
        socket_data->next_incoming = ntohl( header->sequence_number ) + 1;
-
 
711
        // release additional packets
-
 
712
        next_packet = pq_detach( packet );
-
 
713
        if( next_packet ){
-
 
714
            pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
-
 
715
        }
-
 
716
        // trim if longer than the header
-
 
717
        if(( packet_get_data_length( packet ) > sizeof( * header ))
-
 
718
        && ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){
-
 
719
            return tcp_release_and_return( packet, ERROR_CODE );
-
 
720
        }
-
 
721
        tcp_prepare_operation_header( socket, socket_data, header, 0, 0 );
-
 
722
        fibril_mutex_lock( & socket_data->operation.mutex );
-
 
723
        socket_data->operation.result = tcp_queue_packet( socket, socket_data, packet, 1 );
-
 
724
        if( socket_data->operation.result == EOK ){
-
 
725
            socket_data->state = TCP_SOCKET_ESTABLISHED;
-
 
726
            packet = tcp_get_packets_to_send( socket, socket_data );
-
 
727
            if( packet ){
-
 
728
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
729
                // send the packet
-
 
730
                tcp_send_packets( socket_data->device_id, packet );
-
 
731
                // signal the result
-
 
732
                fibril_condvar_signal( & socket_data->operation.condvar );
-
 
733
                fibril_mutex_unlock( & socket_data->operation.mutex );
-
 
734
                return EOK;
-
 
735
            }
-
 
736
        }
-
 
737
        fibril_mutex_unlock( & socket_data->operation.mutex );
-
 
738
    }
-
 
739
    return tcp_release_and_return( packet, EINVAL );
-
 
740
}
-
 
741
 
-
 
742
int tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen ){
-
 
743
    ERROR_DECLARE;
-
 
744
 
-
 
745
    packet_t            next_packet;
-
 
746
    socket_core_ref     socket;
-
 
747
    tcp_socket_data_ref socket_data;
-
 
748
    int                 socket_id;
-
 
749
    int                 listening_socket_id = listening_socket->socket_id;
-
 
750
    int                 listening_port = listening_socket->port;
-
 
751
 
-
 
752
    assert( listening_socket );
-
 
753
    assert( listening_socket_data );
-
 
754
    assert( listening_socket->specific_data == listening_socket_data );
-
 
755
    assert( header );
-
 
756
    assert( packet );
-
 
757
 
-
 
758
//  printf( "syn %d\n", header->synchronize );
-
 
759
    if( header->synchronize ){
-
 
760
        socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data ));
-
 
761
        if( ! socket_data ){
-
 
762
            return tcp_release_and_return( packet, ENOMEM );
-
 
763
        }else{
-
 
764
            tcp_initialize_socket_data( socket_data );
-
 
765
            socket_data->local_lock = listening_socket_data->local_lock;
-
 
766
            socket_data->local_sockets = listening_socket_data->local_sockets;
-
 
767
            socket_data->listening_socket_id = listening_socket->socket_id;
-
 
768
 
-
 
769
            socket_data->next_incoming = ntohl( header->sequence_number );
-
 
770
            socket_data->treshold = socket_data->next_incoming + ntohs( header->window );
-
 
771
 
-
 
772
            socket_data->addrlen = addrlen;
-
 
773
            socket_data->addr = malloc( socket_data->addrlen );
-
 
774
            if( ! socket_data->addr ){
-
 
775
                free( socket_data );
-
 
776
                return tcp_release_and_return( packet, ENOMEM );
-
 
777
            }
-
 
778
            memcpy( socket_data->addr, src, socket_data->addrlen );
-
 
779
 
-
 
780
            socket_data->dest_port = ntohs( header->source_port );
-
 
781
            if( ERROR_OCCURRED( tl_set_address_port( socket_data->addr, socket_data->addrlen, socket_data->dest_port ))){
-
 
782
                free( socket_data->addr );
-
 
783
                free( socket_data );
-
 
784
                pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
785
                return ERROR_CODE;
-
 
786
            }
-
 
787
 
-
 
788
//          printf( "addr %p\n", socket_data->addr, socket_data->addrlen );
-
 
789
            // create a socket
-
 
790
            if( ERROR_OCCURRED( socket_create( socket_data->local_sockets, listening_socket->phone, socket_data, & socket_id ))){
-
 
791
                free( socket_data->addr );
-
 
792
                free( socket_data );
-
 
793
                return tcp_release_and_return( packet, ERROR_CODE );
-
 
794
            }
-
 
795
 
-
 
796
            printf("new_sock %d\n", socket_id);
-
 
797
            socket_data->pseudo_header = listening_socket_data->pseudo_header;
-
 
798
            socket_data->headerlen = listening_socket_data->headerlen;
-
 
799
            listening_socket_data->pseudo_header = NULL;
-
 
800
            listening_socket_data->headerlen = 0;
-
 
801
 
-
 
802
            fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
803
//          printf("list lg\n");
-
 
804
            fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
805
//          printf("list locked\n");
-
 
806
            // find the destination socket
-
 
807
            listening_socket = socket_port_find( & tcp_globals.sockets, listening_port, SOCKET_MAP_KEY_LISTENING, 0 );
-
 
808
            if(( ! listening_socket ) || ( listening_socket->socket_id != listening_socket_id )){
-
 
809
                fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
810
                // a shadow may remain until app hangs up
-
 
811
                return tcp_release_and_return( packet, EOK/*ENOTSOCK*/ );
-
 
812
            }
-
 
813
//          printf("port %d\n", listening_socket->port );
-
 
814
            listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data;
-
 
815
            assert( listening_socket_data );
-
 
816
 
-
 
817
//          printf("list ll\n");
-
 
818
            fibril_rwlock_write_lock( listening_socket_data->local_lock );
-
 
819
//          printf("list locked\n");
-
 
820
 
-
 
821
            socket = socket_cores_find( listening_socket_data->local_sockets, socket_id );
-
 
822
            if( ! socket ){
-
 
823
                // where is the socket?!?
-
 
824
                fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
825
                return ENOTSOCK;
-
 
826
            }
-
 
827
            socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
828
            assert( socket_data );
-
 
829
 
-
 
830
//          uint8_t * data = socket_data->addr;
-
 
831
//          printf( "addr %d of %x %x %x %x-%x %x %x %x-%x %x %x %x-%x %x %x %x\n", socket_data->addrlen, data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ] );
-
 
832
 
-
 
833
            ERROR_CODE = socket_port_add( & tcp_globals.sockets, listening_port, socket, ( const char * ) socket_data->addr, socket_data->addrlen );
-
 
834
            assert( socket == socket_port_find( & tcp_globals.sockets, listening_port, ( const char * ) socket_data->addr, socket_data->addrlen ));
-
 
835
            //ERROR_CODE = socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port );
-
 
836
            //tcp_globals.last_used_port = socket->port;
-
 
837
//          printf("bound %d\n", socket->port );
-
 
838
            fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
839
            if( ERROR_CODE != EOK ){
-
 
840
                socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
841
                return tcp_release_and_return( packet, ERROR_CODE );
-
 
842
            }
-
 
843
 
-
 
844
            socket_data->state = TCP_SOCKET_LISTEN;
-
 
845
            socket_data->next_incoming = ntohl( header->sequence_number ) + 1;
-
 
846
            // release additional packets
-
 
847
            next_packet = pq_detach( packet );
-
 
848
            if( next_packet ){
-
 
849
                pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
-
 
850
            }
-
 
851
            // trim if longer than the header
-
 
852
            if(( packet_get_data_length( packet ) > sizeof( * header ))
-
 
853
            && ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){
-
 
854
                socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
855
                return tcp_release_and_return( packet, ERROR_CODE );
-
 
856
            }
-
 
857
            tcp_prepare_operation_header( socket, socket_data, header, 1, 0 );
-
 
858
            if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 ))){
-
 
859
                socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
860
                return ERROR_CODE;
-
 
861
            }
-
 
862
            packet = tcp_get_packets_to_send( socket, socket_data );
-
 
863
//          printf("send %d\n", packet_get_id( packet ));
-
 
864
            if( ! packet ){
-
 
865
                socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
866
                return EINVAL;
-
 
867
            }else{
-
 
868
                socket_data->state = TCP_SOCKET_SYN_RECEIVED;
-
 
869
//              printf("unlock\n");
-
 
870
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
871
                // send the packet
-
 
872
                tcp_send_packets( socket_data->device_id, packet );
-
 
873
                return EOK;
-
 
874
            }
-
 
875
        }
-
 
876
    }
-
 
877
    return tcp_release_and_return( packet, EINVAL );
-
 
878
}
-
 
879
 
-
 
880
int tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){
-
 
881
    ERROR_DECLARE;
-
 
882
 
-
 
883
    socket_core_ref     listening_socket;
-
 
884
    tcp_socket_data_ref listening_socket_data;
-
 
885
 
-
 
886
    assert( socket );
-
 
887
    assert( socket_data );
-
 
888
    assert( socket->specific_data == socket_data );
-
 
889
    assert( header );
-
 
890
    assert( packet );
-
 
891
 
-
 
892
    printf("syn_rec\n");
-
 
893
    if( header->acknowledge ){
-
 
894
        // process acknowledgement
-
 
895
        tcp_process_acknowledgement( socket, socket_data, header );
-
 
896
 
-
 
897
        socket_data->next_incoming = ntohl( header->sequence_number );// + 1;
-
 
898
        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
899
        socket_data->state = TCP_SOCKET_ESTABLISHED;
-
 
900
        listening_socket = socket_cores_find( socket_data->local_sockets, socket_data->listening_socket_id );
-
 
901
        if( listening_socket ){
-
 
902
            listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data;
-
 
903
            assert( listening_socket_data );
-
 
904
 
-
 
905
            // queue the received packet
-
 
906
            if( ! ERROR_OCCURRED( dyn_fifo_push( & listening_socket->accepted, socket->socket_id, listening_socket_data->backlog ))){
-
 
907
                // notify the destination socket
-
 
908
                async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, 0, 0, 0, ( ipcarg_t ) socket->socket_id );
-
 
909
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
910
                return EOK;
-
 
911
            }
-
 
912
        }
-
 
913
        // send FIN
-
 
914
        socket_data->state = TCP_SOCKET_FIN_WAIT_1;
-
 
915
 
-
 
916
        // create the notification packet
-
 
917
        ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 ));
-
 
918
 
-
 
919
        // send the packet
-
 
920
        ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 ));
-
 
921
 
-
 
922
        // flush packets
-
 
923
        packet = tcp_get_packets_to_send( socket, socket_data );
-
 
924
        fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
925
        if( packet ){
-
 
926
            // send the packet
-
 
927
            tcp_send_packets( socket_data->device_id, packet );
-
 
928
        }
-
 
929
        return EOK;
-
 
930
    }else{
-
 
931
        return tcp_release_and_return( packet, EINVAL );
-
 
932
    }
-
 
933
    return EINVAL;
-
 
934
}
-
 
935
 
-
 
936
void tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header ){
-
 
937
    size_t      number;
-
 
938
    size_t      length;
-
 
939
    packet_t    packet;
-
 
940
    packet_t    next;
-
 
941
    packet_t    acknowledged = NULL;
-
 
942
    packet_t    first;
-
 
943
    uint32_t    old;
-
 
944
 
-
 
945
    assert( socket );
-
 
946
    assert( socket_data );
-
 
947
    assert( socket->specific_data == socket_data );
-
 
948
    assert( header );
-
 
949
 
-
 
950
    if( header->acknowledge ){
-
 
951
        number = ntohl( header->acknowledgement_number );
-
 
952
        // if more data acknowledged
-
 
953
        if( number != socket_data->expected ){
-
 
954
            old = socket_data->expected;
-
 
955
            if( IS_IN_INTERVAL_OVERFLOW( old, socket_data->fin_outgoing, number )){
-
 
956
                switch( socket_data->state ){
-
 
957
                    case TCP_SOCKET_FIN_WAIT_1:
-
 
958
                        socket_data->state = TCP_SOCKET_FIN_WAIT_2;
-
 
959
                        break;
-
 
960
                    case TCP_SOCKET_LAST_ACK:
-
 
961
                    case TCP_SOCKET_CLOSING:
-
 
962
                        // fin acknowledged - release the socket in another fibril
-
 
963
                        tcp_prepare_timeout( tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true );
-
 
964
                        break;
-
 
965
                    default:
-
 
966
                        break;
-
 
967
                }
-
 
968
            }
-
 
969
            // update the treshold if higher than set
-
 
970
            if( number + ntohs( header->window ) > socket_data->expected + socket_data->treshold ){
-
 
971
                socket_data->treshold = number + ntohs( header->window ) - socket_data->expected;
-
 
972
            }
-
 
973
            // set new expected sequence number
-
 
974
            socket_data->expected = number;
-
 
975
            socket_data->expected_count = 1;
-
 
976
            packet = socket_data->outgoing;
-
 
977
            while( pq_get_order( packet, & number, & length ) == EOK ){
-
 
978
                if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) old, ( uint32_t )( number + length ), ( uint32_t ) socket_data->expected )){
-
 
979
                    next = pq_detach( packet );
-
 
980
                    if( packet == socket_data->outgoing ){
-
 
981
                        socket_data->outgoing = next;
-
 
982
                    }
-
 
983
                    // add to acknowledged or release
-
 
984
                    first = pq_add( acknowledged, packet, 0, 0 );
-
 
985
                    if( first ){
-
 
986
                        acknowledged = first;
-
 
987
                    }else{
-
 
988
                        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
989
                    }
-
 
990
                    packet = next;
-
 
991
                }else if( old < socket_data->expected ){
-
 
992
                    break;
-
 
993
                }
-
 
994
            }
-
 
995
            // release acknowledged
-
 
996
            if( acknowledged ){
-
 
997
                pq_release( tcp_globals.net_phone, packet_get_id( acknowledged ));
-
 
998
            }
-
 
999
            return;
-
 
1000
        // if the same as the previous time
-
 
1001
        }else if( number == socket_data->expected ){
-
 
1002
            // increase the counter
-
 
1003
            ++ socket_data->expected_count;
-
 
1004
            if( socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT ){
-
 
1005
                socket_data->expected_count = 1;
-
 
1006
                // TODO retransmit lock
-
 
1007
                //tcp_retransmit_packet( socket, socket_data, number );
-
 
1008
            }
-
 
1009
        }
-
 
1010
    }
-
 
1011
}
-
 
1012
 
106
int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
1013
int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
107
    ERROR_DECLARE;
1014
    ERROR_DECLARE;
108
 
1015
 
109
    packet_t    packet;
1016
    packet_t    packet;
110
 
1017
 
-
 
1018
    assert( call );
-
 
1019
    assert( answer );
-
 
1020
    assert( answer_count );
-
 
1021
 
111
    * answer_count = 0;
1022
    * answer_count = 0;
112
    switch( IPC_GET_METHOD( * call )){
1023
    switch( IPC_GET_METHOD( * call )){
113
        case IPC_M_PHONE_HUNGUP:
-
 
114
            return EOK;
-
 
115
        case NET_TL_RECEIVED:
1024
        case NET_TL_RECEIVED:
-
 
1025
            //fibril_rwlock_read_lock( & tcp_globals.lock );
116
            ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call )));
1026
            if( ! ERROR_OCCURRED( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
117
            return tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call ));
1027
                ERROR_CODE = tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call ));
-
 
1028
            }
-
 
1029
            //fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1030
            return ERROR_CODE;
-
 
1031
        case IPC_M_CONNECT_TO_ME:
-
 
1032
            return tcp_process_client_messages( callid, * call );
118
    }
1033
    }
119
    return ENOTSUP;
1034
    return ENOTSUP;
120
}
1035
}
121
 
1036
 
-
 
1037
void tcp_refresh_socket_data( tcp_socket_data_ref socket_data ){
-
 
1038
    assert( socket_data );
-
 
1039
 
-
 
1040
    bzero( socket_data, sizeof( * socket_data ));
-
 
1041
    socket_data->state = TCP_SOCKET_INITIAL;
-
 
1042
    socket_data->device_id = -1;
-
 
1043
    socket_data->window = NET_DEFAULT_TCP_WINDOW;
-
 
1044
    socket_data->treshold = socket_data->window;
-
 
1045
    socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
-
 
1046
    socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
-
 
1047
    socket_data->acknowledged = socket_data->last_outgoing;
-
 
1048
    socket_data->next_outgoing = socket_data->last_outgoing + 1;
-
 
1049
    socket_data->expected = socket_data->next_outgoing;
-
 
1050
}
-
 
1051
 
-
 
1052
void tcp_initialize_socket_data( tcp_socket_data_ref socket_data ){
-
 
1053
    assert( socket_data );
-
 
1054
 
-
 
1055
    tcp_refresh_socket_data( socket_data );
-
 
1056
    fibril_mutex_initialize( & socket_data->operation.mutex );
-
 
1057
    fibril_condvar_initialize( & socket_data->operation.condvar );
-
 
1058
}
-
 
1059
 
-
 
1060
int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
-
 
1061
    int                     res;
-
 
1062
    bool                    keep_on_going = true;
-
 
1063
    socket_cores_t          local_sockets;
-
 
1064
    int                     app_phone = IPC_GET_PHONE( & call );
-
 
1065
    struct sockaddr *       addr;
-
 
1066
    size_t                  addrlen;
-
 
1067
    fibril_rwlock_t         lock;
-
 
1068
    ipc_call_t              answer;
-
 
1069
    int                     answer_count;
-
 
1070
    tcp_socket_data_ref     socket_data;
-
 
1071
    socket_core_ref         socket;
-
 
1072
 
-
 
1073
    /*
-
 
1074
     * Accept the connection
-
 
1075
     *  - Answer the first IPC_M_CONNECT_ME_TO call.
-
 
1076
     */
-
 
1077
    ipc_answer_0( callid, EOK );
-
 
1078
 
-
 
1079
    socket_cores_initialize( & local_sockets );
-
 
1080
    fibril_rwlock_initialize( & lock );
-
 
1081
 
-
 
1082
    while( keep_on_going ){
-
 
1083
        // refresh data
-
 
1084
        refresh_answer( & answer, & answer_count );
-
 
1085
 
-
 
1086
        callid = async_get_call( & call );
-
 
1087
//      printf( "message %d\n", IPC_GET_METHOD( * call ));
-
 
1088
 
-
 
1089
        switch( IPC_GET_METHOD( call )){
-
 
1090
            case IPC_M_PHONE_HUNGUP:
-
 
1091
                keep_on_going = false;
-
 
1092
                res = EOK;
-
 
1093
                break;
-
 
1094
            case NET_SOCKET:
-
 
1095
                socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data ));
-
 
1096
                if( ! socket_data ){
-
 
1097
                    res = ENOMEM;
-
 
1098
                }else{
-
 
1099
                    tcp_initialize_socket_data( socket_data );
-
 
1100
                    socket_data->local_lock = & lock;
-
 
1101
                    socket_data->local_sockets = & local_sockets;
-
 
1102
                    fibril_rwlock_write_lock( & lock );
-
 
1103
                    res = socket_create( & local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID( answer ));
-
 
1104
                    fibril_rwlock_write_unlock( & lock );
-
 
1105
                    if( res == EOK ){
-
 
1106
                        * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( tcp_header_t );
-
 
1107
                        * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
-
 
1108
                        answer_count = 3;
-
 
1109
                    }else{
-
 
1110
                        free( socket_data );
-
 
1111
                    }
-
 
1112
                }
-
 
1113
                break;
-
 
1114
            case NET_SOCKET_BIND:
-
 
1115
                res = data_receive(( void ** ) & addr, & addrlen );
-
 
1116
                if( res == EOK ){
-
 
1117
                    fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1118
                    fibril_rwlock_write_lock( & lock );
-
 
1119
                    res = socket_bind( & local_sockets, & tcp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port );
-
 
1120
                    if( res == EOK ){
-
 
1121
                        socket = socket_cores_find( & local_sockets, SOCKET_GET_SOCKET_ID( call ));
-
 
1122
                        if( socket ){
-
 
1123
                            socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1124
                            assert( socket_data );
-
 
1125
                            socket_data->state = TCP_SOCKET_LISTEN;
-
 
1126
                        }
-
 
1127
                    }
-
 
1128
                    fibril_rwlock_write_unlock( & lock );
-
 
1129
                    fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1130
                    free( addr );
-
 
1131
                }
-
 
1132
                break;
-
 
1133
            case NET_SOCKET_LISTEN:
-
 
1134
                fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1135
//              fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1136
                fibril_rwlock_write_lock( & lock );
-
 
1137
                res = tcp_listen_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_BACKLOG( call ));
-
 
1138
                fibril_rwlock_write_unlock( & lock );
-
 
1139
//              fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1140
                fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1141
                break;
-
 
1142
            case NET_SOCKET_CONNECT:
-
 
1143
                res = data_receive(( void ** ) & addr, & addrlen );
-
 
1144
                if( res == EOK ){
-
 
1145
                    // the global lock may released in the tcp_connect_message() function
-
 
1146
                    fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1147
                    fibril_rwlock_write_lock( & lock );
-
 
1148
                    res = tcp_connect_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen );
-
 
1149
                    if( res != EOK ){
-
 
1150
                        fibril_rwlock_write_unlock( & lock );
-
 
1151
                        fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1152
                        free( addr );
-
 
1153
                    }
-
 
1154
                }
-
 
1155
                break;
-
 
1156
            case NET_SOCKET_ACCEPT:
-
 
1157
                fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1158
                fibril_rwlock_write_lock( & lock );
-
 
1159
                res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), & addrlen );
-
 
1160
                fibril_rwlock_write_unlock( & lock );
-
 
1161
                fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1162
                if( res > 0 ){
-
 
1163
                    * SOCKET_SET_SOCKET_ID( answer ) = res;
-
 
1164
                    * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-
 
1165
                    answer_count = 2;
-
 
1166
                }
-
 
1167
                break;
-
 
1168
            case NET_SOCKET_SEND:
-
 
1169
                fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1170
                fibril_rwlock_write_lock( & lock );
-
 
1171
                res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call ));
-
 
1172
                if( res != EOK ){
-
 
1173
                    fibril_rwlock_write_unlock( & lock );
-
 
1174
                    fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1175
                }
-
 
1176
                break;
-
 
1177
            case NET_SOCKET_SENDTO:
-
 
1178
                res = data_receive(( void ** ) & addr, & addrlen );
-
 
1179
                if( res == EOK ){
-
 
1180
                    fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1181
                    fibril_rwlock_write_lock( & lock );
-
 
1182
                    res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call ));
-
 
1183
                    if( res != EOK ){
-
 
1184
                        fibril_rwlock_write_unlock( & lock );
-
 
1185
                        fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1186
                    }
-
 
1187
                    free( addr );
-
 
1188
                }
-
 
1189
                break;
-
 
1190
            case NET_SOCKET_RECV:
-
 
1191
                fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1192
                fibril_rwlock_write_lock( & lock );
-
 
1193
                res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), NULL );
-
 
1194
                fibril_rwlock_write_unlock( & lock );
-
 
1195
                fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1196
                if( res > 0 ){
-
 
1197
                    * SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
-
 
1198
                    answer_count = 1;
-
 
1199
                    res = EOK;
-
 
1200
                }
-
 
1201
                break;
-
 
1202
            case NET_SOCKET_RECVFROM:
-
 
1203
                fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1204
                fibril_rwlock_write_lock( & lock );
-
 
1205
                res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen );
-
 
1206
                fibril_rwlock_write_unlock( & lock );
-
 
1207
                fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1208
                if( res > 0 ){
-
 
1209
                    * SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
-
 
1210
                    * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-
 
1211
                    answer_count = 2;
-
 
1212
                    res = EOK;
-
 
1213
                }
-
 
1214
                break;
-
 
1215
            case NET_SOCKET_CLOSE:
-
 
1216
                fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1217
                fibril_rwlock_write_lock( & lock );
-
 
1218
                res = tcp_close_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ));
-
 
1219
                if( res != EOK ){
-
 
1220
                    fibril_rwlock_write_unlock( & lock );
-
 
1221
                    fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1222
                }
-
 
1223
                break;
-
 
1224
            case NET_SOCKET_GETSOCKOPT:
-
 
1225
            case NET_SOCKET_SETSOCKOPT:
-
 
1226
            default:
-
 
1227
                res = ENOTSUP;
-
 
1228
                break;
-
 
1229
        }
-
 
1230
 
-
 
1231
//      printf( "res = %d\n", res );
-
 
1232
 
-
 
1233
        answer_call( callid, res, & answer, answer_count );
-
 
1234
    }
-
 
1235
 
-
 
1236
    printf("release\n");
-
 
1237
    // release all local sockets
-
 
1238
    socket_cores_release( tcp_globals.net_phone, & local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
1239
 
-
 
1240
    return EOK;
-
 
1241
}
-
 
1242
 
-
 
1243
int tcp_timeout( void * data ){
-
 
1244
    tcp_timeout_ref     timeout = data;
-
 
1245
    int                 keep_write_lock = false;
-
 
1246
    socket_core_ref     socket;
-
 
1247
    tcp_socket_data_ref socket_data;
-
 
1248
 
-
 
1249
    assert( timeout );
-
 
1250
 
-
 
1251
    // sleep the given timeout
-
 
1252
    async_usleep( timeout->timeout );
-
 
1253
    // lock the globals
-
 
1254
    if( timeout->globals_read_only ){
-
 
1255
        fibril_rwlock_read_lock( & tcp_globals.lock );
-
 
1256
    }else{
-
 
1257
        fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1258
    }
-
 
1259
    // find the pending operation socket
-
 
1260
    socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length );
-
 
1261
    if( socket && ( socket->socket_id == timeout->socket_id )){
-
 
1262
        socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1263
        assert( socket_data );
-
 
1264
        if( socket_data->local_sockets == timeout->local_sockets ){
-
 
1265
            fibril_rwlock_write_lock( socket_data->local_lock );
-
 
1266
            if( timeout->sequence_number ){
-
 
1267
                // increase the timeout counter;
-
 
1268
                ++ socket_data->timeout_count;
-
 
1269
                if( socket_data->timeout_count == TCP_MAX_TIMEOUTS ){
-
 
1270
                    // TODO release as connection lost
-
 
1271
                    //tcp_refresh_socket_data( socket_data );
-
 
1272
                }
-
 
1273
                // retransmit
-
 
1274
                // TODO enable retransmit
-
 
1275
                //tcp_retransmit_packet( socket, socket_data, timeout->sequence_number );
-
 
1276
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1277
            }else{
-
 
1278
                fibril_mutex_lock( & socket_data->operation.mutex );
-
 
1279
                // set the timeout operation result if state not changed
-
 
1280
                if( socket_data->state == timeout->state ){
-
 
1281
                    socket_data->operation.result = ETIMEOUT;
-
 
1282
                    // notify the main fibril
-
 
1283
                    fibril_condvar_signal( & socket_data->operation.condvar );
-
 
1284
                    // keep the global write lock
-
 
1285
                    keep_write_lock = true;
-
 
1286
                }else{
-
 
1287
                    // operation is ok, do nothing
-
 
1288
                    // unlocking from now on, so the unlock order does not matter...
-
 
1289
                    fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1290
                }
-
 
1291
                fibril_mutex_unlock( & socket_data->operation.mutex );
-
 
1292
            }
-
 
1293
        }
-
 
1294
    }
-
 
1295
    // unlock only if no socket
-
 
1296
    if( timeout->globals_read_only ){
-
 
1297
        fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1298
    }else if( ! keep_write_lock ){
-
 
1299
        // release if not desired
-
 
1300
        fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1301
    }
-
 
1302
    // release the timeout structure
-
 
1303
    free( timeout );
-
 
1304
    return EOK;
-
 
1305
}
-
 
1306
 
-
 
1307
int tcp_release_after_timeout( void * data ){
-
 
1308
    tcp_timeout_ref     timeout = data;
-
 
1309
    socket_core_ref     socket;
-
 
1310
    tcp_socket_data_ref socket_data;
-
 
1311
    fibril_rwlock_t *   local_lock;
-
 
1312
 
-
 
1313
    assert( timeout );
-
 
1314
 
-
 
1315
    // sleep the given timeout
-
 
1316
    async_usleep( timeout->timeout );
-
 
1317
    // lock the globals
-
 
1318
    fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1319
    // find the pending operation socket
-
 
1320
    socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length );
-
 
1321
    if( socket && ( socket->socket_id == timeout->socket_id )){
-
 
1322
        socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1323
        assert( socket_data );
-
 
1324
        if( socket_data->local_sockets == timeout->local_sockets ){
-
 
1325
            local_lock = socket_data->local_lock;
-
 
1326
            fibril_rwlock_write_lock( local_lock );
-
 
1327
            socket_destroy( tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
-
 
1328
            fibril_rwlock_write_unlock( local_lock );
-
 
1329
        }
-
 
1330
    }
-
 
1331
    // unlock the globals
-
 
1332
    fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1333
    // release the timeout structure
-
 
1334
    free( timeout );
-
 
1335
    return EOK;
-
 
1336
}
-
 
1337
 
-
 
1338
void tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number ){
-
 
1339
    packet_t    packet;
-
 
1340
    packet_t    copy;
-
 
1341
    size_t      data_length;
-
 
1342
 
-
 
1343
    assert( socket );
-
 
1344
    assert( socket_data );
-
 
1345
    assert( socket->specific_data == socket_data );
-
 
1346
 
-
 
1347
    // sent packet?
-
 
1348
    packet = pq_find( socket_data->outgoing, sequence_number );
-
 
1349
    printf("retransmit %d\n", packet_get_id( packet ));
-
 
1350
    if( packet ){
-
 
1351
        pq_get_order( packet, NULL, & data_length );
-
 
1352
        copy = tcp_prepare_copy( socket, socket_data, packet, data_length, sequence_number );
-
 
1353
        fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1354
//      printf( "r send %d\n", packet_get_id( packet ));
-
 
1355
        if( copy ){
-
 
1356
            tcp_send_packets( socket_data->device_id, copy );
-
 
1357
        }
-
 
1358
    }else{
-
 
1359
        fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1360
    }
-
 
1361
}
-
 
1362
 
-
 
1363
int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog ){
-
 
1364
    socket_core_ref     socket;
-
 
1365
    tcp_socket_data_ref socket_data;
-
 
1366
 
-
 
1367
    assert( local_sockets );
-
 
1368
 
-
 
1369
    if( backlog < 0 ) return EINVAL;
-
 
1370
    // find the socket
-
 
1371
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1372
    if( ! socket ) return ENOTSOCK;
-
 
1373
    // get the socket specific data
-
 
1374
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1375
    assert( socket_data );
-
 
1376
    // set the backlog
-
 
1377
    socket_data->backlog = backlog;
-
 
1378
    return EOK;
-
 
1379
}
-
 
1380
 
-
 
1381
int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen ){
-
 
1382
    ERROR_DECLARE;
-
 
1383
 
-
 
1384
    socket_core_ref         socket;
-
 
1385
 
-
 
1386
    assert( local_sockets );
-
 
1387
    assert( addr );
-
 
1388
    assert( addrlen > 0 );
-
 
1389
 
-
 
1390
    // find the socket
-
 
1391
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1392
    if( ! socket ) return ENOTSOCK;
-
 
1393
    if( ERROR_OCCURRED( tcp_connect_core( socket, local_sockets, addr, addrlen ))){
-
 
1394
        tcp_free_socket_data( socket );
-
 
1395
        // unbind if bound
-
 
1396
        if( socket->port > 0 ){
-
 
1397
            socket_ports_exclude( & tcp_globals.sockets, socket->port );
-
 
1398
            socket->port = 0;
-
 
1399
        }
-
 
1400
    }
-
 
1401
    return ERROR_CODE;
-
 
1402
}
-
 
1403
 
-
 
1404
int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen ){
-
 
1405
    ERROR_DECLARE;
-
 
1406
 
-
 
1407
    tcp_socket_data_ref     socket_data;
-
 
1408
    packet_t                packet;
-
 
1409
 
-
 
1410
    assert( socket );
-
 
1411
    assert( addr );
-
 
1412
    assert( addrlen > 0 );
-
 
1413
 
-
 
1414
    // get the socket specific data
-
 
1415
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1416
    assert( socket_data );
-
 
1417
    assert( socket->specific_data == socket_data );
-
 
1418
    if(( socket_data->state != TCP_SOCKET_INITIAL )
-
 
1419
    && (( socket_data->state != TCP_SOCKET_LISTEN ) || ( socket->port <= 0 ))){
-
 
1420
        return EINVAL;
-
 
1421
    }
-
 
1422
    // get the destination port
-
 
1423
    ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & socket_data->dest_port ));
-
 
1424
    if( socket->port <= 0 ){
-
 
1425
        // try to find a free port
-
 
1426
        ERROR_PROPAGATE( socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port ));
-
 
1427
        // set the next port as the search starting port number
-
 
1428
        tcp_globals.last_used_port = socket->port;
-
 
1429
    }
-
 
1430
    ERROR_PROPAGATE( ip_get_route_req( tcp_globals.ip_phone, IPPROTO_TCP, addr, addrlen, & socket_data->device_id, & socket_data->pseudo_header, & socket_data->headerlen ));
-
 
1431
 
-
 
1432
    // create the notification packet
-
 
1433
    ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 1, 0 ));
-
 
1434
 
-
 
1435
    // unlock the globals and wait for an operation
-
 
1436
    fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1437
 
-
 
1438
    socket_data->addr = addr;
-
 
1439
    socket_data->addrlen = addrlen;
-
 
1440
    // send the packet
-
 
1441
    if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 ))
-
 
1442
    || ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false ))){
-
 
1443
        socket_data->addr = NULL;
-
 
1444
        socket_data->addrlen = 0;
-
 
1445
        fibril_rwlock_write_lock( & tcp_globals.lock );
-
 
1446
    }else{
-
 
1447
        packet = tcp_get_packets_to_send( socket, socket_data );
-
 
1448
        if( packet ){
-
 
1449
            fibril_mutex_lock( & socket_data->operation.mutex );
-
 
1450
            fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1451
            // send the packet
-
 
1452
            printf( "connecting %d\n", packet_get_id( packet ));
-
 
1453
            tcp_send_packets( socket_data->device_id, packet );
-
 
1454
            // wait for a reply
-
 
1455
            fibril_condvar_wait( & socket_data->operation.condvar, & socket_data->operation.mutex );
-
 
1456
            ERROR_CODE = socket_data->operation.result;
-
 
1457
            if( ERROR_CODE != EOK ){
-
 
1458
                socket_data->addr = NULL;
-
 
1459
                socket_data->addrlen = 0;
-
 
1460
            }
-
 
1461
        }else{
-
 
1462
            socket_data->addr = NULL;
-
 
1463
            socket_data->addrlen = 0;
-
 
1464
            ERROR_CODE = EINTR;
-
 
1465
        }
-
 
1466
    }
-
 
1467
 
-
 
1468
    fibril_mutex_unlock( & socket_data->operation.mutex );
-
 
1469
 
-
 
1470
    // return the result
-
 
1471
    return ERROR_CODE;
-
 
1472
}
-
 
1473
 
-
 
1474
int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){
-
 
1475
    ERROR_DECLARE;
-
 
1476
 
-
 
1477
    tcp_header_ref  header;
-
 
1478
 
-
 
1479
    assert( socket );
-
 
1480
    assert( socket_data );
-
 
1481
    assert( socket->specific_data == socket_data );
-
 
1482
 
-
 
1483
    // get tcp header
-
 
1484
    header = ( tcp_header_ref ) packet_get_data( packet );
-
 
1485
    if( ! header ) return NO_DATA;
-
 
1486
    header->destination_port = htons( socket_data->dest_port );
-
 
1487
    header->source_port = htons( socket->port );
-
 
1488
    header->sequence_number = htonl( socket_data->next_outgoing );
-
 
1489
    if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) socket_data->addr, socket_data->addrlen ))){
-
 
1490
        return tcp_release_and_return( packet, EINVAL );
-
 
1491
    }
-
 
1492
    // remember the outgoing FIN
-
 
1493
    if( header->finalize ){
-
 
1494
        socket_data->fin_outgoing = socket_data->next_outgoing;
-
 
1495
    }
-
 
1496
    return EOK;
-
 
1497
}
-
 
1498
 
-
 
1499
int tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){
-
 
1500
    ERROR_DECLARE;
-
 
1501
    packet_t        first;
-
 
1502
 
-
 
1503
    assert( socket );
-
 
1504
    assert( socket_data );
-
 
1505
    assert( socket->specific_data == socket_data );
-
 
1506
 
-
 
1507
    ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, data_length ));
-
 
1508
 
-
 
1509
    first = pq_add( socket_data->outgoing, packet, socket_data->next_outgoing, data_length );
-
 
1510
    if( ! first ){
-
 
1511
        return tcp_release_and_return( packet, EINVAL );
-
 
1512
    }
-
 
1513
    socket_data->outgoing = first;
-
 
1514
    socket_data->next_outgoing += data_length;
-
 
1515
    return EOK;
-
 
1516
}
-
 
1517
 
-
 
1518
packet_t tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data ){
-
 
1519
    ERROR_DECLARE;
-
 
1520
 
-
 
1521
    packet_t        packet;
-
 
1522
    packet_t        copy;
-
 
1523
    packet_t        sending = NULL;
-
 
1524
    packet_t        previous = NULL;
-
 
1525
    size_t          data_length;
-
 
1526
 
-
 
1527
    assert( socket );
-
 
1528
    assert( socket_data );
-
 
1529
    assert( socket->specific_data == socket_data );
-
 
1530
 
-
 
1531
    packet = pq_find( socket_data->outgoing, socket_data->last_outgoing + 1 );
-
 
1532
    while( packet ){
-
 
1533
        pq_get_order( packet, NULL, & data_length );
-
 
1534
        // send only if fits into the window
-
 
1535
        // respecting the possible overflow
-
 
1536
        if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) socket_data->last_outgoing, ( uint32_t )( socket_data->last_outgoing + data_length ), ( uint32_t )( socket_data->expected + socket_data->treshold ))){
-
 
1537
            copy = tcp_prepare_copy( socket, socket_data, packet, data_length, socket_data->last_outgoing + 1 );
-
 
1538
            if( ! copy ){
-
 
1539
                return sending;
-
 
1540
            }
-
 
1541
            if( ! sending ){
-
 
1542
                sending = copy;
-
 
1543
            }else{
-
 
1544
                if( ERROR_OCCURRED( pq_insert_after( previous, copy ))){
-
 
1545
                    pq_release( tcp_globals.net_phone, packet_get_id( copy ));
-
 
1546
                    return sending;
-
 
1547
                }
-
 
1548
            }
-
 
1549
            previous = copy;
-
 
1550
            packet = pq_next( packet );
-
 
1551
            // overflow occurred ?
-
 
1552
            if(( ! packet ) && ( socket_data->last_outgoing > socket_data->next_outgoing )){
-
 
1553
                printf("gpts overflow\n");
-
 
1554
                // continue from the beginning
-
 
1555
                packet = socket_data->outgoing;
-
 
1556
            }
-
 
1557
            socket_data->last_outgoing += data_length;
-
 
1558
        }else{
-
 
1559
            break;
-
 
1560
        }
-
 
1561
    }
-
 
1562
    return sending;
-
 
1563
}
-
 
1564
 
-
 
1565
packet_t tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){
-
 
1566
    ERROR_DECLARE;
-
 
1567
 
-
 
1568
    tcp_header_ref  header;
-
 
1569
    uint32_t        checksum;
-
 
1570
 
-
 
1571
    assert( socket );
-
 
1572
    assert( socket_data );
-
 
1573
    assert( socket->specific_data == socket_data );
-
 
1574
 
-
 
1575
    // adjust the pseudo header
-
 
1576
    if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length( packet )))){
-
 
1577
        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
1578
        return NULL;
-
 
1579
    }
-
 
1580
 
-
 
1581
    // get the header
-
 
1582
    header = ( tcp_header_ref ) packet_get_data( packet );
-
 
1583
    if( ! header ){
-
 
1584
        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
1585
        return NULL;
-
 
1586
    }
-
 
1587
    assert( ntohl( header->sequence_number ) == sequence_number );
-
 
1588
 
-
 
1589
    // adjust the header
-
 
1590
    if( socket_data->next_incoming ){
-
 
1591
        header->acknowledgement_number = htonl( socket_data->next_incoming );
-
 
1592
        header->acknowledge = 1;
-
 
1593
    }
-
 
1594
    header->window = htons( socket_data->window );
-
 
1595
 
-
 
1596
    // checksum
-
 
1597
    header->checksum = 0;
-
 
1598
    checksum = compute_checksum( 0, socket_data->pseudo_header, socket_data->headerlen );
-
 
1599
    checksum = compute_checksum( checksum, ( uint8_t * ) packet_get_data( packet ), packet_get_data_length( packet ));
-
 
1600
    header->checksum = htons( flip_checksum( compact_checksum( checksum )));
-
 
1601
    // prepare the packet
-
 
1602
    if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_TCP, 0, 0, 0, 0 ))
-
 
1603
    // prepare the timeout
-
 
1604
    || ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true ))){
-
 
1605
        pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
1606
        return NULL;
-
 
1607
    }
-
 
1608
    return packet;
-
 
1609
}
-
 
1610
 
-
 
1611
packet_t tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){
-
 
1612
    packet_t        copy;
-
 
1613
 
-
 
1614
    assert( socket );
-
 
1615
    assert( socket_data );
-
 
1616
    assert( socket->specific_data == socket_data );
-
 
1617
 
-
 
1618
    // make a copy of the packet
-
 
1619
    copy = packet_get_copy( tcp_globals.net_phone, packet );
-
 
1620
    if( ! copy ) return NULL;
-
 
1621
 
-
 
1622
    return tcp_send_prepare_packet( socket, socket_data, copy, data_length, sequence_number );
-
 
1623
}
-
 
1624
 
-
 
1625
void tcp_send_packets( device_id_t device_id, packet_t packet ){
-
 
1626
    packet_t    next;
-
 
1627
 
-
 
1628
    while( packet ){
-
 
1629
        next = pq_detach( packet );
-
 
1630
        ip_send_msg( tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0 );
-
 
1631
        packet = next;
-
 
1632
    }
-
 
1633
}
-
 
1634
 
-
 
1635
int tcp_get_packet_dimension( device_id_t device_id, packet_dimension_ref * packet_dimension ){
-
 
1636
    ERROR_DECLARE;
-
 
1637
 
-
 
1638
    assert( packet_dimension );
-
 
1639
 
-
 
1640
    * packet_dimension = packet_dimensions_find( & tcp_globals.dimensions, device_id );
-
 
1641
    if( ! * packet_dimension ){
-
 
1642
        // ask for and remember them if not found
-
 
1643
        * packet_dimension = malloc( sizeof( ** packet_dimension ));
-
 
1644
        if( ! * packet_dimension ) return ENOMEM;
-
 
1645
        if( ERROR_OCCURRED( ip_packet_size_req( tcp_globals.ip_phone, device_id, & ( ** packet_dimension ).addr_len, & ( ** packet_dimension ).prefix, & ( ** packet_dimension ).content, & ( ** packet_dimension ).suffix ))){
-
 
1646
            free( * packet_dimension );
-
 
1647
            return ERROR_CODE;
-
 
1648
        }
-
 
1649
        ERROR_CODE = packet_dimensions_add( & tcp_globals.dimensions, device_id, * packet_dimension );
-
 
1650
        if( ERROR_CODE < 0 ){
-
 
1651
            free( * packet_dimension );
-
 
1652
            return ERROR_CODE;
-
 
1653
        }
-
 
1654
    }
-
 
1655
    return EOK;
-
 
1656
}
-
 
1657
 
-
 
1658
void tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize ){
-
 
1659
    assert( socket );
-
 
1660
    assert( socket_data );
-
 
1661
    assert( socket->specific_data == socket_data );
-
 
1662
    assert( header );
-
 
1663
 
-
 
1664
    bzero( header, sizeof( * header ));
-
 
1665
    header->source_port = htons( socket->port );
-
 
1666
    header->source_port = htons( socket_data->dest_port );
-
 
1667
    header->header_length = TCP_COMPUTE_HEADER_LENGTH( sizeof( * header ));
-
 
1668
    header->synchronize = synchronize;
-
 
1669
    header->finalize = finalize;
-
 
1670
}
-
 
1671
 
-
 
1672
int tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only ){
-
 
1673
    tcp_timeout_ref operation_timeout;
-
 
1674
    fid_t           fibril;
-
 
1675
 
-
 
1676
    assert( socket );
-
 
1677
    assert( socket_data );
-
 
1678
    assert( socket->specific_data == socket_data );
-
 
1679
 
-
 
1680
    // prepare the timeout with key bundle structure
-
 
1681
    operation_timeout = malloc( sizeof( * operation_timeout ) + socket->key_length + 1 );
-
 
1682
    if( ! operation_timeout ) return ENOMEM;
-
 
1683
    bzero( operation_timeout, sizeof( * operation_timeout ));
-
 
1684
    operation_timeout->globals_read_only = globals_read_only;
-
 
1685
    operation_timeout->port = socket->port;
-
 
1686
    operation_timeout->local_sockets = socket_data->local_sockets;
-
 
1687
    operation_timeout->socket_id = socket->socket_id;
-
 
1688
    operation_timeout->timeout = timeout;
-
 
1689
    operation_timeout->sequence_number = sequence_number;
-
 
1690
    operation_timeout->state = state;
-
 
1691
 
-
 
1692
    // copy the key
-
 
1693
    operation_timeout->key = (( char * ) operation_timeout ) + sizeof( * operation_timeout );
-
 
1694
    operation_timeout->key_length = socket->key_length;
-
 
1695
    memcpy( operation_timeout->key, socket->key, socket->key_length );
-
 
1696
    operation_timeout->key[ operation_timeout->key_length ] = '\0';
-
 
1697
 
-
 
1698
    // prepare the timeouting thread
-
 
1699
    fibril = fibril_create( timeout_function, operation_timeout );
-
 
1700
    if( ! fibril ){
-
 
1701
        free( operation_timeout );
-
 
1702
        return EPARTY;
-
 
1703
    }
-
 
1704
//  fibril_mutex_lock( & socket_data->operation.mutex );
-
 
1705
    // start the timeouting fibril
-
 
1706
    fibril_add_ready( fibril );
-
 
1707
    //socket_data->state = state;
-
 
1708
    return EOK;
-
 
1709
}
-
 
1710
 
-
 
1711
int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){
-
 
1712
    ERROR_DECLARE;
-
 
1713
 
-
 
1714
    socket_core_ref     socket;
-
 
1715
    tcp_socket_data_ref socket_data;
-
 
1716
    int                 packet_id;
-
 
1717
    packet_t            packet;
-
 
1718
    size_t              length;
-
 
1719
 
-
 
1720
    assert( local_sockets );
-
 
1721
 
-
 
1722
    // find the socket
-
 
1723
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1724
    if( ! socket ) return ENOTSOCK;
-
 
1725
    // get the socket specific data
-
 
1726
    if( ! socket->specific_data ) return NO_DATA;
-
 
1727
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1728
 
-
 
1729
    // check state
-
 
1730
    if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){
-
 
1731
        return ENOTCONN;
-
 
1732
    }
-
 
1733
 
-
 
1734
    // send the source address if desired
-
 
1735
    if( addrlen ){
-
 
1736
        ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
-
 
1737
        * addrlen = socket_data->addrlen;
-
 
1738
    }
-
 
1739
 
-
 
1740
    // get the next received packet
-
 
1741
    packet_id = dyn_fifo_value( & socket->received );
-
 
1742
    if( packet_id < 0 ) return NO_DATA;
-
 
1743
    ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, packet_id ));
-
 
1744
 
-
 
1745
    // reply the packets
-
 
1746
    ERROR_PROPAGATE( socket_reply_packets( packet, & length ));
-
 
1747
 
-
 
1748
    // release the packet
-
 
1749
    dyn_fifo_pop( & socket->received );
-
 
1750
    pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
1751
    // return the total length
-
 
1752
    return ( int ) length;
-
 
1753
}
-
 
1754
 
-
 
1755
int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags ){
-
 
1756
    ERROR_DECLARE;
-
 
1757
 
-
 
1758
    socket_core_ref         socket;
-
 
1759
    tcp_socket_data_ref     socket_data;
-
 
1760
    packet_dimension_ref    packet_dimension;
-
 
1761
    packet_t                packet;
-
 
1762
    size_t                  total_length;
-
 
1763
    tcp_header_ref          header;
-
 
1764
    int                     index;
-
 
1765
    int                     result;
-
 
1766
 
-
 
1767
    assert( local_sockets );
-
 
1768
 
-
 
1769
    // find the socket
-
 
1770
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1771
    if( ! socket ) return ENOTSOCK;
-
 
1772
    // get the socket specific data
-
 
1773
    if( ! socket->specific_data ) return NO_DATA;
-
 
1774
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1775
 
-
 
1776
    // check state
-
 
1777
    if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){
-
 
1778
        return ENOTCONN;
-
 
1779
    }
-
 
1780
 
-
 
1781
    ERROR_PROPAGATE( tcp_get_packet_dimension( socket_data->device_id, & packet_dimension ));
-
 
1782
 
-
 
1783
    // TODO return the device_id + data_fragment_size if different - the client should send it again
-
 
1784
    // ( two messages are better than ip fragmentation )
-
 
1785
 
-
 
1786
    for( index = 0; index < fragments; ++ index ){
-
 
1787
        // read the data fragment
-
 
1788
        result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, sizeof( tcp_header_t ), packet_dimension, socket_data->addr, socket_data->addrlen );
-
 
1789
        if( result < 0 ) return result;
-
 
1790
        total_length = ( size_t ) result;
-
 
1791
        // prefix the tcp header
-
 
1792
        header = PACKET_PREFIX( packet, tcp_header_t );
-
 
1793
        if( ! header ){
-
 
1794
            return tcp_release_and_return( packet, ENOMEM );
-
 
1795
        }
-
 
1796
        tcp_prepare_operation_header( socket, socket_data, header, 0, 0 );
-
 
1797
        ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 0 ));
-
 
1798
    }
-
 
1799
 
-
 
1800
    // flush packets
-
 
1801
    packet = tcp_get_packets_to_send( socket, socket_data );
-
 
1802
    fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1803
    fibril_rwlock_read_unlock( & tcp_globals.lock );
-
 
1804
    if( packet ){
-
 
1805
        // send the packet
-
 
1806
        tcp_send_packets( socket_data->device_id, packet );
-
 
1807
    }
-
 
1808
 
-
 
1809
    return EOK;
-
 
1810
}
-
 
1811
 
-
 
1812
int tcp_close_message( socket_cores_ref local_sockets, int socket_id ){
-
 
1813
    ERROR_DECLARE;
-
 
1814
 
-
 
1815
    socket_core_ref         socket;
-
 
1816
    tcp_socket_data_ref     socket_data;
-
 
1817
    packet_t                packet;
-
 
1818
 
-
 
1819
    // find the socket
-
 
1820
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1821
    if( ! socket ) return ENOTSOCK;
-
 
1822
    // get the socket specific data
-
 
1823
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1824
    assert( socket_data );
-
 
1825
 
-
 
1826
    // check state
-
 
1827
    switch( socket_data->state ){
-
 
1828
        case TCP_SOCKET_ESTABLISHED:
-
 
1829
            socket_data->state = TCP_SOCKET_FIN_WAIT_1;
-
 
1830
            break;
-
 
1831
        case TCP_SOCKET_CLOSE_WAIT:
-
 
1832
            socket_data->state = TCP_SOCKET_LAST_ACK;
-
 
1833
            break;
-
 
1834
//      case TCP_SOCKET_LISTEN:
-
 
1835
        default:
-
 
1836
            // just destroy
-
 
1837
            if( ! ERROR_OCCURRED( socket_destroy( tcp_globals.net_phone, socket_id, local_sockets, & tcp_globals.sockets, tcp_free_socket_data ))){
-
 
1838
                fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1839
                fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1840
            }
-
 
1841
            return ERROR_CODE;
-
 
1842
    }
-
 
1843
    // send FIN
-
 
1844
    // TODO should I wait to complete?
-
 
1845
 
-
 
1846
    // create the notification packet
-
 
1847
    ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 ));
-
 
1848
 
-
 
1849
    // send the packet
-
 
1850
    ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 ));
-
 
1851
 
-
 
1852
    // flush packets
-
 
1853
    packet = tcp_get_packets_to_send( socket, socket_data );
-
 
1854
    fibril_rwlock_write_unlock( socket_data->local_lock );
-
 
1855
    fibril_rwlock_write_unlock( & tcp_globals.lock );
-
 
1856
    if( packet ){
-
 
1857
        // send the packet
-
 
1858
        tcp_send_packets( socket_data->device_id, packet );
-
 
1859
    }
-
 
1860
    return EOK;
-
 
1861
}
-
 
1862
 
-
 
1863
int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize ){
-
 
1864
    ERROR_DECLARE;
-
 
1865
 
-
 
1866
    packet_dimension_ref    packet_dimension;
-
 
1867
    tcp_header_ref          header;
-
 
1868
 
-
 
1869
    assert( packet );
-
 
1870
 
-
 
1871
    // get the device packet dimension
-
 
1872
    ERROR_PROPAGATE( tcp_get_packet_dimension( socket_data->device_id, & packet_dimension ));
-
 
1873
    // get a new packet
-
 
1874
    * packet = packet_get_4( tcp_globals.net_phone, sizeof( tcp_header_t ), packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
-
 
1875
    if( ! * packet ) return ENOMEM;
-
 
1876
    // allocate space in the packet
-
 
1877
    header = PACKET_SUFFIX( * packet, tcp_header_t );
-
 
1878
    if( ! header ){
-
 
1879
        tcp_release_and_return( * packet, ENOMEM );
-
 
1880
    }
-
 
1881
 
-
 
1882
    tcp_prepare_operation_header( socket, socket_data, header, synchronize, finalize );
-
 
1883
    return EOK;
-
 
1884
}
-
 
1885
 
-
 
1886
int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen ){
-
 
1887
    ERROR_DECLARE;
-
 
1888
 
-
 
1889
    socket_core_ref     accepted;
-
 
1890
    socket_core_ref     socket;
-
 
1891
    tcp_socket_data_ref socket_data;
-
 
1892
 
-
 
1893
    assert( local_sockets );
-
 
1894
    assert( addrlen );
-
 
1895
 
-
 
1896
    // find the socket
-
 
1897
    socket = socket_cores_find( local_sockets, socket_id );
-
 
1898
    if( ! socket ) return ENOTSOCK;
-
 
1899
    // get the socket specific data
-
 
1900
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1901
    assert( socket_data );
-
 
1902
 
-
 
1903
    // check state
-
 
1904
    if( socket_data->state != TCP_SOCKET_LISTEN ){
-
 
1905
        return EINVAL;
-
 
1906
    }
-
 
1907
 
-
 
1908
    do{
-
 
1909
        socket_id = dyn_fifo_value( & socket->accepted );
-
 
1910
        if( socket_id < 0 ) return ENOTSOCK;
-
 
1911
 
-
 
1912
        accepted = socket_cores_find( local_sockets, socket_id );
-
 
1913
        if( ! accepted ) return ENOTSOCK;
-
 
1914
        // get the socket specific data
-
 
1915
        socket_data = ( tcp_socket_data_ref ) accepted->specific_data;
-
 
1916
        assert( socket_data );
-
 
1917
        if( socket_data->state == TCP_SOCKET_ESTABLISHED ){
-
 
1918
            ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
-
 
1919
            * addrlen = socket_data->addrlen;
-
 
1920
        }
-
 
1921
        dyn_fifo_pop( & socket->accepted );
-
 
1922
    }while( socket_data->state != TCP_SOCKET_ESTABLISHED );
-
 
1923
    printf("ret accept %d\n", accepted->socket_id );
-
 
1924
    return accepted->socket_id;
-
 
1925
}
-
 
1926
 
-
 
1927
void tcp_free_socket_data( socket_core_ref socket ){
-
 
1928
    tcp_socket_data_ref     socket_data;
-
 
1929
 
-
 
1930
    assert( socket );
-
 
1931
 
-
 
1932
    printf( "destroy_socket %d\n", socket->socket_id );
-
 
1933
 
-
 
1934
    // get the socket specific data
-
 
1935
    socket_data = ( tcp_socket_data_ref ) socket->specific_data;
-
 
1936
    assert( socket_data );
-
 
1937
    //free the pseudo header
-
 
1938
    if( socket_data->pseudo_header ){
-
 
1939
        if( socket_data->headerlen ){
-
 
1940
            printf("d pseudo\n");
-
 
1941
            free( socket_data->pseudo_header );
-
 
1942
            socket_data->headerlen = 0;
-
 
1943
        }
-
 
1944
        socket_data->pseudo_header = NULL;
-
 
1945
    }
-
 
1946
    socket_data->headerlen = 0;
-
 
1947
    // free the address
-
 
1948
    if( socket_data->addr ){
-
 
1949
        if( socket_data->addrlen ){
-
 
1950
            printf("d addr\n");
-
 
1951
            free( socket_data->addr );
-
 
1952
            socket_data->addrlen = 0;
-
 
1953
        }
-
 
1954
        socket_data->addr = NULL;
-
 
1955
    }
-
 
1956
    socket_data->addrlen = 0;
-
 
1957
}
-
 
1958
 
-
 
1959
int tcp_release_and_return( packet_t packet, int result ){
-
 
1960
    pq_release( tcp_globals.net_phone, packet_get_id( packet ));
-
 
1961
    return result;
-
 
1962
}
-
 
1963
 
122
/** @}
1964
/** @}
123
 */
1965
 */