Subversion Repositories HelenOS

Rev

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