diff --git a/src/frontend/stmclient.cc b/src/frontend/stmclient.cc index e4f148c..f1139ca 100644 --- a/src/frontend/stmclient.cc +++ b/src/frontend/stmclient.cc @@ -415,6 +415,11 @@ void STMClient::main( void ) } network->tick(); + + const Network::NetworkException *exn = network->get_send_exception(); + if ( exn ) { + overlays.get_notification_engine().set_network_exception( *exn ); + } } catch ( Network::NetworkException e ) { if ( !network->shutdown_in_progress() ) { overlays.get_notification_engine().set_network_exception( e ); diff --git a/src/network/network.cc b/src/network/network.cc index 095b188..4df9506 100644 --- a/src/network/network.cc +++ b/src/network/network.cc @@ -131,7 +131,9 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se expected_receiver_seq( 0 ), RTT_hit( false ), SRTT( 1000 ), - RTTVAR( 500 ) + RTTVAR( 500 ), + have_send_exception( false ), + send_exception() { setup(); @@ -238,7 +240,9 @@ Connection::Connection( const char *key_str, const char *ip, int port ) /* clien expected_receiver_seq( 0 ), RTT_hit( false ), SRTT( 1000 ), - RTTVAR( 500 ) + RTTVAR( 500 ), + have_send_exception( false ), + send_exception() { setup(); @@ -266,9 +270,14 @@ void Connection::send( string s ) ssize_t bytes_sent = sendto( sock, p.data(), p.size(), 0, (sockaddr *)&remote_addr, sizeof( remote_addr ) ); - if ( (!server) /* Server treats all sendto()s as successful. */ - && (bytes_sent != static_cast( p.size() )) ) { - throw NetworkException( "sendto", errno ); + if ( bytes_sent == static_cast( p.size() ) ) { + have_send_exception = false; + } else { + /* Notify the frontend on sendto() failure, but don't alter control flow. + sendto() success is not very meaningful because packets can be lost in + flight anyway. */ + have_send_exception = true; + send_exception = NetworkException( "sendto", errno ); } } diff --git a/src/network/network.h b/src/network/network.h index a190f7e..83a29c4 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -42,6 +42,7 @@ namespace Network { string function; int the_errno; NetworkException( string s_function, int s_errno ) : function( s_function ), the_errno( s_errno ) {} + NetworkException() : function( "" ), the_errno( 0 ) {} }; enum Direction { @@ -101,6 +102,11 @@ namespace Network { double SRTT; double RTTVAR; + /* Exception from send(), to be delivered if the frontend asks for it, + without altering control flow. */ + bool have_send_exception; + NetworkException send_exception; + Packet new_packet( string &s_payload ); public: @@ -121,6 +127,11 @@ namespace Network { double get_SRTT( void ) const { return SRTT; } const struct in_addr & get_remote_ip( void ) const { return remote_addr.sin_addr; } + + const NetworkException *get_send_exception( void ) const + { + return have_send_exception ? &send_exception : NULL; + } }; } diff --git a/src/network/networktransport.h b/src/network/networktransport.h index 167f5c0..7019dd8 100644 --- a/src/network/networktransport.h +++ b/src/network/networktransport.h @@ -102,6 +102,8 @@ namespace Network { unsigned int send_interval( void ) const { return sender.send_interval(); } const struct in_addr & get_remote_ip( void ) const { return connection.get_remote_ip(); } + + const NetworkException *get_send_exception( void ) const { return connection.get_send_exception(); } }; }