Subversion Repositories HelenOS

Rev

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

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