SequenceNumber( 0 ),
TimeSent( posix_time::microsec_clock::universal_time() ),
ReplyBuffer(),
- NumReplies( 0 )
+ RepliesCount( 0 ),
+ TimesToPingTotal( 0 ),
+ MinTimesToPing( 0 ),
+ MaxTimesToPing( std::numeric_limits<std::size_t>::max() )
{
}
{
}
-void BoostPinger::ping( const std::string &destination )
+void BoostPinger::ping(
+ const std::string &destination,
+ const std::size_t times_to_ping
+)
{
BOOST_ASSERT( !destination.empty() );
+ BOOST_ASSERT( ( MinTimesToPing < times_to_ping ) && ( times_to_ping < MaxTimesToPing ) );
icmp::resolver::query query( icmp::v4(), destination, "" );
DestinationEndpoint = *Resolver.resolve( query );
+ TimesToPingTotal = times_to_ping;
+
+ start_pinger();
+}
+
+void BoostPinger::start_pinger()
+{
start_send();
start_receive();
io_service.run();
}
+void BoostPinger::stop_pinger()
+{
+ io_service.stop();
+}
+
void BoostPinger::start_send()
{
- IcmpData icmp_data( "ping message" );
+ IcmpPacket icmp_echo_request_packet = create_echo_request_packet();
+
+ std::size_t times_already_pinged = SequenceNumber;
+ if ( times_already_pinged <= TimesToPingTotal )
+ {
+ send_echo_request( icmp_echo_request_packet );
+ }
+ else
+ {
+ stop_pinger();
+ }
+}
+
+IcmpPacket BoostPinger::create_echo_request_packet()
+{
+ IcmpData icmp_data( "ping-message" );
// Create an ICMP header for an echo request.
SequenceNumber++;
IcmpHeader icmp_header( type, code, checksum, identifier, SequenceNumber );
// Encode the ICMP header and data in an ICMP packet.
- IcmpPacket icmp_echo_request_packet( icmp_header, icmp_data );
-
- int ping_times = SequenceNumber;
- if ( ping_times < 4 )
- {
- send_echo_request( icmp_echo_request_packet );
- }
- else
- {
- io_service.stop();
- }
+ return IcmpPacket( icmp_header, icmp_data );
}
void BoostPinger::send_echo_request( const IcmpPacket &icmp_packet )
Socket.send_to( request_buffer.data(), DestinationEndpoint );
// Wait up to five seconds for a reply.
- NumReplies = 0;
+ RepliesCount = 0;
Timer.expires_at( TimeSent + posix_time::seconds( 5 ) );
Timer.async_wait( boost::bind( &BoostPinger::handle_timeout, this ) );
}
void BoostPinger::handle_timeout()
{
- if ( NumReplies == 0 )
+ if ( RepliesCount == 0 )
std::cout << "Request timed out" << std::endl;
// Requests must be sent no less than one second apart.
if ( is && icmp_packet.match( IcmpHeader::EchoReply, get_identifier(), SequenceNumber ) )
{
// If this is the first reply, interrupt the five second timeout.
- if ( NumReplies == 0 )
+ if ( RepliesCount == 0 )
Timer.cancel();
- ++NumReplies;
+ ++RepliesCount;
// Print out some information about the reply packet.
print_echo_reply( icmp_packet, length );
Ipv4Header ipv4_hdr = icmp_packet.get_ip_header();
IcmpHeader icmp_hdr = icmp_packet.get_icmp_header();
+ std::size_t bytes_received = length - ipv4_hdr.get_header_length();
+ std::string source_address = ipv4_hdr.get_source_address().to_string();
+ std::size_t sequence_number = icmp_hdr.get_sequence_number();
+ std::size_t ttl = ipv4_hdr.get_time_to_live();
posix_time::ptime now = posix_time::microsec_clock::universal_time();
- std::cout << ( length - ipv4_hdr.get_header_length() ) << " bytes from "
- << ipv4_hdr.get_source_address() << ": icmp_seq="
- << icmp_hdr.get_sequence_number() << ", ttl="
- << ipv4_hdr.get_time_to_live() << ", time="
- << (now - TimeSent).total_milliseconds() << " ms" << std::endl;
+ std::size_t time = (now - TimeSent).total_milliseconds();
+
+ std::cout << bytes_received << " bytes "
+ << "from " << source_address
+ << ": icmp_seq=" << sequence_number
+ << " ttl=" << ttl
+ << " time=" << time << " ms" << std::endl;
}
uint16_t BoostPinger::get_identifier()
BoostPinger( boost::asio::io_service &io_service );
virtual ~BoostPinger();
- void ping( const std::string &destination );
+ void ping(
+ const std::string &destination,
+ const std::size_t times_to_ping
+ );
private:
+ void start_pinger();
+ void stop_pinger();
+
void start_send();
+ IcmpPacket create_echo_request_packet();
void send_echo_request( const IcmpPacket &icmp_packet );
void handle_timeout();
uint16_t SequenceNumber;
boost::posix_time::ptime TimeSent;
boost::asio::streambuf ReplyBuffer;
- std::size_t NumReplies;
+ std::size_t RepliesCount;
+ std::size_t TimesToPingTotal;
+
+ const std::size_t MinTimesToPing;
+ const std::size_t MaxTimesToPing;
};