Pinger interface now allows to specify the number of pings to perform
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Tue, 1 Mar 2011 15:01:57 +0000 (16:01 +0100)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Wed, 2 Mar 2011 16:38:40 +0000 (17:38 +0100)
src/main.cpp
src/ping/boostpinger.cpp
src/ping/boostpinger.h
src/ping/pinger.h

index 8a611b7..7fc2099 100644 (file)
@@ -24,7 +24,7 @@ int main( int argc, char* argv[] )
             Configuration config = config_reader.get_configuration();
             Host host = config.get_host();
             string destination = host.get_address();
-            p.ping( destination );
+            p.ping( destination, 50 );
         }
         catch ( std::exception& e )
         {
index 75b7b92..5e09a67 100644 (file)
@@ -30,7 +30,10 @@ BoostPinger::BoostPinger(
     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() )
 {
 }
 
@@ -38,22 +41,53 @@ BoostPinger::~BoostPinger()
 {
 }
 
-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++;
@@ -65,17 +99,7 @@ void BoostPinger::start_send()
     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 )
@@ -89,14 +113,14 @@ 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.
@@ -133,10 +157,10 @@ void BoostPinger::handle_receive( const std::size_t &length )
     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 );
@@ -153,12 +177,18 @@ void BoostPinger::print_echo_reply(
     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()
index 1fdccfe..ecd35d9 100644 (file)
@@ -20,10 +20,17 @@ public:
     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();
 
@@ -45,7 +52,11 @@ private:
     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;
 
 };
 
index 3d1035c..41a7b8b 100644 (file)
@@ -13,7 +13,10 @@ public:
     Pinger();
     virtual ~Pinger();
 
-    virtual void ping( const std::string &destination ) = 0;
+    virtual void ping(
+            const std::string &destination,
+            const std::size_t times_to_ping
+    ) = 0;
 
 };