Subversion Repositories HelenOS

Rev

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