diff --git a/Makefile b/Makefile index d0b8269..ee24373 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -proto = userinput.proto transportinstruction.proto -source = parse.cpp parserstate.cpp parser.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp transportfragment.cpp user.cpp userinput.pb.cc completeterminal.cpp stm-server.cpp stm.cpp transportinstruction.pb.cc transportsender.cpp stmclient.cpp terminaloverlay.cpp -objects = parserstate.o parser.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o transportfragment.o user.o userinput.pb.o completeterminal.o transportinstruction.pb.o transportsender.o stmclient.o terminaloverlay.o +proto = userinput.proto hostinput.proto transportinstruction.proto +source = parse.cpp parserstate.cpp parser.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp transportfragment.cpp user.cpp userinput.pb.cc completeterminal.cpp stm-server.cpp stm.cpp transportinstruction.pb.cc transportsender.cpp stmclient.cpp terminaloverlay.cpp hostinput.pb.cc +objects = parserstate.o parser.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o transportfragment.o user.o userinput.pb.o completeterminal.o transportinstruction.pb.o transportsender.o stmclient.o terminaloverlay.o hostinput.pb.o executables = parse termemu ntester encrypt decrypt stm-server stm CXX = g++ diff --git a/completeterminal.cpp b/completeterminal.cpp index 52e0c61..3897414 100644 --- a/completeterminal.cpp +++ b/completeterminal.cpp @@ -1,8 +1,11 @@ #include "completeterminal.hpp" +#include "hostinput.pb.h" + using namespace std; using namespace Parser; using namespace Terminal; +using namespace HostBuffers; string Complete::act( const string &str ) { @@ -33,17 +36,36 @@ string Complete::act( const Action *act ) /* interface for Network::Transport */ string Complete::diff_from( const Complete &existing ) { - if ( existing.get_fb() == get_fb() ) { - return ""; - } else { - return Terminal::Display::new_frame( true, existing.get_fb(), terminal.get_fb() ); + HostBuffers::HostMessage output; + + if ( !(existing.get_fb() == get_fb()) ) { + if ( (existing.get_fb().ds.get_width() != terminal.get_fb().ds.get_width()) + || (existing.get_fb().ds.get_height() != terminal.get_fb().ds.get_height()) ) { + Instruction *new_res = output.add_instruction(); + new_res->MutableExtension( resize )->set_width( terminal.get_fb().ds.get_width() ); + new_res->MutableExtension( resize )->set_height( terminal.get_fb().ds.get_height() ); + } + Instruction *new_inst = output.add_instruction(); + new_inst->MutableExtension( hostbytes )->set_hoststring( Terminal::Display::new_frame( true, existing.get_fb(), terminal.get_fb() ) ); } + + return output.SerializeAsString(); } void Complete::apply_string( string diff ) { - string terminal_to_host = act( diff ); - assert( terminal_to_host.empty() ); + HostBuffers::HostMessage input; + assert( input.ParseFromString( diff ) ); + + for ( int i = 0; i < input.instruction_size(); i++ ) { + if ( input.instruction( i ).HasExtension( hostbytes ) ) { + string terminal_to_host = act( input.instruction( i ).GetExtension( hostbytes ).hoststring() ); + assert( terminal_to_host.empty() ); /* server never interrogates client terminal */ + } else if ( input.instruction( i ).HasExtension( resize ) ) { + act( new Resize( input.instruction( i ).GetExtension( resize ).width(), + input.instruction( i ).GetExtension( resize ).height() ) ); + } + } } bool Complete::operator==( Complete const &x ) const diff --git a/hostinput.proto b/hostinput.proto new file mode 100644 index 0000000..1b27274 --- /dev/null +++ b/hostinput.proto @@ -0,0 +1,25 @@ +option optimize_for = LITE_RUNTIME; + +package HostBuffers; + +message HostMessage { + repeated Instruction instruction = 1; +} + +message Instruction { + extensions 2 to max; +} + +message HostBytes { + optional bytes hoststring = 4; +} + +message ResizeMessage { + optional int32 width = 5; + optional int32 height = 6; +} + +extend Instruction { + optional HostBytes hostbytes = 2; + optional ResizeMessage resize = 3; +} diff --git a/network.hpp b/network.hpp index f6ec1b2..9d8f7d8 100644 --- a/network.hpp +++ b/network.hpp @@ -14,6 +14,8 @@ using namespace std; using namespace Crypto; namespace Network { + static const unsigned int MOSH_PROTOCOL_VERSION = 1; + uint64_t timestamp( void ); uint16_t timestamp16( void ); uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold ); diff --git a/networktransport.cpp b/networktransport.cpp index f61a785..5d8ead1 100644 --- a/networktransport.cpp +++ b/networktransport.cpp @@ -42,6 +42,10 @@ void Transport::recv( void ) if ( fragments.add_fragment( frag ) ) { /* complete packet */ Instruction inst = fragments.get_assembly(); + if ( inst.protocol_version() != MOSH_PROTOCOL_VERSION ) { + throw NetworkException( "Mosh protocol version mismatch", 0 ); + } + sender.process_acknowledgment_through( inst.ack_num() ); /* first, make sure we don't already have the new state */ diff --git a/networktransport.hpp b/networktransport.hpp index 35f7d71..1412b5e 100644 --- a/networktransport.hpp +++ b/networktransport.hpp @@ -67,9 +67,6 @@ namespace Network { MyState &get_current_state( void ) { return sender.get_current_state(); } void set_current_state( const MyState &x ) { sender.set_current_state( x ); } - typename list< TimestampedState >::iterator begin( void ) { return received_states.begin(); } - typename list< TimestampedState >::iterator end( void ) { return received_states.end(); } - uint64_t get_remote_state_num( void ) { return received_states.back().num; } const TimestampedState & get_latest_remote_state( void ) const { return received_states.back(); } diff --git a/stm-server.cpp b/stm-server.cpp index f1ca552..e2a21d3 100644 --- a/stm-server.cpp +++ b/stm-server.cpp @@ -73,6 +73,12 @@ int main( void ) exit( 1 ); } + /* clear STY environment variable so GNU screen regards us as top level */ + if ( unsetenv( "STY" ) < 0 ) { + perror( "unsetenv" ); + exit( 1 ); + } + /* get shell name */ struct passwd *pw = getpwuid( geteuid() ); if ( pw == NULL ) { @@ -84,7 +90,7 @@ int main( void ) my_argv[ 0 ] = strdup( pw->pw_shell ); assert( my_argv[ 0 ] ); my_argv[ 1 ] = NULL; - + if ( execve( pw->pw_shell, my_argv, environ ) < 0 ) { perror( "execve" ); exit( 1 ); diff --git a/stmclient.cpp b/stmclient.cpp index d534773..b913750 100644 --- a/stmclient.cpp +++ b/stmclient.cpp @@ -236,14 +236,9 @@ bool STMClient::process_resize( void ) if ( !network->shutdown_in_progress() ) { network->get_current_state().push_back( res ); } - - /* tell local emulator -- there is probably a safer way to do this */ - for ( auto i = network->begin(); - i != network->end(); - i++ ) { - i->state.act( &res ); - } + /* note remote emulator will probably reply with its own Resize to adjust our state */ + /* tell prediction engine */ overlays.get_prediction_engine().reset(); diff --git a/transportinstruction.proto b/transportinstruction.proto index 9c53c0e..20009fd 100644 --- a/transportinstruction.proto +++ b/transportinstruction.proto @@ -3,10 +3,12 @@ option optimize_for = LITE_RUNTIME; package TransportBuffers; message Instruction { - optional uint64 old_num = 1; - optional uint64 new_num = 2; - optional uint64 ack_num = 3; - optional uint64 throwaway_num = 4; + optional uint32 protocol_version = 1; - optional bytes diff = 5; + optional uint64 old_num = 2; + optional uint64 new_num = 3; + optional uint64 ack_num = 4; + optional uint64 throwaway_num = 5; + + optional bytes diff = 6; } diff --git a/transportsender.cpp b/transportsender.cpp index 8dd0882..d6b20b2 100644 --- a/transportsender.cpp +++ b/transportsender.cpp @@ -218,6 +218,7 @@ template void TransportSender::send_in_fragments( string diff, uint64_t new_num ) { Instruction inst; + inst.set_protocol_version( MOSH_PROTOCOL_VERSION ); inst.set_old_num( assumed_receiver_state->num ); inst.set_new_num( new_num ); inst.set_ack_num( ack_num );