Catch network exceptions
This commit is contained in:
+59
-55
@@ -135,75 +135,79 @@ 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 ) {
|
||||||
int active_fds = poll( pollfds, 2, network.tick() );
|
try {
|
||||||
if ( active_fds < 0 ) {
|
int active_fds = poll( pollfds, 2, network.tick() );
|
||||||
perror( "poll" );
|
if ( active_fds < 0 ) {
|
||||||
break;
|
perror( "poll" );
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ( pollfds[ 0 ].revents & POLLIN ) {
|
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||||
/* packet received from the network */
|
/* packet received from the network */
|
||||||
network.recv();
|
network.recv();
|
||||||
|
|
||||||
/* is new user input available for the terminal? */
|
/* is new user input available for the terminal? */
|
||||||
if ( network.get_remote_state_num() != last_remote_num ) {
|
if ( network.get_remote_state_num() != last_remote_num ) {
|
||||||
string terminal_to_host;
|
string terminal_to_host;
|
||||||
|
|
||||||
Network::UserStream us;
|
Network::UserStream us;
|
||||||
us.apply_string( network.get_remote_diff() );
|
us.apply_string( network.get_remote_diff() );
|
||||||
/* apply userstream to terminal */
|
/* apply userstream to terminal */
|
||||||
for ( size_t i = 0; i < us.size(); i++ ) {
|
for ( size_t i = 0; i < us.size(); i++ ) {
|
||||||
terminal_to_host += terminal.act( us.get_action( i ) );
|
terminal_to_host += terminal.act( us.get_action( i ) );
|
||||||
if ( typeid( *us.get_action( i ) ) == typeid( Parser::Resize ) ) {
|
if ( typeid( *us.get_action( i ) ) == typeid( Parser::Resize ) ) {
|
||||||
/* tell child process of resize */
|
/* tell child process of resize */
|
||||||
const Parser::Resize *res = static_cast<const Parser::Resize *>( us.get_action( i ) );
|
const Parser::Resize *res = static_cast<const Parser::Resize *>( us.get_action( i ) );
|
||||||
window_size.ws_col = res->width;
|
window_size.ws_col = res->width;
|
||||||
window_size.ws_row = res->height;
|
window_size.ws_row = res->height;
|
||||||
if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
|
if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
|
||||||
perror( "ioctl TIOCSWINSZ" );
|
perror( "ioctl TIOCSWINSZ" );
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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 ) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
||||||
|
|
||||||
/* update client with new state of terminal */
|
/* update client with new state of terminal */
|
||||||
network.set_current_state( 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||||
|
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||||
/* 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 ) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} catch ( Network::NetworkException e ) {
|
||||||
|
fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) );
|
||||||
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
|
||||||
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,70 +139,74 @@ void client( const char *ip, int port, const char *key )
|
|||||||
uint64_t last_remote_num = network.get_remote_state_num();
|
uint64_t last_remote_num = network.get_remote_state_num();
|
||||||
|
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
int active_fds = poll( pollfds, 3, network.tick() );
|
try {
|
||||||
if ( active_fds < 0 ) {
|
int active_fds = poll( pollfds, 3, network.tick() );
|
||||||
perror( "poll" );
|
if ( active_fds < 0 ) {
|
||||||
break;
|
perror( "poll" );
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if ( pollfds[ 0 ].revents & POLLIN ) {
|
|
||||||
/* packet received from the network */
|
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||||
network.recv();
|
/* packet received from the network */
|
||||||
|
network.recv();
|
||||||
/* is a new frame available from the terminal? */
|
|
||||||
if ( network.get_remote_state_num() != last_remote_num ) {
|
/* is a new frame available from the terminal? */
|
||||||
string diff = network.get_remote_diff();
|
if ( network.get_remote_state_num() != last_remote_num ) {
|
||||||
swrite( STDOUT_FILENO, diff.data(), diff.size() );
|
string diff = network.get_remote_diff();
|
||||||
|
swrite( STDOUT_FILENO, diff.data(), diff.size() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( pollfds[ 1 ].revents & POLLIN ) {
|
if ( pollfds[ 1 ].revents & POLLIN ) {
|
||||||
/* input from the user needs to be fed to the network */
|
/* input from the user needs to be fed to the network */
|
||||||
const int buf_size = 16384;
|
const int buf_size = 16384;
|
||||||
char buf[ buf_size ];
|
char buf[ buf_size ];
|
||||||
|
|
||||||
/* fill buffer if possible */
|
/* fill buffer if possible */
|
||||||
ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size );
|
ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size );
|
||||||
if ( bytes_read == 0 ) { /* EOF */
|
if ( bytes_read == 0 ) { /* EOF */
|
||||||
return;
|
return;
|
||||||
} else if ( bytes_read < 0 ) {
|
} else if ( bytes_read < 0 ) {
|
||||||
perror( "read" );
|
perror( "read" );
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < bytes_read; i++ ) {
|
||||||
|
network.get_current_state().push_back( Parser::UserByte( buf[ i ] ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < bytes_read; i++ ) {
|
if ( pollfds[ 2 ].revents & POLLIN ) {
|
||||||
network.get_current_state().push_back( Parser::UserByte( buf[ i ] ) );
|
/* 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 );
|
||||||
|
|
||||||
|
network.get_current_state().push_back( res );
|
||||||
|
|
||||||
if ( pollfds[ 2 ].revents & POLLIN ) {
|
/* tell local emulator -- there is probably a safer way to do this */
|
||||||
/* resize */
|
for ( list< Network::TimestampedState<Terminal::Complete> >::iterator i = network.begin();
|
||||||
struct signalfd_siginfo info;
|
i != network.end();
|
||||||
assert( read( winch_fd, &info, sizeof( info ) ) == sizeof( info ) );
|
i++ ) {
|
||||||
assert( info.ssi_signo == SIGWINCH );
|
i->state.act( &res );
|
||||||
|
}
|
||||||
/* get new size */
|
|
||||||
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
|
|
||||||
perror( "ioctl TIOCGWINSZ" );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tell remote emulator */
|
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||||
Parser::Resize res( window_size.ws_col, window_size.ws_row );
|
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||||
|
break;
|
||||||
network.get_current_state().push_back( res );
|
|
||||||
|
|
||||||
/* tell local emulator -- there is probably a safer way to do this */
|
|
||||||
for ( list< Network::TimestampedState<Terminal::Complete> >::iterator i = network.begin();
|
|
||||||
i != network.end();
|
|
||||||
i++ ) {
|
|
||||||
i->state.act( &res );
|
|
||||||
}
|
}
|
||||||
}
|
} catch ( Network::NetworkException e ) {
|
||||||
|
fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) );
|
||||||
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
|
||||||
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user