Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -205,6 +205,6 @@
 int	tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen );
 int	tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
-int	tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags );
-int	tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen );
+int	tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags );
+int	tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen );
 int tcp_close_message( socket_cores_ref local_sockets, int socket_id );
 
@@ -298,5 +298,5 @@
 		return tcp_release_and_return( packet, EINVAL );
 	}
-	if( length < sizeof( tcp_header_t ) + offset ){
+	if( length < TCP_HEADER_SIZE + offset ){
 		return tcp_release_and_return( packet, NO_DATA );
 	}
@@ -668,4 +668,6 @@
 	ERROR_DECLARE;
 
+	packet_dimension_ref	packet_dimension;
+
 	assert( socket );
 	assert( socket_data );
@@ -676,5 +678,6 @@
 
 	// queue the received packet
-	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
+	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
+	|| ERROR_OCCURRED( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ))){
 		return tcp_release_and_return( packet, ERROR_CODE );
 	}
@@ -684,5 +687,5 @@
 
 	// notify the destination socket
-	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size ), 0, 0, ( ipcarg_t ) fragments );
 	return EOK;
 }
@@ -783,4 +786,5 @@
 //			printf( "addr %p\n", socket_data->addr, socket_data->addrlen );
 			// create a socket
+			socket_id = -1;
 			if( ERROR_OCCURRED( socket_create( socket_data->local_sockets, listening_socket->phone, socket_data, & socket_id ))){
 				free( socket_data->addr );
@@ -789,4 +793,5 @@
 			}
 
+			socket_id *= -1;
 			printf("new_sock %d\n", socket_id);
 			socket_data->pseudo_header = listening_socket_data->pseudo_header;
@@ -901,5 +906,5 @@
 			if( ! ERROR_OCCURRED( dyn_fifo_push( & listening_socket->accepted, socket->socket_id, listening_socket_data->backlog ))){
 				// notify the destination socket
-				async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, 0, 0, 0, ( ipcarg_t ) socket->socket_id );
+				async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, socket_data->data_fragment_size, TCP_HEADER_SIZE, 0, ( ipcarg_t ) socket->socket_id );
 				fibril_rwlock_write_unlock( socket_data->local_lock );
 				return EOK;
@@ -1035,5 +1040,5 @@
 	bzero( socket_data, sizeof( * socket_data ));
 	socket_data->state = TCP_SOCKET_INITIAL;
-	socket_data->device_id = -1;
+	socket_data->device_id = DEVICE_INVALID_ID;
 	socket_data->window = NET_DEFAULT_TCP_WINDOW;
 	socket_data->treshold = socket_data->window;
@@ -1051,4 +1056,5 @@
 	fibril_mutex_initialize( & socket_data->operation.mutex );
 	fibril_condvar_initialize( & socket_data->operation.condvar );
+	socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
 }
 
@@ -1065,4 +1071,5 @@
 	tcp_socket_data_ref		socket_data;
 	socket_core_ref			socket;
+	packet_dimension_ref	packet_dimension;
 
 	/*
@@ -1096,9 +1103,13 @@
 					socket_data->local_sockets = & local_sockets;
 					fibril_rwlock_write_lock( & lock );
+					* SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
 					res = socket_create( & local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID( answer ));
 					fibril_rwlock_write_unlock( & lock );
 					if( res == EOK ){
-						* SOCKET_SET_HEADER_SIZE( answer ) = sizeof( tcp_header_t );
-						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
+						if( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
+							* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+						}
+//						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
+						* SOCKET_SET_HEADER_SIZE( answer ) = TCP_HEADER_SIZE;
 						answer_count = 3;
 					}else{
@@ -1138,5 +1149,5 @@
 				res = data_receive(( void ** ) & addr, & addrlen );
 				if( res == EOK ){
-					// the global lock may released in the tcp_connect_message() function
+					// the global lock may be released in the tcp_connect_message() function
 					fibril_rwlock_write_lock( & tcp_globals.lock );
 					fibril_rwlock_write_lock( & lock );
@@ -1152,5 +1163,5 @@
 				fibril_rwlock_read_lock( & tcp_globals.lock );
 				fibril_rwlock_write_lock( & lock );
-				res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), & addrlen );
+				res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_NEW_SOCKET_ID( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), & addrlen );
 				fibril_rwlock_write_unlock( & lock );
 				fibril_rwlock_read_unlock( & tcp_globals.lock );
@@ -1158,5 +1169,5 @@
 					* SOCKET_SET_SOCKET_ID( answer ) = res;
 					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-					answer_count = 2;
+					answer_count = 3;
 				}
 				break;
@@ -1164,8 +1175,10 @@
 				fibril_rwlock_read_lock( & tcp_globals.lock );
 				fibril_rwlock_write_lock( & lock );
-				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 ));
+				res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
 				if( res != EOK ){
 					fibril_rwlock_write_unlock( & lock );
 					fibril_rwlock_read_unlock( & tcp_globals.lock );
+				}else{
+					answer_count = 2;
 				}
 				break;
@@ -1175,8 +1188,10 @@
 					fibril_rwlock_read_lock( & tcp_globals.lock );
 					fibril_rwlock_write_lock( & lock );
-					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 ));
+					res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
 					if( res != EOK ){
 						fibril_rwlock_write_unlock( & lock );
 						fibril_rwlock_read_unlock( & tcp_globals.lock );
+					}else{
+						answer_count = 2;
 					}
 					free( addr );
@@ -1204,5 +1219,5 @@
 					* SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
 					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-					answer_count = 2;
+					answer_count = 3;
 					res = EOK;
 				}
@@ -1725,5 +1740,5 @@
 }
 
-int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags ){
+int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags ){
 	ERROR_DECLARE;
 
@@ -1738,4 +1753,5 @@
 
 	assert( local_sockets );
+	assert( data_fragment_size );
 
 	// find the socket
@@ -1753,10 +1769,9 @@
 	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 
-	// TODO return the device_id + data_fragment_size if different - the client should send it again
-	// ( two messages are better than ip fragmentation )
+	* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
 
 	for( index = 0; index < fragments; ++ index ){
 		// read the data fragment
-		result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, sizeof( tcp_header_t ), packet_dimension, socket_data->addr, socket_data->addrlen );
+		result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen );
 		if( result < 0 ) return result;
 		total_length = ( size_t ) result;
@@ -1844,5 +1859,5 @@
 	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 	// get a new packet
-	* packet = packet_get_4( tcp_globals.net_phone, sizeof( tcp_header_t ), packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
+	* packet = packet_get_4( tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
 	if( ! * packet ) return ENOMEM;
 	// allocate space in the packet
@@ -1856,5 +1871,5 @@
 }
 
-int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen ){
+int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen ){
 	ERROR_DECLARE;
 
@@ -1862,6 +1877,8 @@
 	socket_core_ref		socket;
 	tcp_socket_data_ref	socket_data;
+	packet_dimension_ref	packet_dimension;
 
 	assert( local_sockets );
+	assert( data_fragment_size );
 	assert( addrlen );
 
@@ -1887,7 +1904,14 @@
 		socket_data = ( tcp_socket_data_ref ) accepted->specific_data;
 		assert( socket_data );
+		// TODO can it be in another state?
 		if( socket_data->state == TCP_SOCKET_ESTABLISHED ){
 			ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
+			ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 			* addrlen = socket_data->addrlen;
+			* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+			if( new_socket_id > 0 ){
+				ERROR_PROPAGATE( socket_cores_update( local_sockets, accepted->socket_id, new_socket_id ));
+				accepted->socket_id = new_socket_id;
+			}
 		}
 		dyn_fifo_pop( & socket->accepted );
