Subversion Repositories HelenOS

Rev

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