diff --git a/src/frontend/terminaloverlay.cc b/src/frontend/terminaloverlay.cc index 462c39a..87f64ee 100644 --- a/src/frontend/terminaloverlay.cc +++ b/src/frontend/terminaloverlay.cc @@ -301,8 +301,8 @@ int OverlayManager::wait_time( void ) next_expiry = 1000; } - if ( predictions.active() && ( next_expiry > 10 ) ) { - next_expiry = 10; + if ( predictions.active() && ( next_expiry > 20 ) ) { + next_expiry = 20; } return next_expiry; diff --git a/src/network/networktransport.cc b/src/network/networktransport.cc index 435426a..99eac97 100644 --- a/src/network/networktransport.cc +++ b/src/network/networktransport.cc @@ -128,6 +128,7 @@ void Transport::recv( void ) received_states.push_back( new_state ); sender.set_ack_num( received_states.back().num ); + sender.remote_heard( new_state.timestamp ); if ( !inst.diff().empty() ) { sender.set_data_ack(); } diff --git a/src/network/transportsender.cc b/src/network/transportsender.cc index fe27ff7..e023396 100644 --- a/src/network/transportsender.cc +++ b/src/network/transportsender.cc @@ -45,7 +45,8 @@ TransportSender::TransportSender( Connection *s_connection, MyState &in pending_data_ack( false ), ack_timestamp( 0 ), ack_history(), - SEND_MINDELAY( 15 ) + SEND_MINDELAY( 15 ), + last_heard( 0 ) { } @@ -63,41 +64,57 @@ unsigned int TransportSender::send_interval( void ) const return SEND_INTERVAL; } -/* How many ms can the caller wait before we will have an event (empty ack or next frame)? */ +/* Housekeeping routine to calculate next send and ack times */ template -int TransportSender::wait_time( void ) +void TransportSender::calculate_timers( void ) { - if ( pending_data_ack && (next_ack_time > timestamp() + ACK_DELAY) ) { - next_ack_time = timestamp() + ACK_DELAY; + uint64_t now = timestamp(); + + /* Update assumed receiver state */ + update_assumed_receiver_state(); + + /* Cut out common prefix of all states */ + rationalize_states(); + + if ( pending_data_ack && (next_ack_time > now + ACK_DELAY) ) { + next_ack_time = now + ACK_DELAY; } - if ( !(current_state == sent_states.back().state) ) { /* pending data to send */ - if ( next_send_time > timestamp() + SEND_MINDELAY ) { - next_send_time = timestamp() + SEND_MINDELAY; + if ( ( !(current_state == assumed_receiver_state->state) + && (last_heard + ACTIVE_RETRY_TIMEOUT > now) ) + || !(current_state == sent_states.back().state) ) { /* pending data to send */ + if ( next_send_time > now + SEND_MINDELAY ) { + next_send_time = now + SEND_MINDELAY; } if ( next_send_time < sent_states.back().timestamp + send_interval() ) { next_send_time = sent_states.back().timestamp + send_interval(); } + } else { + next_send_time = uint64_t(-1); } /* speed up shutdown sequence */ if ( shutdown_in_progress || (ack_num == uint64_t(-1)) ) { next_ack_time = sent_states.back().timestamp + send_interval(); } +} - uint64_t next_wakeup = next_ack_time; +/* How many ms to wait until next event */ +template +int TransportSender::wait_time( void ) +{ + calculate_timers(); - if ( next_send_time < next_wakeup ) { - next_wakeup = next_send_time; - } + uint64_t next_wakeup = min( next_ack_time, next_send_time ); + uint64_t now = timestamp(); if ( !connection->get_attached() ) { return -1; } - if ( next_wakeup > timestamp() ) { - return next_wakeup - timestamp(); + if ( next_wakeup > now ) { + return next_wakeup - now; } else { return 0; } @@ -107,35 +124,33 @@ int TransportSender::wait_time( void ) template void TransportSender::tick( void ) { - wait_time(); + calculate_timers(); /* updates assumed receiver state and rationalizes */ if ( !connection->get_attached() ) { return; } - if ( (timestamp() < next_ack_time) - && (timestamp() < next_send_time) ) { + uint64_t now = timestamp(); + + if ( (now < next_ack_time) + && (now < next_send_time) ) { return; } /* Determine if a new diff or empty ack needs to be sent */ - /* Update assumed receiver state */ - update_assumed_receiver_state(); - /* Cut out common prefix of all states */ - rationalize_states(); - string diff = current_state.diff_from( assumed_receiver_state->state ); - if ( diff.empty() && (timestamp() >= next_ack_time) ) { + if ( diff.empty() && (now >= next_ack_time) ) { send_empty_ack(); return; } - if ( !diff.empty() && ( (timestamp() >= next_send_time) - || (timestamp() >= next_ack_time) ) ) { + if ( !diff.empty() && ( (now >= next_send_time) + || (now >= next_ack_time) ) ) { /* Send diffs or ack */ send_to_receiver( diff ); + return; } } @@ -156,6 +171,7 @@ void TransportSender::send_empty_ack( void ) send_in_fragments( "", new_num ); next_ack_time = timestamp() + ACK_INTERVAL; + next_send_time = uint64_t(-1); } template diff --git a/src/network/transportsender.h b/src/network/transportsender.h index 82c7bf3..127c3a7 100644 --- a/src/network/transportsender.h +++ b/src/network/transportsender.h @@ -44,6 +44,7 @@ namespace Network { static const int ACK_DELAY = 100; /* ms before delayed ack */ static const int SHUTDOWN_RETRIES = 3; /* number of shutdown packets to send before giving up */ static const int ECHO_TIMEOUT = 50; /* for late ack */ + static const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */ /* helper methods for tick() */ void update_assumed_receiver_state( void ); @@ -72,6 +73,8 @@ namespace Network { uint64_t next_ack_time; uint64_t next_send_time; + void calculate_timers( void ); + bool verbose; bool shutdown_in_progress; int shutdown_tries; @@ -86,6 +89,8 @@ namespace Network { unsigned int SEND_MINDELAY; /* ms to collect all input */ + uint64_t last_heard; /* last time received new state */ + public: /* constructor */ TransportSender( Connection *s_connection, MyState &initial_state ); @@ -105,6 +110,9 @@ namespace Network { /* Accelerate reply ack */ void set_data_ack( void ) { pending_data_ack = true; } + /* Received something */ + void remote_heard( uint64_t ts ) { last_heard = ts; } + /* Starts shutdown sequence */ void start_shutdown( void ) { shutdown_in_progress = true; }