diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index 3974157..68e505c 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -245,13 +245,15 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network while ( 1 ) { try { - int active_fds = poll( pollfds, 3, network.wait_time() ); + uint64_t now = Network::timestamp(); + + int active_fds = poll( pollfds, 3, min( network.wait_time(), terminal.wait_time( now ) ) ); if ( active_fds < 0 ) { perror( "poll" ); break; } - uint64_t now = Network::timestamp(); + now = Network::timestamp(); if ( pollfds[ 0 ].revents & POLLIN ) { /* packet received from the network */ @@ -281,8 +283,10 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network } } - /* register input frame number for future echo ack */ - terminal.register_input_frame( last_remote_num, now ); + if ( !us.empty() ) { + /* register input frame number for future echo ack */ + terminal.register_input_frame( last_remote_num, now ); + } /* update client with new state of terminal */ if ( !network.shutdown_in_progress() ) { @@ -399,7 +403,13 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network } } - terminal.set_echo_ack( now ); + if ( terminal.set_echo_ack( now ) ) { + /* update client with new echo ack */ + if ( !network.shutdown_in_progress() ) { + network.set_current_state( terminal ); + } + } + network.tick(); } catch ( Network::NetworkException e ) { fprintf( stderr, "%s: %s\n", e.function.c_str(), strerror( e.the_errno ) ); diff --git a/src/network/transportsender.cc b/src/network/transportsender.cc index c8e5c97..b996d82 100644 --- a/src/network/transportsender.cc +++ b/src/network/transportsender.cc @@ -104,7 +104,11 @@ int TransportSender::wait_time( void ) { calculate_timers(); - uint64_t next_wakeup = min( next_ack_time, next_send_time ); + uint64_t next_wakeup = next_ack_time; + if ( next_send_time < next_wakeup ) { + next_wakeup = next_send_time; + } + uint64_t now = timestamp(); if ( !connection->get_attached() ) { diff --git a/src/statesync/completeterminal.cc b/src/statesync/completeterminal.cc index 83a8d1e..f473129 100644 --- a/src/statesync/completeterminal.cc +++ b/src/statesync/completeterminal.cc @@ -106,8 +106,9 @@ bool Complete::operator==( Complete const &x ) const return (terminal == x.terminal) && (echo_ack == x.echo_ack); } -void Complete::set_echo_ack( uint64_t now ) +bool Complete::set_echo_ack( uint64_t now ) { + bool ret = false; uint64_t newest_echo_ack = 0; for ( BOOST_AUTO( i, input_history.begin() ); i != input_history.end(); i++ ) { @@ -118,10 +119,33 @@ void Complete::set_echo_ack( uint64_t now ) input_history.remove_if( (&_1)->*&pair::first < newest_echo_ack ); + if ( echo_ack != newest_echo_ack ) { + ret = true; + } + echo_ack = newest_echo_ack; + + return ret; } void Complete::register_input_frame( uint64_t n, uint64_t now ) { input_history.push_back( make_pair( n, now ) ); } + +int Complete::wait_time( uint64_t now ) const +{ + if ( input_history.size() < 2 ) { + return INT_MAX; + } + + BOOST_AUTO( it, input_history.begin() ); + it++; + + uint64_t next_echo_ack_time = it->second + ECHO_TIMEOUT; + if ( next_echo_ack_time <= now ) { + return 0; + } else { + return next_echo_ack_time - now; + } +} diff --git a/src/statesync/completeterminal.h b/src/statesync/completeterminal.h index 273c5f3..99c4e5c 100644 --- a/src/statesync/completeterminal.h +++ b/src/statesync/completeterminal.h @@ -49,8 +49,9 @@ namespace Terminal { bool parser_grounded( void ) const { return parser.is_grounded(); } uint64_t get_echo_ack( void ) const { return echo_ack; } - void set_echo_ack( uint64_t now ); + bool set_echo_ack( uint64_t now ); void register_input_frame( uint64_t n, uint64_t now ); + int wait_time( uint64_t now ) const; /* interface for Network::Transport */ void subtract( const Complete * ) {} diff --git a/src/statesync/user.h b/src/statesync/user.h index ddfcd65..51384d2 100644 --- a/src/statesync/user.h +++ b/src/statesync/user.h @@ -68,7 +68,8 @@ namespace Network { void push_back( Parser::UserByte s_userbyte ) { actions.push_back( UserEvent( s_userbyte ) ); } void push_back( Parser::Resize s_resize ) { actions.push_back( UserEvent( s_resize ) ); } - size_t size( void ) { return actions.size(); } + bool empty( void ) const { return actions.empty(); } + size_t size( void ) const { return actions.size(); } const Parser::Action *get_action( unsigned int i ); /* interface for Network::Transport */