#include "icmp/icmppacket.h"
#include "icmp/icmptype.h"
#include "icmp/ipv4header.h"
+#include "boostpinger.h"
using namespace std;
using boost::asio::const_buffers_1;
//-----------------------------------------------------------------------------
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 ),
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 ) )
* 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 )
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(
TimeSent + seconds( EchoReplyTimeoutInSec )
);
IcmpPacketReceiveTimer.async_wait(
- boost::bind( &BoostPinger::handle_timeout_icmp_packet, this )
+ boost::bind( &BoostPinger::handle_ping_done, this )
);
}
);
}
-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();
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 )
#define BOOSTPINGER_H
#include <boost/asio.hpp>
+#include <boost/function.hpp>
class IcmpPacket;
{
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
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;
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,
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
/// the status of the pinger
BoostPinger::PingStatus PingerStatus;
+ boost::function< void(bool) > PingDoneCallback;
};
#endif /* BOOSTPINGER_H */
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()
{
}
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()
}
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();