Import of server, all hooked together
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
proto = userinput.proto
|
proto = userinput.proto
|
||||||
source = parse.cpp parserstate.cpp parser.cpp templates.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 networkinstruction.cpp user.cpp userinput.pb.cc completeterminal.cpp
|
source = parse.cpp parserstate.cpp parser.cpp templates.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 networkinstruction.cpp user.cpp userinput.pb.cc completeterminal.cpp rtm-server.cpp
|
||||||
objects = parserstate.o parser.o templates.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 networkinstruction.o user.o userinput.pb.o completeterminal.o
|
objects = parserstate.o parser.o templates.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 networkinstruction.o user.o userinput.pb.o completeterminal.o
|
||||||
repos = templates.rpo
|
repos = templates.rpo
|
||||||
executables = parse termemu ntester encrypt decrypt
|
executables = parse termemu ntester encrypt decrypt rtm-server
|
||||||
|
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_BSD_SOURCE
|
CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_BSD_SOURCE
|
||||||
@@ -26,6 +26,9 @@ encrypt: encrypt.o $(objects) ntester # serialize link steps because of -frepo
|
|||||||
decrypt: decrypt.o $(objects) encrypt # serialize link steps because of -frepo
|
decrypt: decrypt.o $(objects) encrypt # serialize link steps because of -frepo
|
||||||
$(CXX) $(CXXFLAGS) -o $@ decrypt.o $(objects) $(LIBS)
|
$(CXX) $(CXXFLAGS) -o $@ decrypt.o $(objects) $(LIBS)
|
||||||
|
|
||||||
|
rtm-server: rtm-server.o $(objects) decrypt # serialize link steps because of -frepo
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ rtm-server.o $(objects) $(LIBS)
|
||||||
|
|
||||||
templates.o: templates.cpp
|
templates.o: templates.cpp
|
||||||
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
|
||||||
|
|
||||||
|
|||||||
+21
-2
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
using namespace Terminal;
|
||||||
|
|
||||||
string Terminal::Complete::act( const string &str )
|
string Complete::act( const string &str )
|
||||||
{
|
{
|
||||||
for ( unsigned int i = 0; i < str.size(); i++ ) {
|
for ( unsigned int i = 0; i < str.size(); i++ ) {
|
||||||
/* parse octet into up to three actions */
|
/* parse octet into up to three actions */
|
||||||
@@ -22,9 +23,27 @@ string Terminal::Complete::act( const string &str )
|
|||||||
return terminal.read_octets_to_host();
|
return terminal.read_octets_to_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
string Terminal::Complete::act( const Action *act )
|
string Complete::act( const Action *act )
|
||||||
{
|
{
|
||||||
/* apply action to terminal */
|
/* apply action to terminal */
|
||||||
act->act_on_terminal( &terminal );
|
act->act_on_terminal( &terminal );
|
||||||
return terminal.read_octets_to_host();
|
return terminal.read_octets_to_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* interface for Network::Transport */
|
||||||
|
string Complete::diff_from( const Complete &existing )
|
||||||
|
{
|
||||||
|
return Terminal::Display::new_frame( true, existing.get_fb(), terminal.get_fb() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Complete::apply_string( string diff )
|
||||||
|
{
|
||||||
|
string terminal_to_host = act( diff );
|
||||||
|
assert( terminal_to_host.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Complete::operator==( Complete const &x ) const
|
||||||
|
{
|
||||||
|
assert( parser == x.parser );
|
||||||
|
return terminal == x.terminal;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,13 @@ namespace Terminal {
|
|||||||
std::string open( void ) { return terminal.open(); }
|
std::string open( void ) { return terminal.open(); }
|
||||||
std::string close( void ) { return terminal.close(); }
|
std::string close( void ) { return terminal.close(); }
|
||||||
|
|
||||||
const Framebuffer & get_fb( void ) { return terminal.get_fb(); }
|
const Framebuffer & get_fb( void ) const { return terminal.get_fb(); }
|
||||||
|
|
||||||
|
/* interface for Network::Transport */
|
||||||
|
void subtract( const Complete * ) {}
|
||||||
|
std::string diff_from( const Complete &existing );
|
||||||
|
void apply_string( std::string diff );
|
||||||
|
bool operator==( const Complete &x ) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ void Transport<MyState, RemoteState>::update_assumed_receiver_state( void )
|
|||||||
template <class MyState, class RemoteState>
|
template <class MyState, class RemoteState>
|
||||||
void Transport<MyState, RemoteState>::rationalize_states( void )
|
void Transport<MyState, RemoteState>::rationalize_states( void )
|
||||||
{
|
{
|
||||||
MyState * const known_receiver_state = &sent_states.front().state;
|
const MyState * known_receiver_state = &sent_states.front().state;
|
||||||
|
|
||||||
current_state.subtract( known_receiver_state );
|
current_state.subtract( known_receiver_state );
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ string Transport<MyState, RemoteState>::get_remote_diff( void )
|
|||||||
|
|
||||||
string ret( received_states.back().state.diff_from( last_receiver_state ) );
|
string ret( received_states.back().state.diff_from( last_receiver_state ) );
|
||||||
|
|
||||||
MyState * const oldest_receiver_state = &received_states.front().state;
|
const RemoteState *oldest_receiver_state = &received_states.front().state;
|
||||||
|
|
||||||
for ( typename list< TimestampedState<RemoteState> >::reverse_iterator i = received_states.rbegin();
|
for ( typename list< TimestampedState<RemoteState> >::reverse_iterator i = received_states.rbegin();
|
||||||
i != received_states.rend();
|
i != received_states.rend();
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace Network {
|
|||||||
|
|
||||||
/* simple receiver */
|
/* simple receiver */
|
||||||
list< TimestampedState<RemoteState> > received_states;
|
list< TimestampedState<RemoteState> > received_states;
|
||||||
MyState last_receiver_state; /* the state we were in when user last queried state */
|
RemoteState last_receiver_state; /* the state we were in when user last queried state */
|
||||||
|
|
||||||
FragmentAssembly fragments;
|
FragmentAssembly fragments;
|
||||||
|
|
||||||
@@ -125,6 +125,7 @@ namespace Network {
|
|||||||
string get_key( void ) { return connection.get_key(); }
|
string get_key( void ) { return connection.get_key(); }
|
||||||
|
|
||||||
MyState &get_current_state( void ) { return current_state; }
|
MyState &get_current_state( void ) { return current_state; }
|
||||||
|
void set_current_state( const MyState &x ) { current_state = x; }
|
||||||
|
|
||||||
string get_remote_diff( void );
|
string get_remote_diff( void );
|
||||||
|
|
||||||
|
|||||||
+10
@@ -120,3 +120,13 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Parser::Parser::Parser( const Parser &other )
|
||||||
|
: state( other.state )
|
||||||
|
{}
|
||||||
|
|
||||||
|
Parser::Parser & Parser::Parser::operator=( const Parser &other )
|
||||||
|
{
|
||||||
|
state = other.state;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
+15
-4
@@ -18,19 +18,25 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Parser {
|
namespace Parser {
|
||||||
|
static StateFamily family;
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
private:
|
private:
|
||||||
StateFamily family;
|
State const *state;
|
||||||
State *state;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Parser() : family(), state( &family.s_Ground ) {}
|
Parser() : state( &family.s_Ground ) {}
|
||||||
|
|
||||||
Parser( const Parser & );
|
Parser( const Parser &other );
|
||||||
Parser & operator=( const Parser & );
|
Parser & operator=( const Parser & );
|
||||||
~Parser() {}
|
~Parser() {}
|
||||||
|
|
||||||
std::list<Action *> input( wchar_t ch );
|
std::list<Action *> input( wchar_t ch );
|
||||||
|
|
||||||
|
bool operator==( const Parser &x ) const
|
||||||
|
{
|
||||||
|
return state == x.state;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t BUF_SIZE = 8;
|
static const size_t BUF_SIZE = 8;
|
||||||
@@ -46,6 +52,11 @@ namespace Parser {
|
|||||||
UTF8Parser();
|
UTF8Parser();
|
||||||
|
|
||||||
std::list<Action *> input( char c );
|
std::list<Action *> input( char c );
|
||||||
|
|
||||||
|
bool operator==( const UTF8Parser &x ) const
|
||||||
|
{
|
||||||
|
return parser == x.parser;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using namespace Parser;
|
using namespace Parser;
|
||||||
|
|
||||||
Transition State::anywhere_rule( wchar_t ch )
|
Transition State::anywhere_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( (ch == 0x18) || (ch == 0x1A)
|
if ( (ch == 0x18) || (ch == 0x1A)
|
||||||
|| ((0x80 <= ch) && (ch <= 0x8F))
|
|| ((0x80 <= ch) && (ch <= 0x8F))
|
||||||
@@ -27,7 +27,7 @@ Transition State::anywhere_rule( wchar_t ch )
|
|||||||
return Transition( NULL, NULL ); /* don't allocate an Ignore action */
|
return Transition( NULL, NULL ); /* don't allocate an Ignore action */
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition State::input( wchar_t ch )
|
Transition State::input( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
Transition ret = anywhere_rule( ch );
|
Transition ret = anywhere_rule( ch );
|
||||||
if ( !ret.next_state ) {
|
if ( !ret.next_state ) {
|
||||||
@@ -56,7 +56,7 @@ static bool GLGR ( wchar_t ch )
|
|||||||
|| ( (0xA0 <= ch) && (ch <= 0xFF) ) ); /* GR area */
|
|| ( (0xA0 <= ch) && (ch <= 0xFF) ) ); /* GR area */
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition Ground::input_state_rule( wchar_t ch )
|
Transition Ground::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -69,12 +69,12 @@ Transition Ground::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *Escape::enter( void )
|
Action *Escape::enter( void ) const
|
||||||
{
|
{
|
||||||
return new Clear;
|
return new Clear;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition Escape::input_state_rule( wchar_t ch )
|
Transition Escape::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -112,7 +112,7 @@ Transition Escape::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition Escape_Intermediate::input_state_rule( wchar_t ch )
|
Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -129,12 +129,12 @@ Transition Escape_Intermediate::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *CSI_Entry::enter( void )
|
Action *CSI_Entry::enter( void ) const
|
||||||
{
|
{
|
||||||
return new Clear;
|
return new Clear;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition CSI_Entry::input_state_rule( wchar_t ch )
|
Transition CSI_Entry::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -164,7 +164,7 @@ Transition CSI_Entry::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition CSI_Param::input_state_rule( wchar_t ch )
|
Transition CSI_Param::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -189,7 +189,7 @@ Transition CSI_Param::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition CSI_Intermediate::input_state_rule( wchar_t ch )
|
Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -210,7 +210,7 @@ Transition CSI_Intermediate::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition CSI_Ignore::input_state_rule( wchar_t ch )
|
Transition CSI_Ignore::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) ) {
|
if ( C0_prime( ch ) ) {
|
||||||
return Transition( new Execute );
|
return Transition( new Execute );
|
||||||
@@ -223,12 +223,12 @@ Transition CSI_Ignore::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *DCS_Entry::enter( void )
|
Action *DCS_Entry::enter( void ) const
|
||||||
{
|
{
|
||||||
return new Clear;
|
return new Clear;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition DCS_Entry::input_state_rule( wchar_t ch )
|
Transition DCS_Entry::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
||||||
return Transition( new Collect, &family->s_DCS_Intermediate );
|
return Transition( new Collect, &family->s_DCS_Intermediate );
|
||||||
@@ -253,7 +253,7 @@ Transition DCS_Entry::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition DCS_Param::input_state_rule( wchar_t ch )
|
Transition DCS_Param::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) {
|
if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) {
|
||||||
return Transition( new Param );
|
return Transition( new Param );
|
||||||
@@ -274,7 +274,7 @@ Transition DCS_Param::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition DCS_Intermediate::input_state_rule( wchar_t ch )
|
Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
||||||
return Transition( new Collect );
|
return Transition( new Collect );
|
||||||
@@ -291,17 +291,17 @@ Transition DCS_Intermediate::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *DCS_Passthrough::enter( void )
|
Action *DCS_Passthrough::enter( void ) const
|
||||||
{
|
{
|
||||||
return new Hook;
|
return new Hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *DCS_Passthrough::exit( void )
|
Action *DCS_Passthrough::exit( void ) const
|
||||||
{
|
{
|
||||||
return new Unhook;
|
return new Unhook;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition DCS_Passthrough::input_state_rule( wchar_t ch )
|
Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( C0_prime( ch ) || ( (0x20 <= ch) && (ch <= 0x7E) ) ) {
|
if ( C0_prime( ch ) || ( (0x20 <= ch) && (ch <= 0x7E) ) ) {
|
||||||
return Transition( new Put );
|
return Transition( new Put );
|
||||||
@@ -314,7 +314,7 @@ Transition DCS_Passthrough::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition DCS_Ignore::input_state_rule( wchar_t ch )
|
Transition DCS_Ignore::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( ch == 0x9C ) {
|
if ( ch == 0x9C ) {
|
||||||
return Transition( &family->s_Ground );
|
return Transition( &family->s_Ground );
|
||||||
@@ -323,17 +323,17 @@ Transition DCS_Ignore::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *OSC_String::enter( void )
|
Action *OSC_String::enter( void ) const
|
||||||
{
|
{
|
||||||
return new OSC_Start;
|
return new OSC_Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *OSC_String::exit( void )
|
Action *OSC_String::exit( void ) const
|
||||||
{
|
{
|
||||||
return new OSC_End;
|
return new OSC_End;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition OSC_String::input_state_rule( wchar_t ch )
|
Transition OSC_String::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( (0x20 <= ch) && (ch <= 0x7F) ) {
|
if ( (0x20 <= ch) && (ch <= 0x7F) ) {
|
||||||
return Transition( new OSC_Put );
|
return Transition( new OSC_Put );
|
||||||
@@ -346,7 +346,7 @@ Transition OSC_String::input_state_rule( wchar_t ch )
|
|||||||
return Transition();
|
return Transition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition SOS_PM_APC_String::input_state_rule( wchar_t ch )
|
Transition SOS_PM_APC_String::input_state_rule( wchar_t ch ) const
|
||||||
{
|
{
|
||||||
if ( ch == 0x9C ) {
|
if ( ch == 0x9C ) {
|
||||||
return Transition( &family->s_Ground );
|
return Transition( &family->s_Ground );
|
||||||
|
|||||||
+26
-26
@@ -9,17 +9,17 @@ namespace Parser {
|
|||||||
class State
|
class State
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual Transition input_state_rule( wchar_t ch ) = 0;
|
virtual Transition input_state_rule( wchar_t ch ) const = 0;
|
||||||
StateFamily *family;
|
StateFamily *family;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Transition anywhere_rule( wchar_t ch );
|
Transition anywhere_rule( wchar_t ch ) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setfamily( StateFamily *s_family ) { family = s_family; }
|
void setfamily( StateFamily *s_family ) { family = s_family; }
|
||||||
Transition input( wchar_t ch );
|
Transition input( wchar_t ch ) const;
|
||||||
virtual Action *enter( void ) { return new Ignore; }
|
virtual Action *enter( void ) const { return new Ignore; }
|
||||||
virtual Action *exit( void ) { return new Ignore; }
|
virtual Action *exit( void ) const { return new Ignore; }
|
||||||
|
|
||||||
State() : family( NULL ) {};
|
State() : family( NULL ) {};
|
||||||
virtual ~State() {};
|
virtual ~State() {};
|
||||||
@@ -29,58 +29,58 @@ namespace Parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Ground : public State {
|
class Ground : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Escape : public State {
|
class Escape : public State {
|
||||||
Action *enter( void );
|
Action *enter( void ) const;
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Escape_Intermediate : public State {
|
class Escape_Intermediate : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CSI_Entry : public State {
|
class CSI_Entry : public State {
|
||||||
Action *enter( void );
|
Action *enter( void ) const;
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class CSI_Param : public State {
|
class CSI_Param : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class CSI_Intermediate : public State {
|
class CSI_Intermediate : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class CSI_Ignore : public State {
|
class CSI_Ignore : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DCS_Entry : public State {
|
class DCS_Entry : public State {
|
||||||
Action *enter( void );
|
Action *enter( void ) const;
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class DCS_Param : public State {
|
class DCS_Param : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class DCS_Intermediate : public State {
|
class DCS_Intermediate : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
class DCS_Passthrough : public State {
|
class DCS_Passthrough : public State {
|
||||||
Action *enter( void );
|
Action *enter( void ) const;
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
Action *exit( void );
|
Action *exit( void ) const;
|
||||||
};
|
};
|
||||||
class DCS_Ignore : public State {
|
class DCS_Ignore : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OSC_String : public State {
|
class OSC_String : public State {
|
||||||
Action *enter( void );
|
Action *enter( void ) const;
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
Action *exit( void );
|
Action *exit( void ) const;
|
||||||
};
|
};
|
||||||
class SOS_PM_APC_String : public State {
|
class SOS_PM_APC_String : public State {
|
||||||
Transition input_state_rule( wchar_t ch );
|
Transition input_state_rule( wchar_t ch ) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+191
@@ -0,0 +1,191 @@
|
|||||||
|
#include <locale.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <langinfo.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pty.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include "networktransport.hpp"
|
||||||
|
#include "completeterminal.hpp"
|
||||||
|
#include "swrite.hpp"
|
||||||
|
#include "user.hpp"
|
||||||
|
|
||||||
|
void serve( int host_fd );
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( void )
|
||||||
|
{
|
||||||
|
int master;
|
||||||
|
struct termios child_termios;
|
||||||
|
|
||||||
|
/* Adopt implementation locale */
|
||||||
|
if ( NULL == setlocale( LC_ALL, "" ) ) {
|
||||||
|
perror( "setlocale" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify locale calls for UTF-8 */
|
||||||
|
if ( strcmp( nl_langinfo( CODESET ), "UTF-8" ) != 0 ) {
|
||||||
|
fprintf( stderr, "stm requires a UTF-8 locale.\n" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify terminal configuration */
|
||||||
|
if ( tcgetattr( STDIN_FILENO, &child_termios ) < 0 ) {
|
||||||
|
perror( "tcgetattr" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(child_termios.c_iflag & IUTF8) ) {
|
||||||
|
fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" );
|
||||||
|
child_termios.c_iflag |= IUTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fork child process */
|
||||||
|
pid_t child = forkpty( &master, NULL, &child_termios, NULL );
|
||||||
|
|
||||||
|
if ( child == -1 ) {
|
||||||
|
perror( "forkpty" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( child == 0 ) {
|
||||||
|
/* child */
|
||||||
|
if ( setenv( "TERM", "xterm", true ) < 0 ) {
|
||||||
|
perror( "setenv" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ask ncurses to send UTF-8 instead of ISO 2022 for line-drawing chars */
|
||||||
|
if ( setenv( "NCURSES_NO_UTF8_ACS", "1", true ) < 0 ) {
|
||||||
|
perror( "setenv" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get shell name */
|
||||||
|
struct passwd *pw = getpwuid( geteuid() );
|
||||||
|
if ( pw == NULL ) {
|
||||||
|
perror( "getpwuid" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
char *my_argv[ 2 ];
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
exit( 0 );
|
||||||
|
} else {
|
||||||
|
/* parent */
|
||||||
|
serve( master );
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "[stm is exiting.]\n" );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serve( int host_fd )
|
||||||
|
{
|
||||||
|
/* get initial window size */
|
||||||
|
struct winsize window_size;
|
||||||
|
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
|
||||||
|
perror( "ioctl TIOCGWINSZ" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tell child process */
|
||||||
|
if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
|
||||||
|
perror( "ioctl TIOCSWINSZ" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open parser and terminal */
|
||||||
|
Terminal::Complete terminal( window_size.ws_col, window_size.ws_row );
|
||||||
|
|
||||||
|
/* open network */
|
||||||
|
Network::UserStream blank;
|
||||||
|
Network::Transport< Terminal::Complete, Network::UserStream > network( terminal, blank );
|
||||||
|
|
||||||
|
printf( "key= %s port= %d\n", network.get_key().c_str(), network.port() );
|
||||||
|
|
||||||
|
/* prepare to poll for events */
|
||||||
|
struct pollfd pollfds[ 2 ];
|
||||||
|
|
||||||
|
pollfds[ 0 ].fd = network.fd();
|
||||||
|
pollfds[ 0 ].events = POLLIN;
|
||||||
|
|
||||||
|
pollfds[ 1 ].fd = host_fd;
|
||||||
|
pollfds[ 1 ].events = POLLIN;
|
||||||
|
|
||||||
|
uint64_t last_remote_num = network.get_remote_state_num();
|
||||||
|
|
||||||
|
while ( 1 ) {
|
||||||
|
network.set_current_state( terminal );
|
||||||
|
|
||||||
|
int active_fds = poll( pollfds, 2, network.tick() );
|
||||||
|
if ( active_fds < 0 ) {
|
||||||
|
perror( "poll" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||||
|
/* packet received from the network */
|
||||||
|
network.recv();
|
||||||
|
|
||||||
|
/* is new user input available for the terminal? */
|
||||||
|
if ( network.get_remote_state_num() != last_remote_num ) {
|
||||||
|
string terminal_to_host;
|
||||||
|
|
||||||
|
Network::UserStream us;
|
||||||
|
us.apply_string( network.get_remote_diff() );
|
||||||
|
/* apply userstream to terminal */
|
||||||
|
for ( size_t i = 0; i < us.size(); i++ ) {
|
||||||
|
terminal_to_host += terminal.act( us.get_action( i ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write any writeback octets back to the host */
|
||||||
|
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pollfds[ 1 ].revents & POLLIN ) {
|
||||||
|
/* input from the host needs to be fed to the terminal */
|
||||||
|
const int buf_size = 16384;
|
||||||
|
char buf[ buf_size ];
|
||||||
|
|
||||||
|
/* fill buffer if possible */
|
||||||
|
ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size );
|
||||||
|
if ( bytes_read == 0 ) { /* EOF */
|
||||||
|
return;
|
||||||
|
} else if ( bytes_read < 0 ) {
|
||||||
|
perror( "read" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write any writeback octets back to the host */
|
||||||
|
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
||||||
|
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||||
|
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "terminal.hpp"
|
#include "terminal.hpp"
|
||||||
|
#include "completeterminal.hpp"
|
||||||
|
|
||||||
#include "user.hpp"
|
#include "user.hpp"
|
||||||
#include "networktransport.cpp"
|
#include "networktransport.cpp"
|
||||||
@@ -29,5 +30,6 @@ template class vector<bool>;
|
|||||||
|
|
||||||
template class vector<Instruction>;
|
template class vector<Instruction>;
|
||||||
template class Transport<UserStream, UserStream>;
|
template class Transport<UserStream, UserStream>;
|
||||||
|
template class Transport<Complete, UserStream>;
|
||||||
|
|
||||||
template class deque<UserEvent>;
|
template class deque<UserEvent>;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
const size_t buf_size = 16384;
|
const size_t buf_size = 16384;
|
||||||
|
|
||||||
void emulate_terminal( int fd );
|
void emulate_terminal( int fd );
|
||||||
int copy( int src, int dest );
|
|
||||||
|
|
||||||
int main( void )
|
int main( void )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -152,3 +152,10 @@ void Emulator::resize( size_t s_width, size_t s_height )
|
|||||||
{
|
{
|
||||||
fb.resize( s_width, s_height );
|
fb.resize( s_width, s_height );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Emulator::operator==( Emulator const &x ) const
|
||||||
|
{
|
||||||
|
assert( dispatch == x.dispatch );
|
||||||
|
assert( user == x.user );
|
||||||
|
return fb == x.fb;
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -49,7 +49,9 @@ namespace Terminal {
|
|||||||
std::string open( void ); /* put user cursor keys in application mode */
|
std::string open( void ); /* put user cursor keys in application mode */
|
||||||
std::string close( void ); /* restore user cursor keys */
|
std::string close( void ); /* restore user cursor keys */
|
||||||
|
|
||||||
const Framebuffer & get_fb( void ) { return fb; }
|
const Framebuffer & get_fb( void ) const { return fb; }
|
||||||
|
|
||||||
|
bool operator==( Emulator const &x ) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,3 +189,9 @@ void Dispatcher::OSC_start( const Parser::OSC_Start *act )
|
|||||||
OSC_string.clear();
|
OSC_string.clear();
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Dispatcher::operator==( const Dispatcher &x ) const
|
||||||
|
{
|
||||||
|
return ( params == x.params ) && ( parsed_params == x.parsed_params ) && ( parsed == x.parsed )
|
||||||
|
&& ( dispatch_chars == x.dispatch_chars ) && ( OSC_string == x.OSC_string ) && ( terminal_to_host == x.terminal_to_host );
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ namespace Terminal {
|
|||||||
void OSC_put( const Parser::OSC_Put *act );
|
void OSC_put( const Parser::OSC_Put *act );
|
||||||
void OSC_start( const Parser::OSC_Start *act );
|
void OSC_start( const Parser::OSC_Start *act );
|
||||||
void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb );
|
void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb );
|
||||||
|
|
||||||
|
bool operator==( const Dispatcher &x ) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ namespace Terminal {
|
|||||||
void resize( int s_width, int s_height );
|
void resize( int s_width, int s_height );
|
||||||
|
|
||||||
DrawState( int s_width, int s_height );
|
DrawState( int s_width, int s_height );
|
||||||
|
|
||||||
|
bool operator==( const DrawState &x ) const
|
||||||
|
{
|
||||||
|
/* XXX other fields not necessary to compare -- for now */
|
||||||
|
return ( width == x.width ) && ( height == x.height ) && ( renditions == x.renditions );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Framebuffer {
|
class Framebuffer {
|
||||||
@@ -227,6 +233,11 @@ namespace Terminal {
|
|||||||
|
|
||||||
void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
|
void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
|
||||||
void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); }
|
void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); }
|
||||||
|
|
||||||
|
bool operator==( const Framebuffer &x ) const
|
||||||
|
{
|
||||||
|
return ( rows == x.rows ) && ( window_title == x.window_title ) && ( ds == x.ds );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace Terminal {
|
|||||||
|
|
||||||
std::string input( const Parser::UserByte *act,
|
std::string input( const Parser::UserByte *act,
|
||||||
bool application_mode_cursor_keys );
|
bool application_mode_cursor_keys );
|
||||||
|
|
||||||
|
bool operator==( const UserInput &x ) const { return last_byte == x.last_byte; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ using namespace Parser;
|
|||||||
using namespace Network;
|
using namespace Network;
|
||||||
using namespace ClientBuffers;
|
using namespace ClientBuffers;
|
||||||
|
|
||||||
void UserStream::subtract( UserStream * const prefix )
|
void UserStream::subtract( const UserStream *prefix )
|
||||||
{
|
{
|
||||||
for ( deque<UserEvent>::iterator i = prefix->actions.begin();
|
for ( deque<UserEvent>::const_iterator i = prefix->actions.begin();
|
||||||
i != prefix->actions.end();
|
i != prefix->actions.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
assert( !actions.empty() );
|
assert( !actions.empty() );
|
||||||
@@ -19,7 +19,7 @@ void UserStream::subtract( UserStream * const prefix )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string UserStream::diff_from( UserStream const & existing )
|
string UserStream::diff_from( const UserStream &existing )
|
||||||
{
|
{
|
||||||
deque<UserEvent>::iterator my_it = actions.begin();
|
deque<UserEvent>::iterator my_it = actions.begin();
|
||||||
|
|
||||||
@@ -83,3 +83,15 @@ void UserStream::apply_string( string diff )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Parser::Action *UserStream::get_action( unsigned int i )
|
||||||
|
{
|
||||||
|
switch( actions[ i ].type ) {
|
||||||
|
case UserByteType:
|
||||||
|
return &( actions[ i ].userbyte );
|
||||||
|
case ResizeType:
|
||||||
|
return &( actions[ i ].resize );
|
||||||
|
default:
|
||||||
|
assert( false );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,13 +40,14 @@ namespace Network {
|
|||||||
void push_back( Parser::UserByte s_userbyte ) { actions.push_back( UserEvent( s_userbyte ) ); }
|
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 ) ); }
|
void push_back( Parser::Resize s_resize ) { actions.push_back( UserEvent( s_resize ) ); }
|
||||||
|
|
||||||
list<Parser::Action *> get_actions( void );
|
size_t size( void ) { return actions.size(); }
|
||||||
|
const Parser::Action *get_action( unsigned int i );
|
||||||
|
|
||||||
/* interface for Network::Transport */
|
/* interface for Network::Transport */
|
||||||
void subtract( UserStream * const prefix );
|
void subtract( const UserStream *prefix );
|
||||||
string diff_from( UserStream const & existing );
|
string diff_from( const UserStream &existing );
|
||||||
void apply_string( string diff );
|
void apply_string( string diff );
|
||||||
bool operator==( UserStream const &x ) const { return actions == x.actions; }
|
bool operator==( const UserStream &x ) const { return actions == x.actions; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user