From 8c7c5340d4dbb87ff8e124c3f3e71174a7a9e9b3 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 13 Feb 2012 03:50:03 -0500 Subject: [PATCH] User selectable prediction mode (fixes #9 github issue) --- scripts/mosh | 21 ++++++++++++++++++--- src/frontend/mosh-client.cc | 16 +++++++++++++--- src/frontend/stmclient.h | 17 +++++++++++++++-- src/frontend/terminaloverlay.cc | 12 +++++++++++- src/frontend/terminaloverlay.h | 15 ++++++++++++++- 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/scripts/mosh b/scripts/mosh index f1da350..6483b61 100755 --- a/scripts/mosh +++ b/scripts/mosh @@ -26,16 +26,31 @@ $|=1; my $client = 'mosh-client'; my $server = 'mosh-server'; +my $predict = 'adaptive'; my $usage = qq{Usage: $0 [options] [user@]host - --client=PATH mosh client on local machine (default: "mosh-client") - --server=PATH mosh server on remote machine (default: "mosh-server")\n}; + --client=PATH mosh client on local machine (default: "mosh-client") + --server=PATH mosh server on remote machine (default: "mosh-server") + + --predict=adaptive local echo for slower links [default] +-a --predict=always use local echo even on fast links +-n --predict=never never use local echo + +Please report bugs to mosh-devel\@mit.edu. +Mosh home page: http://mosh.mit.edu\n}; GetOptions( 'client=s' => \$client, 'server=s' => \$server, + 'predict=s' => \$predict, + 'a' => sub { $predict = 'always' }, + 'n' => sub { $predict = 'never' }, 'fake-proxy!' => \my $fake_proxy ) or die $usage; +if ( not exists { adaptive => 0, always => 0, never => 0 }->{ $predict } ) { + die $usage; +} + if ( defined $fake_proxy ) { use Errno qw(EINTR); use IO::Socket::INET; @@ -122,5 +137,5 @@ if ( $pid == 0 ) { # child # Now start real mosh client $ENV{ 'MOSH_KEY' } = $key; - exec {$client} ($client, $ip, $port); + exec {$client} ($client, $ip, $port, $predict); } diff --git a/src/frontend/mosh-client.cc b/src/frontend/mosh-client.cc index c112056..30141ed 100644 --- a/src/frontend/mosh-client.cc +++ b/src/frontend/mosh-client.cc @@ -22,14 +22,24 @@ #include "stmclient.h" #include "crypto.h" +void usage( const char *argv0 ) { + fprintf( stderr, "Usage: %s IP PORT [always|never|adaptive]\n", argv0 ); +} + int main( int argc, char *argv[] ) { /* Get arguments */ char *ip; int port; - if ( argc != 3 ) { - fprintf( stderr, "Usage: %s IP PORT\n", argv[ 0 ] ); + char *predict_mode = NULL; + + if ( argc == 4 ) { + predict_mode = argv[ 3 ]; + } else if ( argc == 3 ) { + /* do nothing */ + } else { + usage( argv[ 0 ]); exit( 1 ); } @@ -61,7 +71,7 @@ int main( int argc, char *argv[] ) } try { - STMClient client( ip, port, key ); + STMClient client( ip, port, key, predict_mode ); client.init(); try { diff --git a/src/frontend/stmclient.h b/src/frontend/stmclient.h index c03fce3..2256702 100644 --- a/src/frontend/stmclient.h +++ b/src/frontend/stmclient.h @@ -53,7 +53,7 @@ private: void output_new_frame( void ); public: - STMClient( const char *s_ip, int s_port, const char *s_key ) + STMClient( const char *s_ip, int s_port, const char *s_key, const char *predict_mode ) : ip( s_ip ), port( s_port ), key( s_key ), saved_termios(), raw_termios(), winch_fd(), shutdown_signal_fd(), @@ -63,7 +63,20 @@ public: network( NULL ), repaint_requested( false ), quit_sequence_started( false ) - {} + { + if ( predict_mode ) { + if ( !strcmp( predict_mode, "always" ) ) { + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Always ); + } else if ( !strcmp( predict_mode, "never" ) ) { + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Never ); + } else if ( !strcmp( predict_mode, "adaptive" ) ) { + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Adaptive ); + } else { + fprintf( stderr, "Unknown prediction mode %s.\n", predict_mode ); + exit( 1 ); + } + } + } void init( void ); void shutdown( void ); diff --git a/src/frontend/terminaloverlay.cc b/src/frontend/terminaloverlay.cc index adcea4c..428af49 100644 --- a/src/frontend/terminaloverlay.cc +++ b/src/frontend/terminaloverlay.cc @@ -315,7 +315,9 @@ void ConditionalOverlayRow::apply( Framebuffer &fb, uint64_t confirmed_epoch, bo void PredictionEngine::apply( Framebuffer &fb ) const { - bool show = srtt_trigger || glitch_trigger; + bool show = (display_preference != Never) && ( srtt_trigger + || glitch_trigger + || (display_preference == Always) ); if ( show ) { for_each( cursors.begin(), cursors.end(), [&]( const ConditionalCursorMove &x ) { x.apply( fb, confirmed_epoch ); } ); @@ -377,6 +379,10 @@ void PredictionEngine::init_cursor( const Framebuffer &fb ) void PredictionEngine::cull( const Framebuffer &fb ) { + if ( display_preference == Never ) { + return; + } + uint64_t now = timestamp(); /* control srtt_trigger with hysteresis */ @@ -547,6 +553,10 @@ ConditionalOverlayRow & PredictionEngine::get_or_make_row( int row_num, int num_ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { + if ( display_preference == Never ) { + return; + } + cull( fb ); uint64_t now = timestamp(); diff --git a/src/frontend/terminaloverlay.h b/src/frontend/terminaloverlay.h index 86848bb..9384e6e 100644 --- a/src/frontend/terminaloverlay.h +++ b/src/frontend/terminaloverlay.h @@ -185,6 +185,18 @@ namespace Overlay { unsigned int send_interval; public: + enum DisplayPreference { + Always, + Never, + Adaptive + }; + + private: + DisplayPreference display_preference; + + public: + void set_display_preference( DisplayPreference s_pref ) { display_preference = s_pref; } + void apply( Framebuffer &fb ) const; void new_user_byte( char the_byte, const Framebuffer &fb ); void cull( const Framebuffer &fb ); @@ -208,7 +220,8 @@ namespace Overlay { glitch_trigger( 0 ), last_quick_confirmation( 0 ), last_scheduled_timeout( 0 ), - send_interval( 250 ) + send_interval( 250 ), + display_preference( Adaptive ) { } };