Add client
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
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 rtm-server.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 stm-server.cpp stm.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 rtm-server
|
executables = parse termemu ntester encrypt decrypt stm-server stm
|
||||||
|
|
||||||
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 -O2 --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
|
||||||
LIBS = -lutil -lssl -lrt -lm -lprotobuf-lite
|
LIBS = -lutil -lssl -lrt -lm -lprotobuf-lite
|
||||||
PROTOC = protoc
|
PROTOC = protoc
|
||||||
|
|
||||||
@@ -26,8 +26,11 @@ 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
|
stm-server: stm-server.o $(objects) decrypt # serialize link steps because of -frepo
|
||||||
$(CXX) $(CXXFLAGS) -o $@ rtm-server.o $(objects) $(LIBS)
|
$(CXX) $(CXXFLAGS) -o $@ stm-server.o $(objects) $(LIBS)
|
||||||
|
|
||||||
|
stm: stm.o $(objects) stm-server # serialize link steps because of -frepo
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ stm.o $(objects) $(LIBS)
|
||||||
|
|
||||||
templates.o: templates.cpp
|
templates.o: templates.cpp
|
||||||
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ namespace Terminal {
|
|||||||
std::string act( const std::string &str );
|
std::string act( const std::string &str );
|
||||||
std::string act( const Parser::Action *act );
|
std::string act( const Parser::Action *act );
|
||||||
|
|
||||||
std::string open( void ) { return terminal.open(); }
|
|
||||||
std::string close( void ) { return terminal.close(); }
|
|
||||||
|
|
||||||
const Framebuffer & get_fb( void ) const { return terminal.get_fb(); }
|
const Framebuffer & get_fb( void ) const { return terminal.get_fb(); }
|
||||||
|
|
||||||
/* interface for Network::Transport */
|
/* interface for Network::Transport */
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ int main( void )
|
|||||||
serve( master );
|
serve( master );
|
||||||
}
|
}
|
||||||
|
|
||||||
printf( "[stm is exiting.]\n" );
|
printf( "[stm-server is exiting.]\n" );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -132,8 +132,6 @@ void serve( int host_fd )
|
|||||||
uint64_t last_remote_num = network.get_remote_state_num();
|
uint64_t last_remote_num = network.get_remote_state_num();
|
||||||
|
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
network.set_current_state( terminal );
|
|
||||||
|
|
||||||
int active_fds = poll( pollfds, 2, network.tick() );
|
int active_fds = poll( pollfds, 2, network.tick() );
|
||||||
if ( active_fds < 0 ) {
|
if ( active_fds < 0 ) {
|
||||||
perror( "poll" );
|
perror( "poll" );
|
||||||
@@ -155,6 +153,9 @@ void serve( int host_fd )
|
|||||||
terminal_to_host += terminal.act( us.get_action( i ) );
|
terminal_to_host += terminal.act( us.get_action( i ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update client with new state of terminal */
|
||||||
|
network.set_current_state( terminal );
|
||||||
|
|
||||||
/* write any writeback octets back to the host */
|
/* write any writeback octets back to the host */
|
||||||
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||||
break;
|
break;
|
||||||
@@ -176,8 +177,12 @@ void serve( int host_fd )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write any writeback octets back to the host */
|
|
||||||
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
||||||
|
|
||||||
|
/* update client with new state of terminal */
|
||||||
|
network.set_current_state( terminal );
|
||||||
|
|
||||||
|
/* write any writeback octets back to the host */
|
||||||
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
#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 <signal.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
|
||||||
|
#include "networktransport.hpp"
|
||||||
|
#include "completeterminal.hpp"
|
||||||
|
#include "swrite.hpp"
|
||||||
|
#include "user.hpp"
|
||||||
|
|
||||||
|
void client( const char *ip, int port, const char *key );
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
/* Get arguments */
|
||||||
|
char *ip, *key;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
if ( argc != 4 ) {
|
||||||
|
fprintf( stderr, "Usage: %s IP PORT KEY\n", argv[ 0 ] );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = argv[ 1 ];
|
||||||
|
port = atoi( argv[ 2 ] );
|
||||||
|
key = argv[ 3 ];
|
||||||
|
|
||||||
|
struct termios saved_termios, raw_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, &saved_termios ) < 0 ) {
|
||||||
|
perror( "tcgetattr" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put terminal driver in raw mode */
|
||||||
|
raw_termios = saved_termios;
|
||||||
|
if ( !(raw_termios.c_iflag & IUTF8) ) {
|
||||||
|
fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" );
|
||||||
|
raw_termios.c_iflag |= IUTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfmakeraw( &raw_termios );
|
||||||
|
|
||||||
|
if ( tcsetattr( STDIN_FILENO, TCSANOW, &raw_termios ) < 0 ) {
|
||||||
|
perror( "tcsetattr" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put terminal in application-cursor-key mode */
|
||||||
|
swrite( STDOUT_FILENO, Terminal::Emulator::open().c_str() );
|
||||||
|
|
||||||
|
client( ip, port, key );
|
||||||
|
|
||||||
|
/* Restore terminal and terminal-driver state */
|
||||||
|
swrite( STDOUT_FILENO, Terminal::Emulator::close().c_str() );
|
||||||
|
|
||||||
|
if ( tcsetattr( STDIN_FILENO, TCSANOW, &saved_termios ) < 0 ) {
|
||||||
|
perror( "tcsetattr" );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "[stm is exiting.]\n" );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client( const char *ip, int port, const char *key )
|
||||||
|
{
|
||||||
|
/* establish WINCH fd and start listening for signal */
|
||||||
|
sigset_t signal_mask;
|
||||||
|
assert( sigemptyset( &signal_mask ) == 0 );
|
||||||
|
assert( sigaddset( &signal_mask, SIGWINCH ) == 0 );
|
||||||
|
|
||||||
|
/* stop "ignoring" WINCH signal */
|
||||||
|
assert( sigprocmask( SIG_BLOCK, &signal_mask, NULL ) == 0 );
|
||||||
|
|
||||||
|
int winch_fd = signalfd( -1, &signal_mask, 0 );
|
||||||
|
if ( winch_fd < 0 ) {
|
||||||
|
perror( "signalfd" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get initial window size */
|
||||||
|
struct winsize window_size;
|
||||||
|
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
|
||||||
|
perror( "ioctl TIOCGWINSZ" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX transmit initial resize */
|
||||||
|
|
||||||
|
/* local state */
|
||||||
|
Terminal::Complete terminal( window_size.ws_col, window_size.ws_row );
|
||||||
|
Terminal::Framebuffer state( window_size.ws_col, window_size.ws_row );
|
||||||
|
|
||||||
|
/* open network */
|
||||||
|
Network::UserStream blank;
|
||||||
|
Network::Transport< Network::UserStream, Terminal::Complete > network( blank, terminal,
|
||||||
|
key, ip, port );
|
||||||
|
|
||||||
|
/* prepare to poll for events */
|
||||||
|
struct pollfd pollfds[ 3 ];
|
||||||
|
|
||||||
|
pollfds[ 0 ].fd = network.fd();
|
||||||
|
pollfds[ 0 ].events = POLLIN;
|
||||||
|
|
||||||
|
pollfds[ 1 ].fd = STDIN_FILENO;
|
||||||
|
pollfds[ 1 ].events = POLLIN;
|
||||||
|
|
||||||
|
pollfds[ 2 ].fd = winch_fd;
|
||||||
|
pollfds[ 2 ].events = POLLIN;
|
||||||
|
|
||||||
|
uint64_t last_remote_num = network.get_remote_state_num();
|
||||||
|
|
||||||
|
while ( 1 ) {
|
||||||
|
int active_fds = poll( pollfds, 3, network.tick() );
|
||||||
|
if ( active_fds < 0 ) {
|
||||||
|
perror( "poll" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||||
|
/* packet received from the network */
|
||||||
|
network.recv();
|
||||||
|
|
||||||
|
/* is a new frame available from the terminal? */
|
||||||
|
if ( network.get_remote_state_num() != last_remote_num ) {
|
||||||
|
string diff = network.get_remote_diff();
|
||||||
|
swrite( STDOUT_FILENO, diff.data(), diff.size() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pollfds[ 1 ].revents & POLLIN ) {
|
||||||
|
/* input from the user needs to be fed to the network */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < bytes_read; i++ ) {
|
||||||
|
network.get_current_state().push_back( Parser::UserByte( buf[ i ] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pollfds[ 2 ].revents & POLLIN ) {
|
||||||
|
/* handle resize */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||||
|
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,5 +31,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 Transport<Complete, UserStream>;
|
||||||
|
template class Transport<UserStream, Complete>;
|
||||||
|
|
||||||
template class deque<UserEvent>;
|
template class deque<UserEvent>;
|
||||||
|
|||||||
+2
-2
@@ -208,7 +208,7 @@ void emulate_terminal( int fd )
|
|||||||
pollfds[ 2 ].fd = winch_fd;
|
pollfds[ 2 ].fd = winch_fd;
|
||||||
pollfds[ 2 ].events = POLLIN;
|
pollfds[ 2 ].events = POLLIN;
|
||||||
|
|
||||||
swrite( STDOUT_FILENO, complete.open().c_str() );
|
swrite( STDOUT_FILENO, Terminal::Emulator::open().c_str() );
|
||||||
|
|
||||||
int poll_timeout = -1;
|
int poll_timeout = -1;
|
||||||
|
|
||||||
@@ -295,5 +295,5 @@ void emulate_terminal( int fd )
|
|||||||
std::string update = Terminal::Display::new_frame( true, state, complete.get_fb() );
|
std::string update = Terminal::Display::new_frame( true, state, complete.get_fb() );
|
||||||
swrite( STDOUT_FILENO, update.c_str() );
|
swrite( STDOUT_FILENO, update.c_str() );
|
||||||
|
|
||||||
swrite( STDOUT_FILENO, complete.close().c_str() );
|
swrite( STDOUT_FILENO, Terminal::Emulator::close().c_str() );
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -155,7 +155,5 @@ void Emulator::resize( size_t s_width, size_t s_height )
|
|||||||
|
|
||||||
bool Emulator::operator==( Emulator const &x ) const
|
bool Emulator::operator==( Emulator const &x ) const
|
||||||
{
|
{
|
||||||
assert( dispatch == x.dispatch );
|
return ( dispatch == x.dispatch ) && ( user == x.user ) && ( fb == x.fb );
|
||||||
assert( user == x.user );
|
|
||||||
return fb == x.fb;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -46,8 +46,8 @@ namespace Terminal {
|
|||||||
|
|
||||||
std::string read_octets_to_host( void );
|
std::string read_octets_to_host( void );
|
||||||
|
|
||||||
std::string open( void ); /* put user cursor keys in application mode */
|
static std::string open( void ); /* put user cursor keys in application mode */
|
||||||
std::string close( void ); /* restore user cursor keys */
|
static std::string close( void ); /* restore user cursor keys */
|
||||||
|
|
||||||
const Framebuffer & get_fb( void ) const { return fb; }
|
const Framebuffer & get_fb( void ) const { return fb; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user