From: Thomas Jarosch Date: Wed, 4 May 2011 16:10:38 +0000 (+0200) Subject: Turn BoostPinger into true async operation X-Git-Tag: v1.0~22 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=24e706c4b526580c217c7523db567a102f52933f;p=pingcheck Turn BoostPinger into true async operation --- diff --git a/src/host/boostpinger.cpp b/src/host/boostpinger.cpp index 58fe87b..cc25af8 100644 --- a/src/host/boostpinger.cpp +++ b/src/host/boostpinger.cpp @@ -19,6 +19,7 @@ #include "icmp/icmppacket.h" #include "icmp/icmptype.h" #include "icmp/ipv4header.h" +#include "boostpinger.h" using namespace std; using boost::asio::const_buffers_1; @@ -36,10 +37,11 @@ using I2n::Logger::GlobalLogger; //----------------------------------------------------------------------------- BoostPinger::BoostPinger( + boost::asio::io_service &io_service, string source_network_interface, const int echo_reply_timeout_in_sec ) : - IoService(), + IoService(io_service), DestinationEndpoint(), Socket( IoService, icmp::v4() ), IcmpPacketReceiveTimer( IoService ), @@ -49,7 +51,8 @@ BoostPinger::BoostPinger( ReplyBuffer(), RepliesCount( 0 ), EchoReplyTimeoutInSec( echo_reply_timeout_in_sec ), - PingerStatus( PingStatus_NotSent ) + PingerStatus( PingStatus_NotSent ), + PingDoneCallback() { if ( !source_network_interface.empty() && !select_source_network_interface( source_network_interface ) ) @@ -74,29 +77,21 @@ BoostPinger::~BoostPinger() * Ping a destination address from an available local source. * * @param destination_ip The address of the host to ping. - * - * @return true if the ping was successfully performed, or false if the ping - * was not replied due a timeout. - * - * @note This method is synchronous, i.e. this method blocks and returns only - * after the ping requested has finished or timed-out. + * @param done_handler Done handler will be called on successful ping or timeout */ -bool BoostPinger::ping( const string &destination_ip ) +void BoostPinger::ping( const string &destination_ip, boost::function< void(bool) > ping_done_callback ) { BOOST_ASSERT( !destination_ip.empty() ); + PingDoneCallback = ping_done_callback; + // Prepare ping - IoService.reset(); PingerStatus = PingStatus_NotSent; set_destination_endpoint( destination_ip ); - // if start_pinger() does not block, the PingerStatus will be equal to - // PingStatus_NotSent, thus ping_success will be false - start_pinger(); - - bool ping_success = (PingerStatus == PingStatus_SuccessReply); - return ping_success; + start_send(); + start_receive(); } void BoostPinger::set_destination_endpoint( const string &destination_ip ) @@ -108,33 +103,14 @@ void BoostPinger::set_destination_endpoint( const string &destination_ip ) DestinationEndpoint = icmp::endpoint( destination_address, port ); } -void BoostPinger::start_pinger() -{ - start_send(); - start_receive(); - - (void) IoService.run(); -} - -void BoostPinger::stop_pinger() -{ - IoService.stop(); -} - void BoostPinger::start_send() { ++SequenceNumber; IcmpPacket icmp_echo_request_packet = create_echo_request( SequenceNumber ); - if ( PingerStatus == PingStatus_NotSent ) - { - send_echo_request( icmp_echo_request_packet ); - } - else - { - stop_pinger(); - } + BOOST_ASSERT( PingerStatus == PingStatus_NotSent ); + send_echo_request( icmp_echo_request_packet ); } IcmpPacket BoostPinger::create_echo_request( @@ -196,7 +172,7 @@ void BoostPinger::schedule_timeout_echo_reply() TimeSent + seconds( EchoReplyTimeoutInSec ) ); IcmpPacketReceiveTimer.async_wait( - boost::bind( &BoostPinger::handle_timeout_icmp_packet, this ) + boost::bind( &BoostPinger::handle_ping_done, this ) ); } @@ -212,7 +188,12 @@ void BoostPinger::start_receive() ); } -void BoostPinger::handle_timeout_icmp_packet() +/** + * @brief Gets called when the ping is finished: Either on timeout or on ping reply + * + * @return void + **/ +void BoostPinger::handle_ping_done() { // Check reply count as the timer handler // is also called by Timer.cancel(); @@ -222,6 +203,10 @@ void BoostPinger::handle_timeout_icmp_packet() set_ping_status( PingStatus_FailureTimeout ); } + + // Call ping-done handler + bool ping_success = (PingerStatus == PingStatus_SuccessReply); + PingDoneCallback(ping_success); } void BoostPinger::handle_receive_icmp_packet( const size_t &bytes_transferred ) diff --git a/src/host/boostpinger.h b/src/host/boostpinger.h index b0f4d9a..6d337fe 100644 --- a/src/host/boostpinger.h +++ b/src/host/boostpinger.h @@ -2,6 +2,7 @@ #define BOOSTPINGER_H #include +#include class IcmpPacket; @@ -17,12 +18,13 @@ class BoostPinger { public: BoostPinger( + boost::asio::io_service &io_service, std::string source_network_interface, const int echo_reply_timeout_in_sec ); virtual ~BoostPinger(); - bool ping( const std::string &destination_ip ); + void ping( const std::string &destination_ip, boost::function< void(bool) > ping_done_callback); private: enum PingStatus @@ -35,8 +37,6 @@ private: private: void set_destination_endpoint( const std::string &destination_ip ); - void start_pinger(); - void stop_pinger(); void start_send(); IcmpPacket create_echo_request( const uint16_t sequence_number ) const; @@ -44,8 +44,8 @@ private: void schedule_timeout_echo_reply(); void start_receive(); - void handle_timeout_icmp_packet(); void handle_receive_icmp_packet( const std::size_t &bytes_transferred ); + void handle_ping_done(); void print_echo_reply( const IcmpPacket &icmp_packet, @@ -65,7 +65,7 @@ private: private: /// io service object, which has the loop event - boost::asio::io_service IoService; + boost::asio::io_service &IoService; /// the destination host boost::asio::ip::icmp::endpoint DestinationEndpoint; /// the socket object @@ -88,6 +88,7 @@ private: /// the status of the pinger BoostPinger::PingStatus PingerStatus; + boost::function< void(bool) > PingDoneCallback; }; #endif /* BOOSTPINGER_H */ diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp index 3375cf8..91f6a7a 100644 --- a/src/host/pingscheduler.cpp +++ b/src/host/pingscheduler.cpp @@ -41,7 +41,7 @@ PingScheduler::PingScheduler( PingIntervalInSec( ping_interval_in_sec ), IpList( destination_address, nameserver ), HostAnalyzer( destination_address, ping_fail_percentage_limit, link_analyzer ), - Pinger(LocalNetworkInterfaceName, 5), + Pinger(IoService, LocalNetworkInterfaceName, 5), Thread() { } @@ -115,11 +115,11 @@ bool PingScheduler::resolve_ping_address() return true; } -bool PingScheduler::ping( const string &destination_ip ) +void PingScheduler::ping( const string &destination_ip ) { BOOST_ASSERT( !destination_ip.empty() ); - return Pinger.ping( destination_ip ); + Pinger.ping( destination_ip, boost::bind(&PingScheduler::ping_done_handler, this, _1) ); } void PingScheduler::setup_next_ping() @@ -139,8 +139,11 @@ void PingScheduler::setup_next_ping() } string destination_ip = IpList.get_next_ip(); - bool ping_success = ping( destination_ip ); + ping( destination_ip); +} +void PingScheduler::ping_done_handler(bool ping_success) +{ update_ping_statistics( ping_success ); update_ping_elapsed_time(); diff --git a/src/host/pingscheduler.h b/src/host/pingscheduler.h index 77e3af4..cea64ce 100644 --- a/src/host/pingscheduler.h +++ b/src/host/pingscheduler.h @@ -45,7 +45,9 @@ private: void stop_pinging(); bool resolve_ping_address(); - bool ping( const std::string &destination_ip ); + void ping( const std::string &destination_ip); + void ping_done_handler(bool ping_success); + void setup_next_ping(); void schedule_next_ping();