Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions man/mosh-client.1
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,38 @@ directly.
With the \-c option, \fBmosh-client\fP instead prints the number of colors
of the terminal given by the TERM environment variable.

The \-v option will print some debugging information on standard
error. More instances of this flag will result in more debugging
information. If standard error is not redirected from the terminal,
the display will be corrupted and quickly become unusable.

.SH ENVIRONMENT VARIABLES

.TP
.B MOSH_KEY
This variable must be set, and must contain a Base64-encoded cryptographic key from
.BR mosh-server (1).

.TP
.B MOSH_ESCAPE_KEY
See
.BR mosh (1).

.TP
.B MOSH_PREDICTION_DISPLAY
Controls local echo as described in
.BR mosh (1).

.TP
.B MOSH_PREDICTION_OVERWRITE
Controls local echo insert/overwrite as described in
.BR mosh (1).

.TP
.B MOSH_TITLE_NOPREFIX
See
.BR mosh (1).

.SH SEE ALSO
.BR mosh (1),
.BR mosh-server (1).
Expand Down
59 changes: 59 additions & 0 deletions man/mosh.1
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,67 @@ Synonym for \-\-predict=always
Synonym for \-\-predict=never

.TP

.B \-p \fINUM\fP, \-\-port=\fINUM\fP
Use a particular server-side UDP port, for example, if this is the

.B \-\-predict\-overwrite\fP
When prediction is enabled, do not insert speculative local echo
before existing text, but overwrite it instead.

The MOSH_PREDICTION_OVERWRITE environment variable also enables this
if its value is 'yes'.

.TP
.B \-o
Synonym for \-\-predict\-overwrite

.TP
.B \-\-family=inet
Only use IPv4 for the SSH connection and Mosh session.

.TP
.B \-\-family=inet6
Only use IPv6 for the SSH connection and Mosh session. This and the
following modes require Perl's IO::Socket::IP or IO::Socket::INET6
modules.

.TP
.B \-\-family=auto
Autodetect IPv4 or IPv6 for hosts that only have addresses
in a single family. Hosts with both IPv4 and IPv6 addresses will
raise an error, and require re-invocation of \fBmosh\fP with another
\fB\-\-family\fP option.

.TP
.B \-\-family=all
Choose an address from all available IPv4 or IPv6 address, even for
dual-stack hosts. This is the most convenient option, but requires
dual-stack connectivity, and Mosh 1.2.5 or later on the server, when
roaming with dual-stack servers.

.TP
.B \-\-family=prefer-inet
Similar to \fB\-\-family=all\fP, but attempt connects to the IPv4
addresses first. This is the default.

.TP
.B \-\-family=prefer-inet6
Similar to \fB\-\-family=all\fP, but attempt connects to the IPv6
addresses first.

.TP
.B \-4
Synonym for \-\-family=inet

.TP
.B \-6
Synonym for \-\-family=inet6

.TP
.B \-p \fIPORT\fP[:\fIPORT2\fP], \-\-port=\fIPORT\fP[:\fIPORT2\fP]
Use a particular server-side UDP port or port range,
for example, if this is the
only port that is forwarded through a firewall to the
server. Otherwise, \fBmosh\fP will choose a port between 60000 and
61000.
Expand Down
9 changes: 9 additions & 0 deletions scripts/mosh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ my $server = 'mosh-server';

my $predict = undef;

my $overwrite = 0;

my $port_request = undef;

my $ssh = 'ssh';
Expand All @@ -67,6 +69,8 @@ qq{Usage: $0 [options] [--] [user@]host [command...]
-n --predict=never never use local echo
--predict=experimental aggressively echo even when incorrect

-o --predict-overwrite prediction overwrites instead of inserting

-p NUM --port=NUM server-side UDP port

--ssh=COMMAND ssh command to run when setting up session
Expand Down Expand Up @@ -126,6 +130,7 @@ sub ip_and_sockaddr {
GetOptions( 'client=s' => \$client,
'server=s' => \$server,
'predict=s' => \$predict,
'predict-overwrite|o!' => \$overwrite,
'port=i' => \$port_request,
'a' => sub { $predict = 'always' },
'n' => sub { $predict = 'never' },
Expand All @@ -148,6 +153,10 @@ if ( defined $predict ) {
predict_check( $predict, 0 );
}

if ( $overwrite ) {
$ENV{ "MOSH_PREDICTION_OVERWRITE" } = "yes";
}

if ( defined $port_request ) {
if ( $port_request =~ m{^[0-9]+$}
and $port_request >= 0
Expand Down
6 changes: 5 additions & 1 deletion src/frontend/mosh-client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ int main( int argc, char *argv[] )
char *predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" );
/* can be NULL */

/* Read prediction insertion preference */
char *predict_overwrite = getenv( "MOSH_PREDICTION_OVERWRITE" );
/* can be NULL */

char *key = strdup( env_key );
if ( key == NULL ) {
perror( "strdup" );
Expand All @@ -141,7 +145,7 @@ int main( int argc, char *argv[] )
set_native_locale();

try {
STMClient client( ip, port, key, predict_mode );
STMClient client( ip, port, key, predict_mode, predict_overwrite );
client.init();

try {
Expand Down
5 changes: 4 additions & 1 deletion src/frontend/stmclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class STMClient {
}

public:
STMClient( const char *s_ip, int s_port, const char *s_key, const char *predict_mode )
STMClient( const char *s_ip, int s_port, const char *s_key, const char *predict_mode, const char *predict_overwrite )
: ip( s_ip ), port( s_port ), key( s_key ),
saved_termios(), raw_termios(),
window_size(),
Expand Down Expand Up @@ -103,6 +103,9 @@ class STMClient {
exit( 1 );
}
}
if ( predict_overwrite && !strcmp( predict_overwrite, "yes" ) ) {
overlays.get_prediction_engine().set_predict_overwrite( true );
}
}

void init( void );
Expand Down
48 changes: 31 additions & 17 deletions src/frontend/terminaloverlay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -662,32 +662,45 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
cursor().col--;
cursor().expire( local_frame_sent + 1, now );

for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];

if ( predict_overwrite ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ cursor().col ];
cell.reset_with_orig();
cell.active = true;
cell.tentative_until_epoch = prediction_epoch;
cell.expire( local_frame_sent + 1, now );
cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
const Cell orig_cell = *fb.get_cell();
cell.original_contents.push_back( orig_cell );
cell.replacement = orig_cell;
cell.replacement.clear();
cell.replacement.append(' ');
} else {
for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];

cell.reset_with_orig();
cell.active = true;
cell.tentative_until_epoch = prediction_epoch;
cell.expire( local_frame_sent + 1, now );
cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );

if ( i + 2 < fb.ds.get_width() ) {
ConditionalOverlayCell &next_cell = the_row.overlay_cells[ i + 1 ];
const Cell *next_cell_actual = fb.get_cell( cursor().row, i + 1 );

if ( next_cell.active ) {
if ( next_cell.unknown ) {
cell.unknown = true;
if ( i + 2 < fb.ds.get_width() ) {
ConditionalOverlayCell &next_cell = the_row.overlay_cells[ i + 1 ];
const Cell *next_cell_actual = fb.get_cell( cursor().row, i + 1 );

if ( next_cell.active ) {
if ( next_cell.unknown ) {
cell.unknown = true;
} else {
cell.unknown = false;
cell.replacement = next_cell.replacement;
}
} else {
cell.unknown = false;
cell.replacement = next_cell.replacement;
cell.replacement = *next_cell_actual;
}
} else {
cell.unknown = false;
cell.replacement = *next_cell_actual;
cell.unknown = true;
}
} else {
cell.unknown = true;
}
}
}
Expand All @@ -710,7 +723,8 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
}

/* do the insert */
for ( int i = fb.ds.get_width() - 1; i > cursor().col; i-- ) {
int rightmost_column = predict_overwrite ? cursor().col + 1 : fb.ds.get_width() - 1;
for ( int i = rightmost_column; i > cursor().col; i-- ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];
cell.reset_with_orig();
cell.active = true;
Expand Down
5 changes: 4 additions & 1 deletion src/frontend/terminaloverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ namespace Overlay {

private:
DisplayPreference display_preference;
bool predict_overwrite;

bool active( void ) const;

Expand All @@ -261,6 +262,7 @@ namespace Overlay {

public:
void set_display_preference( DisplayPreference s_pref ) { display_preference = s_pref; }
void set_predict_overwrite( bool overwrite ) { predict_overwrite = overwrite; }

void apply( Framebuffer &fb ) const;
void new_user_byte( char the_byte, const Framebuffer &fb );
Expand Down Expand Up @@ -291,7 +293,8 @@ namespace Overlay {
last_quick_confirmation( 0 ),
send_interval( 250 ),
last_height( 0 ), last_width( 0 ),
display_preference( Adaptive )
display_preference( Adaptive ),
predict_overwrite( false )
{
}
};
Expand Down