Subversion Repositories HelenOS

Rev

Rev 4742 | Rev 4756 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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