Import of server, all hooked together

This commit is contained in:
Keith Winstein
2011-08-13 17:10:19 -04:00
parent 71e22ee041
commit 577bfc0dae
20 changed files with 355 additions and 70 deletions
+5 -2
View File
@@ -1,8 +1,8 @@
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
repos = templates.rpo
executables = parse termemu ntester encrypt decrypt
executables = parse termemu ntester encrypt decrypt rtm-server
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
@@ -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
$(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
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
+21 -2
View File
@@ -2,8 +2,9 @@
using namespace std;
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++ ) {
/* parse octet into up to three actions */
@@ -22,9 +23,27 @@ string Terminal::Complete::act( const string &str )
return terminal.read_octets_to_host();
}
string Terminal::Complete::act( const Action *act )
string Complete::act( const Action *act )
{
/* apply action to terminal */
act->act_on_terminal( &terminal );
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;
}
+7 -1
View File
@@ -21,7 +21,13 @@ namespace Terminal {
std::string open( void ) { return terminal.open(); }
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;
};
}
+2 -2
View File
@@ -149,7 +149,7 @@ void Transport<MyState, RemoteState>::update_assumed_receiver_state( void )
template <class MyState, class RemoteState>
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 );
@@ -257,7 +257,7 @@ string Transport<MyState, RemoteState>::get_remote_diff( void )
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();
i != received_states.rend();
+2 -1
View File
@@ -105,7 +105,7 @@ namespace Network {
/* simple receiver */
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;
@@ -125,6 +125,7 @@ namespace Network {
string get_key( void ) { return connection.get_key(); }
MyState &get_current_state( void ) { return current_state; }
void set_current_state( const MyState &x ) { current_state = x; }
string get_remote_diff( void );
+10
View File
@@ -120,3 +120,13 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
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
View File
@@ -18,19 +18,25 @@
#endif
namespace Parser {
static StateFamily family;
class Parser {
private:
StateFamily family;
State *state;
State const *state;
public:
Parser() : family(), state( &family.s_Ground ) {}
Parser() : state( &family.s_Ground ) {}
Parser( const Parser & );
Parser( const Parser &other );
Parser & operator=( const Parser & );
~Parser() {}
std::list<Action *> input( wchar_t ch );
bool operator==( const Parser &x ) const
{
return state == x.state;
}
};
static const size_t BUF_SIZE = 8;
@@ -46,6 +52,11 @@ namespace Parser {
UTF8Parser();
std::list<Action *> input( char c );
bool operator==( const UTF8Parser &x ) const
{
return parser == x.parser;
}
};
}
+23 -23
View File
@@ -3,7 +3,7 @@
using namespace Parser;
Transition State::anywhere_rule( wchar_t ch )
Transition State::anywhere_rule( wchar_t ch ) const
{
if ( (ch == 0x18) || (ch == 0x1A)
|| ((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 */
}
Transition State::input( wchar_t ch )
Transition State::input( wchar_t ch ) const
{
Transition ret = anywhere_rule( ch );
if ( !ret.next_state ) {
@@ -56,7 +56,7 @@ static bool GLGR ( wchar_t ch )
|| ( (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 ) ) {
return Transition( new Execute );
@@ -69,12 +69,12 @@ Transition Ground::input_state_rule( wchar_t ch )
return Transition();
}
Action *Escape::enter( void )
Action *Escape::enter( void ) const
{
return new Clear;
}
Transition Escape::input_state_rule( wchar_t ch )
Transition Escape::input_state_rule( wchar_t ch ) const
{
if ( C0_prime( ch ) ) {
return Transition( new Execute );
@@ -112,7 +112,7 @@ Transition Escape::input_state_rule( wchar_t ch )
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 ) ) {
return Transition( new Execute );
@@ -129,12 +129,12 @@ Transition Escape_Intermediate::input_state_rule( wchar_t ch )
return Transition();
}
Action *CSI_Entry::enter( void )
Action *CSI_Entry::enter( void ) const
{
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 ) ) {
return Transition( new Execute );
@@ -164,7 +164,7 @@ Transition CSI_Entry::input_state_rule( wchar_t ch )
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 ) ) {
return Transition( new Execute );
@@ -189,7 +189,7 @@ Transition CSI_Param::input_state_rule( wchar_t ch )
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 ) ) {
return Transition( new Execute );
@@ -210,7 +210,7 @@ Transition CSI_Intermediate::input_state_rule( wchar_t ch )
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 ) ) {
return Transition( new Execute );
@@ -223,12 +223,12 @@ Transition CSI_Ignore::input_state_rule( wchar_t ch )
return Transition();
}
Action *DCS_Entry::enter( void )
Action *DCS_Entry::enter( void ) const
{
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) ) {
return Transition( new Collect, &family->s_DCS_Intermediate );
@@ -253,7 +253,7 @@ Transition DCS_Entry::input_state_rule( wchar_t ch )
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 ) ) {
return Transition( new Param );
@@ -274,7 +274,7 @@ Transition DCS_Param::input_state_rule( wchar_t ch )
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) ) {
return Transition( new Collect );
@@ -291,17 +291,17 @@ Transition DCS_Intermediate::input_state_rule( wchar_t ch )
return Transition();
}
Action *DCS_Passthrough::enter( void )
Action *DCS_Passthrough::enter( void ) const
{
return new Hook;
}
Action *DCS_Passthrough::exit( void )
Action *DCS_Passthrough::exit( void ) const
{
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) ) ) {
return Transition( new Put );
@@ -314,7 +314,7 @@ Transition DCS_Passthrough::input_state_rule( wchar_t ch )
return Transition();
}
Transition DCS_Ignore::input_state_rule( wchar_t ch )
Transition DCS_Ignore::input_state_rule( wchar_t ch ) const
{
if ( ch == 0x9C ) {
return Transition( &family->s_Ground );
@@ -323,17 +323,17 @@ Transition DCS_Ignore::input_state_rule( wchar_t ch )
return Transition();
}
Action *OSC_String::enter( void )
Action *OSC_String::enter( void ) const
{
return new OSC_Start;
}
Action *OSC_String::exit( void )
Action *OSC_String::exit( void ) const
{
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) ) {
return Transition( new OSC_Put );
@@ -346,7 +346,7 @@ Transition OSC_String::input_state_rule( wchar_t ch )
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 ) {
return Transition( &family->s_Ground );
+26 -26
View File
@@ -9,17 +9,17 @@ namespace Parser {
class State
{
protected:
virtual Transition input_state_rule( wchar_t ch ) = 0;
virtual Transition input_state_rule( wchar_t ch ) const = 0;
StateFamily *family;
private:
Transition anywhere_rule( wchar_t ch );
Transition anywhere_rule( wchar_t ch ) const;
public:
void setfamily( StateFamily *s_family ) { family = s_family; }
Transition input( wchar_t ch );
virtual Action *enter( void ) { return new Ignore; }
virtual Action *exit( void ) { return new Ignore; }
Transition input( wchar_t ch ) const;
virtual Action *enter( void ) const { return new Ignore; }
virtual Action *exit( void ) const { return new Ignore; }
State() : family( NULL ) {};
virtual ~State() {};
@@ -29,58 +29,58 @@ namespace Parser {
};
class Ground : public State {
Transition input_state_rule( wchar_t ch );
Transition input_state_rule( wchar_t ch ) const;
};
class Escape : public State {
Action *enter( void );
Transition input_state_rule( wchar_t ch );
Action *enter( void ) const;
Transition input_state_rule( wchar_t ch ) const;
};
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 {
Action *enter( void );
Transition input_state_rule( wchar_t ch );
Action *enter( void ) const;
Transition input_state_rule( wchar_t ch ) const;
};
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 {
Transition input_state_rule( wchar_t ch );
Transition input_state_rule( wchar_t ch ) const;
};
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 {
Action *enter( void );
Transition input_state_rule( wchar_t ch );
Action *enter( void ) const;
Transition input_state_rule( wchar_t ch ) const;
};
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 {
Transition input_state_rule( wchar_t ch );
Transition input_state_rule( wchar_t ch ) const;
};
class DCS_Passthrough : public State {
Action *enter( void );
Transition input_state_rule( wchar_t ch );
Action *exit( void );
Action *enter( void ) const;
Transition input_state_rule( wchar_t ch ) const;
Action *exit( void ) const;
};
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 {
Action *enter( void );
Transition input_state_rule( wchar_t ch );
Action *exit( void );
Action *enter( void ) const;
Transition input_state_rule( wchar_t ch ) const;
Action *exit( void ) const;
};
class SOS_PM_APC_String : public State {
Transition input_state_rule( wchar_t ch );
Transition input_state_rule( wchar_t ch ) const;
};
}
+191
View File
@@ -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;
}
}
}
+2
View File
@@ -5,6 +5,7 @@
#include <string>
#include "terminal.hpp"
#include "completeterminal.hpp"
#include "user.hpp"
#include "networktransport.cpp"
@@ -29,5 +30,6 @@ template class vector<bool>;
template class vector<Instruction>;
template class Transport<UserStream, UserStream>;
template class Transport<Complete, UserStream>;
template class deque<UserEvent>;
-1
View File
@@ -28,7 +28,6 @@
const size_t buf_size = 16384;
void emulate_terminal( int fd );
int copy( int src, int dest );
int main( void )
{
+7
View File
@@ -152,3 +152,10 @@ void Emulator::resize( size_t s_width, size_t 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
View File
@@ -49,7 +49,9 @@ namespace Terminal {
std::string open( void ); /* put user cursor keys in application mode */
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;
};
}
+6
View File
@@ -189,3 +189,9 @@ void Dispatcher::OSC_start( const Parser::OSC_Start *act )
OSC_string.clear();
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 );
}
+2
View File
@@ -76,6 +76,8 @@ namespace Terminal {
void OSC_put( const Parser::OSC_Put *act );
void OSC_start( const Parser::OSC_Start *act );
void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb );
bool operator==( const Dispatcher &x ) const;
};
}
+11
View File
@@ -151,6 +151,12 @@ namespace Terminal {
void resize( 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 {
@@ -227,6 +233,11 @@ namespace Terminal {
void reset_cell( Cell *c ) { c->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 );
}
};
}
+2
View File
@@ -16,6 +16,8 @@ namespace Terminal {
std::string input( const Parser::UserByte *act,
bool application_mode_cursor_keys );
bool operator==( const UserInput &x ) const { return last_byte == x.last_byte; }
};
}
+15 -3
View File
@@ -8,9 +8,9 @@ using namespace Parser;
using namespace Network;
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++ ) {
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();
@@ -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;
}
}
+5 -4
View File
@@ -40,13 +40,14 @@ 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 ) ); }
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 */
void subtract( UserStream * const prefix );
string diff_from( UserStream const & existing );
void subtract( const UserStream *prefix );
string diff_from( const UserStream &existing );
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; }
};
}