Subversion Repositories HelenOS

Rev

Rev 4750 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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