istream &is
)
{
- BOOST_ASSERT( (icmp::v4() == protocol) || (icmp::v6() == protocol) );
-
IcmpPacketItem icmp_packet;
if ( icmp::v4() == protocol )
}
else
{
- BOOST_ASSERT( !"Invalid ICMP Packet Type." ); //lint !e506
+ GlobalLogger.warning() << "ICMP packet creation failed: "
+ << "Unknown protocol, expect ICMP v4 or v6!" << endl;
+ icmp_packet.reset(); // --> (!icmp_packet) is true
+ return icmp_packet;
}
- if ( !icmp_packet->read( is ) )
+ IcmpPacket::ReadReturnCode return_code = icmp_packet->read( is );
+ if ( return_code != IcmpPacket::ReadReturnCode_OK )
{
- GlobalLogger.info() << "ICMP packet creation failed" << endl;
+ GlobalLogger.warning() << "ICMP packet creation failed: "
+ << IcmpPacket::return_code_to_string(return_code) << endl;
icmp_packet.reset(); // --> (!icmp_packet) is true
// --> icmp_pinger will not try to continue working with this packet
// TODO why good packets are reports as bad? The read() has problems!
}
+ else if ( !is.good() )
+ {
+ GlobalLogger.warning() << "ICMP packet creation failed: "
+ << "Stream not good at end of creation!" << endl;
+ icmp_packet.reset(); // --> (!icmp_packet) is true
+ }
return icmp_packet;
}
ReplyReceived( false ),
EchoReplyTimeoutInSec( echo_reply_timeout_in_sec ),
PingerStatus( PingStatus_NotSent ),
- PingDoneCallback()
+ PingDoneCallback(),
+ ReceiveHandlerInPlace( false )
{
if ( !NetInterface.bind() )
{
- GlobalLogger.error() << "Error: could not bind the socket with the local interface. "
- << ::strerror( errno ) << endl;
+ GlobalLogger.error()
+ << DestinationEndpoint.address().to_string()
+ << ": could not bind the socket with the local interface. "
+ << ::strerror( errno ) << endl;
}
// Create "unique" identifier
ostream os( &request_buffer );
if ( !icmp_packet->write( os ) )
{
- GlobalLogger.error() << "Error: fail writing ping data." << endl;
+ GlobalLogger.error()
+ << DestinationEndpoint.address().to_string()
+ << ": fail writing ping data." << endl;
}
TimeSent = microsec_clock::universal_time();
size_t bytes_sent = Socket.send_to( data, DestinationEndpoint );
if ( bytes_sent != buffer_size( data ) )
{
- GlobalLogger.error() << "Error: fail sending ping data." << endl;
+ GlobalLogger.error()
+ << DestinationEndpoint.address().to_string()
+ << ": fail sending ping data." << endl;
}
}
catch ( const exception &ex )
{
- GlobalLogger.error() << "Error: fail sending ping data. " << ex.what() << endl;
+ GlobalLogger.error()
+ << DestinationEndpoint.address().to_string()
+ << ": fail sending ping data. " << ex.what() << endl;
}
schedule_timeout_echo_reply();
// is also called by Timer.cancel();
if ( !ReplyReceived )
{
- GlobalLogger.info() << "Request timed out" << endl;
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Request timed out" << endl;
set_ping_status( PingStatus_FailureTimeout );
}
void IcmpPinger::start_receive()
{
- // Discard any data already in the buffer.
- if (ReplyBuffer.size() > 0)
- GlobalLogger.debug() << "consuming unused " << ReplyBuffer.size() << "bytes!" << endl;
- ReplyBuffer.consume( ReplyBuffer.size() );
+ if ( ReceiveHandlerInPlace )
+ {
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Receive Handler in place, do not schedule another one" << endl;
+ return;
+ }
// Waiting for a reply, We prepare the buffer to receive up to SOCKET_BUFFER_SIZE bytes
Socket.async_receive(
ReplyBuffer.prepare( SOCKET_BUFFER_SIZE ),
- boost::bind( &IcmpPinger::handle_receive_icmp_packet, this, _2 )
+ boost::bind( &IcmpPinger::handle_receive_icmp_packet, this, _1, _2 )
);
+ ReceiveHandlerInPlace = true;
}
/**
* @param bytes_transferred Number of bytes transferred.
* @return void
**/
-void IcmpPinger::handle_receive_icmp_packet( const size_t &bytes_transferred )
+void IcmpPinger::handle_receive_icmp_packet( const boost::system::error_code &error,
+ const size_t &bytes_transferred )
{
+
+ ReceiveHandlerInPlace = false;
+
+ if ( error )
+ {
+ GlobalLogger.warning()
+ << DestinationEndpoint.address().to_string()
+ << ": Received error " << error << " in ICMP packet handler; end handler.";
+ return;
+ }
+ if ( ReplyReceived )
+ {
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Got another call to handler, probably due to earlier timeout. "
+ << "Ignore it." << endl;
+ return;
+ }
+
// The actual number of bytes received is committed to the buffer so that we
// can extract it using a std::istream object.
ReplyBuffer.commit( bytes_transferred );
istream is( &ReplyBuffer );
if ( !is )
{
- GlobalLogger.error() << "Error: can't handle ReplyBuffer" << endl;
+ GlobalLogger.error()
+ << DestinationEndpoint.address().to_string()
+ << ": Can't handle ReplyBuffer" << endl;
return;
}
IcmpPacketItem icmp_packet = IcmpPacketFactory::create_icmp_packet( Protocol, is );
if ( !icmp_packet )
{
- GlobalLogger.notice() << "Warning: ignoring broken ICMP packet" << endl;
+ GlobalLogger.warning()
+ << DestinationEndpoint.address().to_string()
+ << ": Ignoring broken ICMP packet" << endl;
return;
}
Identifier, SequenceNumber,
DestinationEndpoint.address() ) )
{
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Received reply" << endl;
+
ReplyReceived = true;
icmp_packet->print_echo_reply( bytes_transferred, TimeSent );
Identifier, SequenceNumber,
DestinationEndpoint.address() ) )
{
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Received destination unreachable" << endl;
+
ReplyReceived = true;
icmp_packet->print_destination_unreachable();
// Unknown ICMP reply, start another receive till timeout
else
{
+ GlobalLogger.info()
+ << DestinationEndpoint.address().to_string()
+ << ": Received packet that does not match" << endl;
start_receive();
}
}
catch ( ... )
{
- GlobalLogger.notice() << "Warning: exception during ICMP parse. "
+ GlobalLogger.notice()
+ << DestinationEndpoint.address().to_string()
+ << ": exception during ICMP parse. "
<< "Starting another receive till timeout." << endl;
start_receive();
}