source: mainline/uspace/srv/net/tl/tcp/tcp.c@ b648ae4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b648ae4 was 21580dd, checked in by Lukas Mejdrech <lukas@…>, 15 years ago

Merged with network branch svn://svn.helenos.org/HelenOS/branches/network revision 4759; ipc_share_* and ipc_data_* changed to async_*; client connection in module.c returns on IPC_M_PHONE_HUNGUP; * Qemu scripts renamed to net-qe.*; (the dp8390 does not respond)

  • Property mode set to 100644
File size: 67.7 KB
Line 
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
29/** @addtogroup tcp
30 * @{
31 */
32
33/** @file
34 * TCP module implementation.
35 * @see tcp.h
36 */
37
38#include <assert.h>
39#include <async.h>
40#include <fibril_synch.h>
41#include <malloc.h>
42//TODO remove stdio
43#include <stdio.h>
44
45#include <ipc/ipc.h>
46#include <ipc/services.h>
47
48#include "../../err.h"
49#include "../../messages.h"
50#include "../../modules.h"
51
52#include "../../structures/dynamic_fifo.h"
53#include "../../structures/packet/packet_client.h"
54
55#include "../../include/checksum.h"
56#include "../../include/in.h"
57#include "../../include/in6.h"
58#include "../../include/inet.h"
59#include "../../include/ip_client.h"
60#include "../../include/ip_interface.h"
61#include "../../include/ip_protocols.h"
62#include "../../include/icmp_client.h"
63#include "../../include/icmp_interface.h"
64#include "../../include/net_interface.h"
65#include "../../include/socket_codes.h"
66#include "../../include/socket_errno.h"
67#include "../../include/tcp_codes.h"
68
69#include "../../socket/socket_core.h"
70#include "../../socket/socket_messages.h"
71
72#include "../tl_common.h"
73#include "../tl_messages.h"
74
75#include "tcp.h"
76#include "tcp_header.h"
77#include "tcp_module.h"
78
79/** The TCP window default value.
80 */
81#define NET_DEFAULT_TCP_WINDOW 10240
82
83/** Initial timeout for new connections.
84 */
85#define NET_DEFAULT_TCP_INITIAL_TIMEOUT 3000000L
86
87/** Default timeout for closing.
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
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
107/** Timeout for connection initialization, SYN sent.
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
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] higher_equal The last value in the interval.
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 */
130typedef struct tcp_timeout tcp_timeout_t;
131
132/** Type definition of the TCP timeout pointer.
133 * @see tcp_timeout
134 */
135typedef tcp_timeout_t * tcp_timeout_ref;
136
137/** TCP reply timeout data.
138 * Used as a timeouting fibril argument.
139 * @see tcp_timeout()
140 */
141struct 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.
172 * @param[in] packet The packet queue to be released.
173 * @param[in] result The result to be returned.
174 * @return The result parameter.
175 */
176int tcp_release_and_return( packet_t packet, int result );
177
178void tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize );
179int 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 );
180void tcp_free_socket_data( socket_core_ref socket );
181int tcp_timeout( void * data );
182int tcp_release_after_timeout( void * data );
183int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error );
184int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen );
185int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
186int tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
187packet_t tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data );
188void tcp_send_packets( device_id_t device_id, packet_t packet );
189void tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header );
190packet_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 );
191packet_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 );
192void tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number );
193int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize );
194void tcp_refresh_socket_data( tcp_socket_data_ref socket_data );
195void tcp_initialize_socket_data( tcp_socket_data_ref socket_data );
196int 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 );
197int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
198int tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
199int 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 );
200int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length );
201
202int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
203int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
204int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog );
205int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen );
206int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
207int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags );
208int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen );
209int tcp_close_message( socket_cores_ref local_sockets, int socket_id );
210
211/** TCP global data.
212 */
213tcp_globals_t tcp_globals;
214
215int tcp_initialize( async_client_conn_t client_connection ){
216 ERROR_DECLARE;
217
218 assert( client_connection );
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 }
225 tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg );
226 if( tcp_globals.ip_phone < 0 ){
227 return tcp_globals.ip_phone;
228 }
229 ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets ));
230 if( ERROR_OCCURRED( packet_dimensions_initialize( & tcp_globals.dimensions ))){
231 socket_ports_destroy( & tcp_globals.sockets );
232 return ERROR_CODE;
233 }
234 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
235 fibril_rwlock_write_unlock( & tcp_globals.lock );
236 return EOK;
237}
238
239int tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
240 ERROR_DECLARE;
241
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
252int 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 }
431 return EOK;
432}
433
434int 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
670int 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
693int 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
740int 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
878int 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
934void 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
1011int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
1012 ERROR_DECLARE;
1013
1014 packet_t packet;
1015
1016 assert( call );
1017 assert( answer );
1018 assert( answer_count );
1019
1020 * answer_count = 0;
1021 switch( IPC_GET_METHOD( * call )){
1022 case NET_TL_RECEIVED:
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 );
1031 }
1032 return ENOTSUP;
1033}
1034
1035void 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
1050void 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
1058int 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
1241int 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
1305int 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
1336void 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
1361int 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
1379int 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
1402int 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
1472int 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
1497int 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
1516packet_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
1563packet_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
1609packet_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
1623void 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
1633void 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
1647int 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
1686int 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
1730int 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
1756 ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
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
1787int 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
1838int 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
1847 ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
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
1861int 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
1902void 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
1934int 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
1939/** @}
1940 */
Note: See TracBrowser for help on using the repository browser.