Subversion Repositories HelenOS

Rev

Rev 4742 | Rev 4756 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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