From 0d85b410fe5ef900df2619622cb531b2dffb9204 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Fri, 30 Sep 2011 01:27:40 -0400 Subject: [PATCH] Split out functions in STMClient --- stmclient.cpp | 156 +++++++++++++++++++++++++++++--------------------- stmclient.hpp | 33 ++++++++++- 2 files changed, 123 insertions(+), 66 deletions(-) diff --git a/stmclient.cpp b/stmclient.cpp index 41348b6..354fe8e 100644 --- a/stmclient.cpp +++ b/stmclient.cpp @@ -61,9 +61,9 @@ void STMClient::shutdown( void ) } } -void STMClient::main( void ) +void STMClient::main_init( void ) { - /* establish WINCH fd and start listening for signal */ + /* establish WINCH fd and start listening for signal */ sigset_t signal_mask; assert( sigemptyset( &signal_mask ) == 0 ); assert( sigaddset( &signal_mask, SIGWINCH ) == 0 ); @@ -71,7 +71,7 @@ void STMClient::main( void ) /* stop "ignoring" WINCH signal */ assert( sigprocmask( SIG_BLOCK, &signal_mask, NULL ) == 0 ); - int winch_fd = signalfd( -1, &signal_mask, 0 ); + winch_fd = signalfd( -1, &signal_mask, 0 ); if ( winch_fd < 0 ) { perror( "signalfd" ); return; @@ -87,18 +87,17 @@ void STMClient::main( void ) /* don't let signals kill us */ assert( sigprocmask( SIG_BLOCK, &signal_mask, NULL ) == 0 ); - int shutdown_signal_fd = signalfd( -1, &signal_mask, 0 ); + shutdown_signal_fd = signalfd( -1, &signal_mask, 0 ); if ( shutdown_signal_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; - } + } /* local state */ Terminal::Complete terminal( window_size.ws_col, window_size.ws_row ); @@ -109,16 +108,87 @@ void STMClient::main( void ) /* open network */ Network::UserStream blank; - Network::Transport< Network::UserStream, Terminal::Complete > network( blank, terminal, - key.c_str(), ip.c_str(), port ); + network = new Network::Transport< Network::UserStream, Terminal::Complete >( blank, terminal, + key.c_str(), ip.c_str(), port ); /* tell server the size of the terminal */ - network.get_current_state().push_back( Parser::Resize( window_size.ws_col, window_size.ws_row ) ); + network->get_current_state().push_back( Parser::Resize( window_size.ws_col, window_size.ws_row ) ); +} + +bool STMClient::process_network_input( void ) +{ + 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() ); + } + + return true; +} + +bool STMClient::process_user_input( int fd ) +{ + const int buf_size = 16384; + char buf[ buf_size ]; + + /* fill buffer if possible */ + ssize_t bytes_read = read( fd, buf, buf_size ); + if ( bytes_read == 0 ) { /* EOF */ + return false; + } else if ( bytes_read < 0 ) { + perror( "read" ); + return false; + } + + if ( !network->shutdown_in_progress() ) { + for ( int i = 0; i < bytes_read; i++ ) { + network->get_current_state().push_back( Parser::UserByte( buf[ i ] ) ); + } + } + + return true; +} + +bool STMClient::process_resize( void ) +{ + struct signalfd_siginfo info; + assert( read( winch_fd, &info, sizeof( info ) ) == sizeof( info ) ); + assert( info.ssi_signo == SIGWINCH ); + + /* get new size */ + if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) { + perror( "ioctl TIOCGWINSZ" ); + return false; + } + + /* tell remote emulator */ + Parser::Resize res( window_size.ws_col, window_size.ws_row ); + + 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 ); + } + + return true; +} + +void STMClient::main( void ) +{ + /* initialize signal handling and structures */ + main_init(); /* prepare to poll for events */ struct pollfd pollfds[ 4 ]; - pollfds[ 0 ].fd = network.fd(); + pollfds[ 0 ].fd = network->fd(); pollfds[ 0 ].events = POLLIN; pollfds[ 1 ].fd = STDIN_FILENO; @@ -130,11 +200,11 @@ void STMClient::main( void ) pollfds[ 3 ].fd = shutdown_signal_fd; pollfds[ 3 ].events = POLLIN; - uint64_t last_remote_num = network.get_remote_state_num(); + last_remote_num = network->get_remote_state_num(); while ( 1 ) { try { - int active_fds = poll( pollfds, 4, network.wait_time() ); + int active_fds = poll( pollfds, 4, network->wait_time() ); if ( active_fds < 0 ) { perror( "poll" ); break; @@ -142,67 +212,23 @@ void STMClient::main( void ) 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 ( !process_network_input() ) { return; } } 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; - } - - if ( !network.shutdown_in_progress() ) { - for ( int i = 0; i < bytes_read; i++ ) { - network.get_current_state().push_back( Parser::UserByte( buf[ i ] ) ); - } - } + if ( !process_user_input( pollfds[ 1 ].fd ) ) { return; } } if ( pollfds[ 2 ].revents & POLLIN ) { /* resize */ - struct signalfd_siginfo info; - assert( read( winch_fd, &info, sizeof( info ) ) == sizeof( info ) ); - assert( info.ssi_signo == SIGWINCH ); - - /* get new size */ - if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) { - perror( "ioctl TIOCGWINSZ" ); - return; - } - - /* tell remote emulator */ - Parser::Resize res( window_size.ws_col, window_size.ws_row ); - - 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 ( list< Network::TimestampedState >::iterator i = network.begin(); - i != network.end(); - i++ ) { - i->state.act( &res ); - } + if ( !process_resize() ) { return; } } if ( pollfds[ 3 ].revents & POLLIN ) { /* shutdown signal */ - if ( network.attached() ) { - network.start_shutdown(); + if ( network->attached() ) { + network->start_shutdown(); } else { break; } @@ -217,20 +243,20 @@ void STMClient::main( void ) if ( (pollfds[ 1 ].revents) & (POLLERR | POLLHUP | POLLNVAL) ) { /* user problem */ - network.start_shutdown(); + network->start_shutdown(); } /* quit if our shutdown has been acknowledged */ - if ( network.shutdown_in_progress() && network.shutdown_acknowledged() ) { + if ( network->shutdown_in_progress() && network->shutdown_acknowledged() ) { break; } /* quit if we received and acknowledged a shutdown request */ - if ( network.counterparty_shutdown_ack_sent() ) { + if ( network->counterparty_shutdown_ack_sent() ) { break; } - network.tick(); + network->tick(); } catch ( Network::NetworkException e ) { fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) ); sleep( 1 ); diff --git a/stmclient.hpp b/stmclient.hpp index 93a6db9..99a561d 100644 --- a/stmclient.hpp +++ b/stmclient.hpp @@ -1,9 +1,14 @@ #ifndef STM_CLIENT_HPP #define STM_CLIENT_HPP +#include #include #include +#include "completeterminal.hpp" +#include "networktransport.hpp" +#include "user.hpp" + class STMClient { private: std::string ip; @@ -12,15 +17,41 @@ private: struct termios saved_termios, raw_termios; + int winch_fd, shutdown_signal_fd; + struct winsize window_size; + + Network::Transport< Network::UserStream, Terminal::Complete > *network; + uint64_t last_remote_num; + + void main_init( void ); + bool process_network_input( void ); + bool process_user_input( int fd ); + bool process_resize( void ); + public: STMClient( const char *s_ip, int s_port, const char *s_key ) : ip( s_ip ), port( s_port ), key( s_key ), - saved_termios(), raw_termios() + saved_termios(), raw_termios(), + winch_fd(), shutdown_signal_fd(), + window_size(), + network( NULL ), + last_remote_num( -1 ) {} void init( void ); void shutdown( void ); void main( void ); + + ~STMClient() + { + if ( network != NULL ) { + delete network; + } + } + + /* unused */ + STMClient( const STMClient & ); + STMClient & operator=( const STMClient & ); }; #endif