From 8f66f5292161c5fa92a97a46e8bdec0170777d8b Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Tue, 12 Apr 2011 14:10:07 +0200 Subject: [PATCH] Renamed packages to more appropriate names - ping to host, because it contains classes to deal with host - notify to link, contains classes that deal with many hosts, on link basis --- src/CMakeLists.txt | 10 +- src/host/boostpinger.cpp | 344 ++++++++++++++++++++++++++++++++++ src/host/boostpinger.h | 82 ++++++++ src/host/hoststatusanalyzer.cpp | 144 ++++++++++++++ src/host/hoststatusanalyzer.h | 52 +++++ src/host/pinginterval.h | 71 +++++++ src/host/pingscheduler.cpp | 149 +++++++++++++++ src/host/pingscheduler.h | 65 +++++++ src/link/linkstatusanalyzer.cpp | 175 +++++++++++++++++ src/link/linkstatusanalyzer.h | 81 ++++++++ src/link/statusnotifiercommand.cpp | 99 ++++++++++ src/link/statusnotifiercommand.h | 39 ++++ src/main.cpp | 4 +- src/notify/linkstatusanalyzer.cpp | 175 ----------------- src/notify/linkstatusanalyzer.h | 81 -------- src/notify/statusnotifiercommand.cpp | 99 ---------- src/notify/statusnotifiercommand.h | 39 ---- src/ping/boostpinger.cpp | 344 ---------------------------------- src/ping/boostpinger.h | 82 -------- src/ping/hoststatusanalyzer.cpp | 144 -------------- src/ping/hoststatusanalyzer.h | 52 ----- src/ping/pinginterval.h | 71 ------- src/ping/pingscheduler.cpp | 149 --------------- src/ping/pingscheduler.h | 65 ------- 24 files changed, 1308 insertions(+), 1308 deletions(-) create mode 100644 src/host/boostpinger.cpp create mode 100644 src/host/boostpinger.h create mode 100644 src/host/hoststatusanalyzer.cpp create mode 100644 src/host/hoststatusanalyzer.h create mode 100644 src/host/pinginterval.h create mode 100644 src/host/pingscheduler.cpp create mode 100644 src/host/pingscheduler.h create mode 100644 src/link/linkstatusanalyzer.cpp create mode 100644 src/link/linkstatusanalyzer.h create mode 100644 src/link/statusnotifiercommand.cpp create mode 100644 src/link/statusnotifiercommand.h delete mode 100644 src/notify/linkstatusanalyzer.cpp delete mode 100644 src/notify/linkstatusanalyzer.h delete mode 100644 src/notify/statusnotifiercommand.cpp delete mode 100644 src/notify/statusnotifiercommand.h delete mode 100644 src/ping/boostpinger.cpp delete mode 100644 src/ping/boostpinger.h delete mode 100644 src/ping/hoststatusanalyzer.cpp delete mode 100644 src/ping/hoststatusanalyzer.h delete mode 100644 src/ping/pinginterval.h delete mode 100644 src/ping/pingscheduler.cpp delete mode 100644 src/ping/pingscheduler.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13ee4d3..079cfa7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,9 @@ set(SOURCES config/host.cpp dns/dnsresolver.cpp dns/hostaddress.cpp + host/boostpinger.cpp + host/hoststatusanalyzer.cpp + host/pingscheduler.cpp icmp/icmpdestinationunreachablemessage.cpp icmp/icmpechoreplymessage.cpp icmp/icmpechorequestmessage.cpp @@ -33,11 +36,8 @@ set(SOURCES icmp/icmpheader.cpp icmp/icmppacket.cpp icmp/ipv4header.cpp - notify/linkstatusanalyzer.cpp - notify/statusnotifiercommand.cpp - ping/boostpinger.cpp - ping/hoststatusanalyzer.cpp - ping/pingscheduler.cpp + link/linkstatusanalyzer.cpp + link/statusnotifiercommand.cpp main.cpp ) diff --git a/src/host/boostpinger.cpp b/src/host/boostpinger.cpp new file mode 100644 index 0000000..2d35a98 --- /dev/null +++ b/src/host/boostpinger.cpp @@ -0,0 +1,344 @@ +#include "host/boostpinger.h" + +#include +#include +#include + +#include + +#include "icmp/icmpchecksumcalculator.h" +#include "icmp/icmpdata.h" +#include "icmp/icmpheader.h" +#include "icmp/icmppacket.h" +#include "icmp/icmptype.h" +#include "icmp/ipv4header.h" + +using namespace std; +using namespace boost::asio; +using namespace boost::asio::ip; +using namespace boost::posix_time; + +//----------------------------------------------------------------------------- +// BoostPinger +//----------------------------------------------------------------------------- + +BoostPinger::BoostPinger( + io_service &io_serv, + string source_network_interface, + const int echo_reply_timeout_in_sec +) : + IoService( io_serv ), + DestinationEndpoint(), + Socket( io_serv, icmp::v4() ), + IcmpPacketReceiveTimer( io_serv ), + SequenceNumber( 0 ), + TimeSent( microsec_clock::universal_time() ), + ReplyBuffer(), + RepliesCount( 0 ), + EchoReplyTimeoutInSec( echo_reply_timeout_in_sec ), + PingerStatus( PingStatus_NotSent ) +{ + BOOST_ASSERT( !source_network_interface.empty() ); + + if ( !select_source_network_interface( source_network_interface ) ) + { + cerr << "Error: could not bind the socket with the local interface." + << ::strerror( errno ) << endl; + } + +} + +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. + */ +bool BoostPinger::ping( const string &destination_ip ) +{ + BOOST_ASSERT( !destination_ip.empty() ); + + uint16_t port = 0; + address destination_address = ip::address::from_string( destination_ip ); + icmp::endpoint destination_endpoint( destination_address, port ); + DestinationEndpoint = destination_endpoint; + + start_pinger(); + + bool ping_success = (PingerStatus == PingStatus_SuccessReply); + return ping_success; +} + +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(); + } +} + +IcmpPacket BoostPinger::create_echo_request( + const uint16_t sequence_number +) const +{ + const IcmpData icmp_data( "ping-message" ); + + IcmpType type = IcmpType_EchoRequest; + uint8_t code = 0; + uint16_t identifier = get_identifier(); + IcmpChecksumCalculator calculator( icmp_data.begin(), icmp_data.end() ); + uint16_t checksum = calculator.compute( + type, code, identifier, sequence_number + ); + IcmpHeader icmp_header( + type, code, checksum, identifier, sequence_number + ); + + return IcmpPacket( icmp_header, icmp_data ); +} + +void BoostPinger::send_echo_request( const IcmpPacket &icmp_packet ) +{ + boost::asio::streambuf request_buffer; + ostream os( &request_buffer ); + os << icmp_packet; + + TimeSent = microsec_clock::universal_time(); + + string dest_address_string = DestinationEndpoint.address().to_string(); + BOOST_ASSERT( !dest_address_string.empty() ); + + // Send the request + try + { + const_buffers_1 data = request_buffer.data(); + size_t bytes_sent = Socket.send_to( data, DestinationEndpoint ); + if ( bytes_sent != buffer_size( data ) ) + { + cerr << "Error: fail sending ping data." << endl; + } + } + catch ( const exception &ex ) + { + cerr << "Error: fail sending ping data. " << ex.what() << endl; + } + + schedule_timeout_echo_reply(); +} + +void BoostPinger::schedule_timeout_echo_reply() +{ + // Wait up to N seconds for a reply. + RepliesCount = 0; + (void) IcmpPacketReceiveTimer.expires_at( + TimeSent + seconds( EchoReplyTimeoutInSec ) + ); + IcmpPacketReceiveTimer.async_wait( + boost::bind( &BoostPinger::handle_timeout_echo_reply, this ) + ); +} + +void BoostPinger::handle_timeout_echo_reply() +{ + if ( RepliesCount == 0 ) + { + print_request_timeout(); + + set_ping_status( PingStatus_FailureTimeout ); + } + + schedule_next_echo_request(); +} + +void BoostPinger::schedule_next_echo_request() +{ + // Requests must be sent no less than one second apart. + const int echo_request_interval_in_sec = 1; + (void) IcmpPacketReceiveTimer.expires_at( + TimeSent + seconds( echo_request_interval_in_sec ) + ); + IcmpPacketReceiveTimer.async_wait( + boost::bind( &BoostPinger::start_send, this ) + ); +} + +void BoostPinger::start_receive() +{ + // Discard any data already in the buffer. + ReplyBuffer.consume( ReplyBuffer.size() ); + + // Wait for a reply. We prepare the buffer to receive up to 64KB. + Socket.async_receive( + ReplyBuffer.prepare( 65536 ), + boost::bind( &BoostPinger::handle_receive_icmp_packet, this, _2 ) + ); +} + +void BoostPinger::handle_receive_icmp_packet( const size_t &bytes_transferred ) +{ + // 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 ) + return; + + // Decode the reply packet. + IcmpPacket icmp_packet; + is >> icmp_packet; + + // We can receive all ICMP packets received by the host, so we need to + // filter out only the echo replies that match the our identifier and + // expected sequence number. + if ( icmp_packet.match( + IcmpType_EchoReply, get_identifier(), SequenceNumber + ) ) + { + // If this is the first reply, interrupt the echo reply timeout. + if ( RepliesCount == 0 ) + { + (void) IcmpPacketReceiveTimer.cancel(); + } + + ++RepliesCount; + + print_echo_reply( icmp_packet, bytes_transferred ); + + set_ping_status( PingStatus_SuccessReply ); + } + else if ( icmp_packet.match( + IcmpType_DestinationUnreachable, get_identifier(), SequenceNumber + ) ) + { + // If this is the first reply, interrupt the echo reply timeout. + if ( RepliesCount == 0 ) + { + (void) IcmpPacketReceiveTimer.cancel(); + } + + ++RepliesCount; + + print_destination_unreachable( icmp_packet ); + + set_ping_status( PingStatus_FailureDestinationUnreachable ); + } + + start_receive(); +} + +void BoostPinger::print_request_timeout() const +{ + cout << "Request timed out" << endl; +} + +void BoostPinger::print_echo_reply( + const IcmpPacket &icmp_packet, + const size_t &bytes_transferred +) const +{ + BOOST_ASSERT( icmp_packet.get_icmp_header().get_type() == IcmpType_EchoReply ); + + Ipv4Header ipv4_hdr = icmp_packet.get_ip_header(); + IcmpHeader icmp_hdr = icmp_packet.get_icmp_header(); + + size_t bytes_received = bytes_transferred - ipv4_hdr.get_header_length(); + string remote_address = ipv4_hdr.get_source_address().to_string(); + uint16_t sequence_number = icmp_hdr.get_sequence_number(); + int ttl = ipv4_hdr.get_time_to_live(); + ptime now = microsec_clock::universal_time(); + int elapsed_time = (now - TimeSent).total_milliseconds(); + + cout << bytes_received << " bytes " + << "from " << remote_address + << ": icmp_seq=" << sequence_number + << " ttl=" << ttl + << " time=" << elapsed_time << " ms" << endl; +} + +void BoostPinger::print_destination_unreachable( + const IcmpPacket &icmp_packet +) const +{ + BOOST_ASSERT( icmp_packet.get_icmp_header().get_type() == IcmpType_DestinationUnreachable ); + + Ipv4Header ipv4_hdr = icmp_packet.get_ip_header(); + IcmpHeader icmp_hdr = icmp_packet.get_icmp_header(); + + string local_address = ipv4_hdr.get_destination_address().to_string(); + uint16_t sequence_number = icmp_hdr.get_sequence_number(); + + cout << "From " << local_address + << " icmp_seq=" << sequence_number + << " Destination Net Unreachable" << endl; +} + +void BoostPinger::set_ping_status( BoostPinger::PingStatus ping_status ) +{ + PingerStatus = ping_status; +} + +uint16_t BoostPinger::get_identifier() const +{ + return static_cast ( ::getpid() ); +} + +/** + * Avoid the socket to drop to another network interface if the destination + * is unreachable through the binded interface. Packets are sent only from + * this interface. + * + * @param source_network_interface The network interface to bind the pinger. + * + * @return false if the bind failed. + */ +bool BoostPinger::select_source_network_interface( + const string &source_network_interface +) +{ + BOOST_ASSERT( !source_network_interface.empty() ); + + int ret = ::setsockopt( + Socket.native(), + SOL_SOCKET, + SO_BINDTODEVICE, + source_network_interface.c_str(), + source_network_interface.size() + ); + if ( ret == -1 ) + { + return false; + } + + return true; +} diff --git a/src/host/boostpinger.h b/src/host/boostpinger.h new file mode 100644 index 0000000..1ed7233 --- /dev/null +++ b/src/host/boostpinger.h @@ -0,0 +1,82 @@ +#ifndef BOOSTPINGER_H +#define BOOSTPINGER_H + +#include + +class IcmpPacket; + +//----------------------------------------------------------------------------- +// BoostPinger +//----------------------------------------------------------------------------- + +/** + * @brief This class performs ping to host using Boost Asio. + * Scope: one object per host. + */ +class BoostPinger +{ +public: + BoostPinger( + boost::asio::io_service &io_serv, + std::string source_network_interface, + const int echo_reply_timeout_in_sec + ); + virtual ~BoostPinger(); + + bool ping( const std::string &destination_ip ); + +private: + enum PingStatus + { + PingStatus_NotSent, + PingStatus_SuccessReply, + PingStatus_FailureTimeout, + PingStatus_FailureDestinationUnreachable + }; + +private: + void start_pinger(); + void stop_pinger(); + + void start_send(); + IcmpPacket create_echo_request( const uint16_t sequence_number ) const; + void send_echo_request( const IcmpPacket &icmp_packet ); + void schedule_timeout_echo_reply(); + void handle_timeout_echo_reply(); + void schedule_next_echo_request(); + + void start_receive(); + void handle_receive_icmp_packet( const std::size_t &bytes_transferred ); + + void print_request_timeout() const; + void print_echo_reply( + const IcmpPacket &icmp_packet, + const std::size_t &bytes_transferred + ) const; + void print_destination_unreachable( + const IcmpPacket &icmp_packet + ) const; + + void set_ping_status( BoostPinger::PingStatus ping_status ); + + uint16_t get_identifier() const; + + bool select_source_network_interface( + const std::string &source_network_interface + ); + +private: + boost::asio::io_service &IoService; + boost::asio::ip::icmp::endpoint DestinationEndpoint; + boost::asio::ip::icmp::socket Socket; + boost::asio::deadline_timer IcmpPacketReceiveTimer; + uint16_t SequenceNumber; + boost::posix_time::ptime TimeSent; + boost::asio::streambuf ReplyBuffer; + int RepliesCount; + int EchoReplyTimeoutInSec; + BoostPinger::PingStatus PingerStatus; + +}; + +#endif /* BOOSTPINGER_H */ diff --git a/src/host/hoststatusanalyzer.cpp b/src/host/hoststatusanalyzer.cpp new file mode 100644 index 0000000..860df20 --- /dev/null +++ b/src/host/hoststatusanalyzer.cpp @@ -0,0 +1,144 @@ +#include "host/hoststatusanalyzer.h" + +#include + +#include + +using namespace std; +using namespace boost; + +//----------------------------------------------------------------------------- +// HostStatusAnalyzer +//----------------------------------------------------------------------------- + +/** + * @param host_address the address of the host it has to analyze. + * @param ping_fail_percentage_limit the percentage threshold of pings that can + * fail. + * @param link_analyzer the object used to notify the status of the host. + */ +HostStatusAnalyzer::HostStatusAnalyzer( + const string &host_address, + const int ping_fail_percentage_limit, + const shared_ptr link_analyzer +) : + HostAddress( host_address ), + LinkAnalyzer( link_analyzer ), + PingFailPercentageLimit( ping_fail_percentage_limit ), + ResolvedIpCount( 0 ), + PingsPerformedCount( 0 ), + PingsFailedCount( 0 ), + ExceededPingFailedLimit( false ) +{ + BOOST_ASSERT( !HostAddress.empty() ); + BOOST_ASSERT( ( 0 <= PingFailPercentageLimit ) && ( PingFailPercentageLimit <= 100 ) ); +} + +HostStatusAnalyzer::~HostStatusAnalyzer() +{ +} + +/** + * @param resolved_ip_count the number of IPs resolved for the host. + */ +void HostStatusAnalyzer::set_resolved_ip_count( const int resolved_ip_count ) +{ + BOOST_ASSERT( 1 <= resolved_ip_count ); + + ResolvedIpCount = resolved_ip_count; +} + +/** + * @return true if the amount of failed pings given to the host exceeded the + * limit. + */ +bool HostStatusAnalyzer::exceeded_ping_failed_limit() const +{ + return ExceededPingFailedLimit; +} + +/** + * Adds a ping status (success or failure). + * @param ping_success + */ +void HostStatusAnalyzer::update_ping_statistics( bool ping_success ) +{ + BOOST_ASSERT( 1 <= ResolvedIpCount ); + BOOST_ASSERT( 0 <= PingsPerformedCount ); + BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); + + increase_ping_performed_count(); + + if ( !ping_success ) + { + increase_ping_failed_count(); + } + + // after we tried all IPs resolved for this host, we can analyze how many + // failed + if ( tried_all_resolved_ip() ) + { + analyze_ping_statistics(); + + reset_ping_counters(); + } + + BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); +} + +bool HostStatusAnalyzer::tried_all_resolved_ip() const +{ + BOOST_ASSERT( ( 0 <= PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) ); + + return ( PingsPerformedCount == ResolvedIpCount ); +} + +void HostStatusAnalyzer::analyze_ping_statistics() +{ + BOOST_ASSERT( !HostAddress.empty() ); + BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount ); + + // notify if the amount of pings that failed exceed the limit + if ( exceeded_ping_failed_limit() ) + { + LinkAnalyzer->notify_host_down( HostAddress ); + } + else + { + LinkAnalyzer->notify_host_up( HostAddress ); + } + +} + +void HostStatusAnalyzer::reset_ping_counters() +{ + PingsPerformedCount = 0; + PingsFailedCount = 0; +} + +void HostStatusAnalyzer::increase_ping_performed_count() +{ + ++PingsPerformedCount; + + BOOST_ASSERT( ( 0 <= PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) ); +} + +void HostStatusAnalyzer::increase_ping_failed_count() +{ + ++PingsFailedCount; + + analyze_ping_failed_count(); + + BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); +} + +void HostStatusAnalyzer::analyze_ping_failed_count() +{ + BOOST_ASSERT( ( 0 <= PingFailPercentageLimit ) && ( PingFailPercentageLimit <= 100 ) ); + BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); + + int ping_fail_absolute_limit = PingFailPercentageLimit / 100; // TODO possible precision loss, check with care + + // keep a boolean variable because the PingsFailedCount can be reseted + ExceededPingFailedLimit = ( PingsFailedCount > ping_fail_absolute_limit ); +} diff --git a/src/host/hoststatusanalyzer.h b/src/host/hoststatusanalyzer.h new file mode 100644 index 0000000..0283cb5 --- /dev/null +++ b/src/host/hoststatusanalyzer.h @@ -0,0 +1,52 @@ +#ifndef HOSTSTATUSANALYZER_H +#define HOSTSTATUSANALYZER_H + +#include + +#include + +#include "link/linkstatusanalyzer.h" + +//----------------------------------------------------------------------------- +// HostStatusAnalyzer +//----------------------------------------------------------------------------- + +/** + * @brief This class analyze the host status (up or down) based on the pings + * responses (success or failure). And notifies its status. + * Scope: one object per host. + */ +class HostStatusAnalyzer +{ +public: + HostStatusAnalyzer( + const std::string &host_address, + const int ping_fail_percentage_limit, + const boost::shared_ptr link_analyzer + ); + virtual ~HostStatusAnalyzer(); + + void set_resolved_ip_count( const int resolved_ip_count ); + bool exceeded_ping_failed_limit() const; + void update_ping_statistics( bool ping_success ); + +private: + bool tried_all_resolved_ip() const; + void analyze_ping_statistics(); + void reset_ping_counters(); + void increase_ping_performed_count(); + void increase_ping_failed_count(); + void analyze_ping_failed_count(); + +private: + std::string HostAddress; + const boost::shared_ptr LinkAnalyzer; + int PingFailPercentageLimit; + int ResolvedIpCount; + int PingsPerformedCount; + int PingsFailedCount; + bool ExceededPingFailedLimit; + +}; + +#endif /* HOSTSTATUSANALYZER_H */ diff --git a/src/host/pinginterval.h b/src/host/pinginterval.h new file mode 100644 index 0000000..0676921 --- /dev/null +++ b/src/host/pinginterval.h @@ -0,0 +1,71 @@ +#ifndef PINGINTERVAL_H +#define PINGINTERVAL_H + +//----------------------------------------------------------------------------- +// PingInterval +//----------------------------------------------------------------------------- + +/** + * @brief Class designed to behave like a scalar type (i.e. int, long), but + * with helper methods to encapsulate interval computation. + * Scope: one object per host. + */ +template +class PingInterval +{ +public: + PingInterval( T interval ); + + operator T(); + + void back_to_original(); + void speed_up(); + +private: + bool can_speed_up() const; + +private: + const T OriginalInterval; + T Interval; + +}; + + +template + PingInterval::PingInterval( + T interval + ) : + OriginalInterval( interval ), + Interval( interval ) + { + } + +template + PingInterval::operator T() + { + return Interval; + } + +template + void PingInterval::back_to_original() + { + Interval = OriginalInterval; + } + +template + void PingInterval::speed_up() + { + if ( can_speed_up() ) + Interval = Interval / 2; + } + +template + bool PingInterval::can_speed_up() const + { + T half_original = OriginalInterval / 2; + + return (Interval > half_original); + } + + +#endif /* PINGINTERVAL_H */ diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp new file mode 100644 index 0000000..2b972d4 --- /dev/null +++ b/src/host/pingscheduler.cpp @@ -0,0 +1,149 @@ +#include "host/pingscheduler.h" + +#include + +#include + +#include "dns/dnsresolver.h" +#include "link/linkstatusanalyzer.h" +#include "host/boostpinger.h" + +using namespace std; +using namespace boost; +using namespace boost::asio; +using namespace boost::posix_time; + +//----------------------------------------------------------------------------- +// PingScheduler +//----------------------------------------------------------------------------- + +PingScheduler::PingScheduler( + boost::asio::io_service &io_serv, + const string &ping_interface, + const string &ping_address, + const long ping_interval_in_sec, + const int ping_fail_percentage_limit, + shared_ptr link_analyzer + +) : + IoService( io_serv ), + LocalNetworkInterfaceName( ping_interface ), + NextPingTimer( io_serv ), + TimeSentLastPing( microsec_clock::universal_time() ), + PingIntervalInSec( ping_interval_in_sec ), + IpList( ping_address ), + HostAnalyzer( ping_address, ping_fail_percentage_limit, link_analyzer ) +{ +} + +PingScheduler::~PingScheduler() +{ +} + +bool PingScheduler::start_pinging() +{ + bool address_resolved = resolve_ping_address(); + if ( !address_resolved ) + { + return false; + } + + schedule_next_ping(); + + return true; +} + +bool PingScheduler::resolve_ping_address() +{ + bool address_resolved = IpList.resolve(); + if ( !address_resolved ) + { + return false; + } + + int resolved_ip_count = IpList.get_resolved_ip_count(); + HostAnalyzer.set_resolved_ip_count( resolved_ip_count ); + + return true; +} + +void PingScheduler::setup_ping() +{ + BOOST_ASSERT( 1 <= IpList.get_resolved_ip_count() ); + + string destination_ip = IpList.get_next_ip(); + bool ping_success = ping( destination_ip ); + + update_ping_statistics( ping_success ); + update_ping_elapsed_time(); + + schedule_next_ping(); +} + +bool PingScheduler::ping( const string &destination_ip ) const +{ + BOOST_ASSERT( !destination_ip.empty() ); + + io_service io_serv; + int echo_reply_timeout_in_sec = 5; // TODO configurable: this is the timeout to WAIT FOR the ping before considering a timeout + + BoostPinger pinger( + io_serv, + LocalNetworkInterfaceName, + echo_reply_timeout_in_sec + ); + return pinger.ping( destination_ip ); +} + +void PingScheduler::schedule_next_ping() +{ + BOOST_ASSERT( 0 < PingIntervalInSec ); + + (void) NextPingTimer.expires_from_now( seconds( PingIntervalInSec ) ); + NextPingTimer.async_wait( bind( &PingScheduler::handle_next_ping, this ) ); +} + +void PingScheduler::handle_next_ping() +{ + setup_ping(); +} + +void PingScheduler::update_ping_statistics( const bool ping_success ) +{ + HostAnalyzer.update_ping_statistics( ping_success ); + + // TODO you must call the method bellow AFTER update_ping_statistics + // Fix this method, once it has a semantic dependency with the + // update_ping_statistics method, because it depends on the PingeAnalyzer + // statistics to update the exceeded_ping_failed_limit + update_ping_interval(); +} + +void PingScheduler::update_ping_interval() +{ + // must to ping more often? + if ( HostAnalyzer.exceeded_ping_failed_limit() ) + { + PingIntervalInSec.speed_up(); + + cout << "- Speeding up ping interval to: " << PingIntervalInSec + << "s" << endl; // TODO output log + } + else + { + PingIntervalInSec.back_to_original(); + + cout << "- Stick to the original ping interval: " << PingIntervalInSec + << "s" << endl; // TODO output log + } +} + +void PingScheduler::update_ping_elapsed_time() +{ + ptime now = microsec_clock::universal_time(); + cout << "- Time elapsed since last ping: " + << (now - TimeSentLastPing).total_seconds() << "s" + << endl; // TODO output log + + TimeSentLastPing = microsec_clock::universal_time(); +} diff --git a/src/host/pingscheduler.h b/src/host/pingscheduler.h new file mode 100644 index 0000000..776a3c9 --- /dev/null +++ b/src/host/pingscheduler.h @@ -0,0 +1,65 @@ +#ifndef PINGSCHEDULER_H +#define PINGSCHEDULER_H + +#include + +#include +#include + +#include "dns/dnsresolver.h" +#include "link/linkstatusanalyzer.h" +#include "host/hoststatusanalyzer.h" +#include "host/pinginterval.h" + +//----------------------------------------------------------------------------- +// PingScheduler +//----------------------------------------------------------------------------- + +/** + * @brief This class is responsible to control whether to ping a host. It + * schedules periodic pings to a host. + * Scope: one object per host. + */ +class PingScheduler +{ +public: + PingScheduler( + boost::asio::io_service &io_serv, + const std::string &ping_interface, + const std::string &ping_address, + const long ping_interval_in_sec, + const int ping_fail_percentage_limit, + boost::shared_ptr link_analyzer + ); + virtual ~PingScheduler(); + + bool start_pinging(); + +private: + bool resolve_ping_address(); + void setup_ping(); + bool ping( const std::string &destination_ip ) const; + void schedule_next_ping(); + void handle_next_ping(); + void update_ping_statistics( const bool ping_success ); + void update_ping_interval(); + void update_ping_elapsed_time(); + +private: + boost::asio::io_service &IoService; + std::string LocalNetworkInterfaceName; + boost::asio::deadline_timer NextPingTimer; + boost::posix_time::ptime TimeSentLastPing; + PingInterval PingIntervalInSec; + DnsResolver IpList; + HostStatusAnalyzer HostAnalyzer; + +}; + +//----------------------------------------------------------------------------- +// PingSchedulerItem +//----------------------------------------------------------------------------- + +typedef boost::shared_ptr PingSchedulerItem; + +#endif /* PINGSCHEDULER_H */ diff --git a/src/link/linkstatusanalyzer.cpp b/src/link/linkstatusanalyzer.cpp new file mode 100644 index 0000000..0dcb3a7 --- /dev/null +++ b/src/link/linkstatusanalyzer.cpp @@ -0,0 +1,175 @@ +#include "link/linkstatusanalyzer.h" + +#include + +#include + +using namespace std; +using namespace boost::posix_time; + +//----------------------------------------------------------------------------- +// LinkStatusAnalyzer +//----------------------------------------------------------------------------- + +LinkStatusAnalyzer::LinkStatusAnalyzer( + const int hosts_down_limit, + const int link_up_interval_in_min, + const string &status_notifier_cmd +) : + HostsDownLimit( hosts_down_limit ), + HostsDownList(), + LinkUpIntervalInMin( link_up_interval_in_min ), + CurrentLinkStatus( LinkStatus_Down ), + CurrentNotificationStatus( NotificationStatus_NotReported ), + TimeLinkStatusChanged( microsec_clock::universal_time() ), + StatusNotifierCmd( status_notifier_cmd ) +{ + BOOST_ASSERT( 0 <= hosts_down_limit ); + BOOST_ASSERT( 0 <= link_up_interval_in_min ); + BOOST_ASSERT( !status_notifier_cmd.empty() ); +} + +LinkStatusAnalyzer::~LinkStatusAnalyzer() +{ +} + +void LinkStatusAnalyzer::notify_host_up( const string &host_address ) +{ + BOOST_ASSERT( !host_address.empty() ); + + cout << "- Host up: " << host_address << endl; // TODO + + add_host_up( host_address ); + + if ( !exceeded_host_down_limit() ) + { + notify_link_up(); + } + + // removed from the list? + BOOST_ASSERT( HostsDownList.count( host_address ) == 0 ); +} + +void LinkStatusAnalyzer::notify_host_down( const string &host_address ) +{ + BOOST_ASSERT( !host_address.empty() ); + + cout << "- Host down: " << host_address << endl; // TODO + + add_host_down( host_address ); + + if ( exceeded_host_down_limit() ) + { + notify_link_down(); + } + + // inserted in the list? + BOOST_ASSERT( HostsDownList.count( host_address ) == 1 ); +} + +void LinkStatusAnalyzer::add_host_up( const string &host_address ) +{ + if ( HostsDownList.count( host_address ) > 0 ) + { + size_t erased_host_count = HostsDownList.erase( host_address ); + + BOOST_ASSERT( erased_host_count == 1 ); + } +} + +void LinkStatusAnalyzer::add_host_down( const string &host_address ) +{ + (void) HostsDownList.insert( host_address ); +} + +bool LinkStatusAnalyzer::exceeded_host_down_limit() const +{ + int host_down_count = static_cast ( HostsDownList.size() ); + + return ( host_down_count > HostsDownLimit ); +} + +void LinkStatusAnalyzer::notify_link_up() +{ + set_link_status( LinkStatus_Up ); + + // report the link status only if it is up longer than a configured amount + // of time and if we haven't reported the new status yet + if ( is_link_up_enough_time() && can_report_link_status() ) + { + BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Up ); + BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); + + bool replaced = StatusNotifierCmd.set_token_value( + StatusNotifierCommand::StatusToken, + "up" + ); + + bool executed = StatusNotifierCmd.execute(); + + if ( replaced && executed ) + { + CurrentNotificationStatus = NotificationStatus_Reported; + } + } +} + +void LinkStatusAnalyzer::notify_link_down() +{ + set_link_status( LinkStatus_Down ); + + if ( can_report_link_status() ) + { + BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Down ); + BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); + + bool replaced = StatusNotifierCmd.set_token_value( + StatusNotifierCommand::StatusToken, + "down" + ); + + bool executed = StatusNotifierCmd.execute(); + + if ( replaced && executed ) + { + CurrentNotificationStatus = NotificationStatus_Reported; + } + } +} + +bool LinkStatusAnalyzer::is_link_up_enough_time() const +{ + if ( CurrentLinkStatus == LinkStatus_Up ) + { + ptime now = microsec_clock::universal_time(); + long amount_time_link_is_up = (now - TimeLinkStatusChanged).total_seconds(); + long link_up_interval_in_sec = LinkUpIntervalInMin * 60; + + if ( amount_time_link_is_up >= link_up_interval_in_sec ) + { + return true; + } + } + + return false; +} + +bool LinkStatusAnalyzer::can_report_link_status() const +{ + return ( CurrentNotificationStatus == NotificationStatus_NotReported ); +} + +void LinkStatusAnalyzer::set_link_status( + const LinkStatusAnalyzer::LinkStatus new_link_status +) +{ + // only reset the control flags if the link status has changed + if ( new_link_status != CurrentLinkStatus ) + { + CurrentLinkStatus = new_link_status; + TimeLinkStatusChanged = microsec_clock::universal_time(); + + // have to report the link status change + CurrentNotificationStatus = NotificationStatus_NotReported; + } +} diff --git a/src/link/linkstatusanalyzer.h b/src/link/linkstatusanalyzer.h new file mode 100644 index 0000000..a80f774 --- /dev/null +++ b/src/link/linkstatusanalyzer.h @@ -0,0 +1,81 @@ +#ifndef LINKSTATUSANALYZER_H +#define LINKSTATUSANALYZER_H + +#include +#include + +#include + +#include "link/statusnotifiercommand.h" + +//----------------------------------------------------------------------------- +// LinkStatusAnalyzer +//----------------------------------------------------------------------------- + +/** + * @brief This class analyzes and notifies the link status, through keeping + * track of the amount of hosts down. + * Scope: one object for many hosts. + */ +class LinkStatusAnalyzer +{ +public: + LinkStatusAnalyzer( + const int hosts_down_limit, + const int link_up_interval_in_min, + const std::string &status_notifier_cmd + ); + virtual ~LinkStatusAnalyzer(); + + void notify_host_up( const std::string &host_address ); + void notify_host_down( const std::string &host_address ); + +private: + enum LinkStatus + { + LinkStatus_Up, + LinkStatus_Down + }; + + enum NotificationStatus + { + NotificationStatus_NotReported, + NotificationStatus_Reported + }; + +private: + void add_host_up( const std::string &host_address ); + void add_host_down( const std::string &host_address ); + + bool exceeded_host_down_limit() const; + + void notify_link_up(); + void notify_link_down(); + + bool is_link_up_enough_time() const; + + bool can_report_link_status() const; + void set_link_status( + const LinkStatusAnalyzer::LinkStatus new_link_status + ); + +private: + /// the maximum amount of hosts which can be down before sound the alarm + const int HostsDownLimit; + /// list of host down (obvious isn't it?) + std::set HostsDownList; + /// interval the link have to be stable in order to consider it is functional + const int LinkUpIntervalInMin; + /// keep track of the actual link status + LinkStatusAnalyzer::LinkStatus CurrentLinkStatus; + /// indicates if was notified the last link status change + LinkStatusAnalyzer::NotificationStatus CurrentNotificationStatus; + /// when was the last time the status changed + boost::posix_time::ptime TimeLinkStatusChanged; + /// + StatusNotifierCommand StatusNotifierCmd; + + +}; + +#endif /* LINKSTATUSANALYZER_H */ diff --git a/src/link/statusnotifiercommand.cpp b/src/link/statusnotifiercommand.cpp new file mode 100644 index 0000000..e1c2bfd --- /dev/null +++ b/src/link/statusnotifiercommand.cpp @@ -0,0 +1,99 @@ +#include "link/statusnotifiercommand.h" + +#include + +#include + +#include + +#include + +using namespace std; + +//----------------------------------------------------------------------------- +// StatusNotifierCommand +//----------------------------------------------------------------------------- + +const string StatusNotifierCommand::StatusToken = "${status}"; + +//----------------------------------------------------------------------------- + +StatusNotifierCommand::StatusNotifierCommand( + const string &status_notifier_cmd +) : + CommandStr( status_notifier_cmd ) +{ +} + +StatusNotifierCommand::~StatusNotifierCommand() +{ +} + +bool StatusNotifierCommand::set_token_value( + const string &token, + const string &value +) +{ + BOOST_ASSERT( !token.empty() ); + BOOST_ASSERT( !value.empty() ); + BOOST_ASSERT( !CommandStr.empty() ); + + const size_t token_begin_pos = CommandStr.find( token ); + if ( token_begin_pos == string::npos ) + { + return false; // token string not found! + } + + const size_t token_size = token.length(); + (void) CommandStr.replace( token_begin_pos, token_size, value ); + + // assert the token is no longer within the command string + BOOST_ASSERT( CommandStr.find( token ) == string::npos ); + + return true; +} + +bool StatusNotifierCommand::execute() const +{ + BOOST_ASSERT( !CommandStr.empty() ); + + string app = get_application_string(); + string args = get_arguments_string(); + string secure_command = app + " " + args; + + cout << "- Command: " << secure_command << endl; // TODO + + int ret = system( secure_command.c_str() ); + if ( ret != 0 ) + return false; + + return true; +} + +string StatusNotifierCommand::get_application_string() const +{ + // retrieve the application name from within the command string + const size_t app_begin_pos = 0; + size_t app_end_pos = CommandStr.find( " " ); + if ( app_end_pos == string::npos ) + { + app_end_pos = CommandStr.find( "\n" ); + if ( app_end_pos == string::npos ) + { + return "invalid-app"; + } + } + + return CommandStr.substr( app_begin_pos, app_end_pos ); +} + +string StatusNotifierCommand::get_arguments_string() const +{ + // retrieve the arguments string from within the command string + const size_t args_begin_pos = CommandStr.find( " " ) + 1; + const size_t args_end_pos = CommandStr.length(); + string args = CommandStr.substr( args_begin_pos, args_end_pos ); + args = escape_shellarg( args ); + + return args; +} diff --git a/src/link/statusnotifiercommand.h b/src/link/statusnotifiercommand.h new file mode 100644 index 0000000..06e0870 --- /dev/null +++ b/src/link/statusnotifiercommand.h @@ -0,0 +1,39 @@ +#ifndef STATUSNOTIFIERCOMMAND_H +#define STATUSNOTIFIERCOMMAND_H + +#include + +//----------------------------------------------------------------------------- +// StatusNotifierCommand +//----------------------------------------------------------------------------- + +/** + * @brief This class provides methods to handle status-notifier-cmd + * configuration. + */ +class StatusNotifierCommand +{ +public: + static const std::string StatusToken; + +public: + explicit StatusNotifierCommand( const std::string &status_notifier_cmd ); + virtual ~StatusNotifierCommand(); + + bool set_token_value( + const std::string &token, + const std::string &value + ); + + bool execute() const; + +private: + std::string get_application_string() const; + std::string get_arguments_string() const; + +private: + std::string CommandStr; + +}; + +#endif /* STATUSNOTIFIERCOMMAND_H */ diff --git a/src/main.cpp b/src/main.cpp index 6833ad2..37b0299 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,8 +7,8 @@ #include "config/configurationreader.h" #include "config/host.h" -#include "notify/linkstatusanalyzer.h" -#include "ping/pingscheduler.h" +#include "link/linkstatusanalyzer.h" +#include "host/pingscheduler.h" using namespace std; using namespace boost; diff --git a/src/notify/linkstatusanalyzer.cpp b/src/notify/linkstatusanalyzer.cpp deleted file mode 100644 index 561f5d4..0000000 --- a/src/notify/linkstatusanalyzer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "notify/linkstatusanalyzer.h" - -#include - -#include - -using namespace std; -using namespace boost::posix_time; - -//----------------------------------------------------------------------------- -// LinkStatusAnalyzer -//----------------------------------------------------------------------------- - -LinkStatusAnalyzer::LinkStatusAnalyzer( - const int hosts_down_limit, - const int link_up_interval_in_min, - const string &status_notifier_cmd -) : - HostsDownLimit( hosts_down_limit ), - HostsDownList(), - LinkUpIntervalInMin( link_up_interval_in_min ), - CurrentLinkStatus( LinkStatus_Down ), - CurrentNotificationStatus( NotificationStatus_NotReported ), - TimeLinkStatusChanged( microsec_clock::universal_time() ), - StatusNotifierCmd( status_notifier_cmd ) -{ - BOOST_ASSERT( 0 <= hosts_down_limit ); - BOOST_ASSERT( 0 <= link_up_interval_in_min ); - BOOST_ASSERT( !status_notifier_cmd.empty() ); -} - -LinkStatusAnalyzer::~LinkStatusAnalyzer() -{ -} - -void LinkStatusAnalyzer::notify_host_up( const string &host_address ) -{ - BOOST_ASSERT( !host_address.empty() ); - - cout << "- Host up: " << host_address << endl; // TODO - - add_host_up( host_address ); - - if ( !exceeded_host_down_limit() ) - { - notify_link_up(); - } - - // removed from the list? - BOOST_ASSERT( HostsDownList.count( host_address ) == 0 ); -} - -void LinkStatusAnalyzer::notify_host_down( const string &host_address ) -{ - BOOST_ASSERT( !host_address.empty() ); - - cout << "- Host down: " << host_address << endl; // TODO - - add_host_down( host_address ); - - if ( exceeded_host_down_limit() ) - { - notify_link_down(); - } - - // inserted in the list? - BOOST_ASSERT( HostsDownList.count( host_address ) == 1 ); -} - -void LinkStatusAnalyzer::add_host_up( const string &host_address ) -{ - if ( HostsDownList.count( host_address ) > 0 ) - { - size_t erased_host_count = HostsDownList.erase( host_address ); - - BOOST_ASSERT( erased_host_count == 1 ); - } -} - -void LinkStatusAnalyzer::add_host_down( const string &host_address ) -{ - (void) HostsDownList.insert( host_address ); -} - -bool LinkStatusAnalyzer::exceeded_host_down_limit() const -{ - int host_down_count = static_cast ( HostsDownList.size() ); - - return ( host_down_count > HostsDownLimit ); -} - -void LinkStatusAnalyzer::notify_link_up() -{ - set_link_status( LinkStatus_Up ); - - // report the link status only if it is up longer than a configured amount - // of time and if we haven't reported the new status yet - if ( is_link_up_enough_time() && can_report_link_status() ) - { - BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Up ); - BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); - - bool replaced = StatusNotifierCmd.set_token_value( - StatusNotifierCommand::StatusToken, - "up" - ); - - bool executed = StatusNotifierCmd.execute(); - - if ( replaced && executed ) - { - CurrentNotificationStatus = NotificationStatus_Reported; - } - } -} - -void LinkStatusAnalyzer::notify_link_down() -{ - set_link_status( LinkStatus_Down ); - - if ( can_report_link_status() ) - { - BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Down ); - BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported ); - - bool replaced = StatusNotifierCmd.set_token_value( - StatusNotifierCommand::StatusToken, - "down" - ); - - bool executed = StatusNotifierCmd.execute(); - - if ( replaced && executed ) - { - CurrentNotificationStatus = NotificationStatus_Reported; - } - } -} - -bool LinkStatusAnalyzer::is_link_up_enough_time() const -{ - if ( CurrentLinkStatus == LinkStatus_Up ) - { - ptime now = microsec_clock::universal_time(); - long amount_time_link_is_up = (now - TimeLinkStatusChanged).total_seconds(); - long link_up_interval_in_sec = LinkUpIntervalInMin * 60; - - if ( amount_time_link_is_up >= link_up_interval_in_sec ) - { - return true; - } - } - - return false; -} - -bool LinkStatusAnalyzer::can_report_link_status() const -{ - return ( CurrentNotificationStatus == NotificationStatus_NotReported ); -} - -void LinkStatusAnalyzer::set_link_status( - const LinkStatusAnalyzer::LinkStatus new_link_status -) -{ - // only reset the control flags if the link status has changed - if ( new_link_status != CurrentLinkStatus ) - { - CurrentLinkStatus = new_link_status; - TimeLinkStatusChanged = microsec_clock::universal_time(); - - // have to report the link status change - CurrentNotificationStatus = NotificationStatus_NotReported; - } -} diff --git a/src/notify/linkstatusanalyzer.h b/src/notify/linkstatusanalyzer.h deleted file mode 100644 index 5dedceb..0000000 --- a/src/notify/linkstatusanalyzer.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef LINKSTATUSANALYZER_H -#define LINKSTATUSANALYZER_H - -#include -#include - -#include - -#include "notify/statusnotifiercommand.h" - -//----------------------------------------------------------------------------- -// LinkStatusAnalyzer -//----------------------------------------------------------------------------- - -/** - * @brief This class analyzes and notifies the link status, through keeping - * track of the amount of hosts down. - * Scope: one object for many hosts. - */ -class LinkStatusAnalyzer -{ -public: - LinkStatusAnalyzer( - const int hosts_down_limit, - const int link_up_interval_in_min, - const std::string &status_notifier_cmd - ); - virtual ~LinkStatusAnalyzer(); - - void notify_host_up( const std::string &host_address ); - void notify_host_down( const std::string &host_address ); - -private: - enum LinkStatus - { - LinkStatus_Up, - LinkStatus_Down - }; - - enum NotificationStatus - { - NotificationStatus_NotReported, - NotificationStatus_Reported - }; - -private: - void add_host_up( const std::string &host_address ); - void add_host_down( const std::string &host_address ); - - bool exceeded_host_down_limit() const; - - void notify_link_up(); - void notify_link_down(); - - bool is_link_up_enough_time() const; - - bool can_report_link_status() const; - void set_link_status( - const LinkStatusAnalyzer::LinkStatus new_link_status - ); - -private: - /// the maximum amount of hosts which can be down before sound the alarm - const int HostsDownLimit; - /// list of host down (obvious isn't it?) - std::set HostsDownList; - /// interval the link have to be stable in order to consider it is functional - const int LinkUpIntervalInMin; - /// keep track of the actual link status - LinkStatusAnalyzer::LinkStatus CurrentLinkStatus; - /// indicates if was notified the last link status change - LinkStatusAnalyzer::NotificationStatus CurrentNotificationStatus; - /// when was the last time the status changed - boost::posix_time::ptime TimeLinkStatusChanged; - /// - StatusNotifierCommand StatusNotifierCmd; - - -}; - -#endif /* LINKSTATUSANALYZER_H */ diff --git a/src/notify/statusnotifiercommand.cpp b/src/notify/statusnotifiercommand.cpp deleted file mode 100644 index dfd5898..0000000 --- a/src/notify/statusnotifiercommand.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "notify/statusnotifiercommand.h" - -#include - -#include - -#include - -#include - -using namespace std; - -//----------------------------------------------------------------------------- -// StatusNotifierCommand -//----------------------------------------------------------------------------- - -const string StatusNotifierCommand::StatusToken = "${status}"; - -//----------------------------------------------------------------------------- - -StatusNotifierCommand::StatusNotifierCommand( - const string &status_notifier_cmd -) : - CommandStr( status_notifier_cmd ) -{ -} - -StatusNotifierCommand::~StatusNotifierCommand() -{ -} - -bool StatusNotifierCommand::set_token_value( - const string &token, - const string &value -) -{ - BOOST_ASSERT( !token.empty() ); - BOOST_ASSERT( !value.empty() ); - BOOST_ASSERT( !CommandStr.empty() ); - - const size_t token_begin_pos = CommandStr.find( token ); - if ( token_begin_pos == string::npos ) - { - return false; // token string not found! - } - - const size_t token_size = token.length(); - (void) CommandStr.replace( token_begin_pos, token_size, value ); - - // assert the token is no longer within the command string - BOOST_ASSERT( CommandStr.find( token ) == string::npos ); - - return true; -} - -bool StatusNotifierCommand::execute() const -{ - BOOST_ASSERT( !CommandStr.empty() ); - - string app = get_application_string(); - string args = get_arguments_string(); - string secure_command = app + " " + args; - - cout << "- Command: " << secure_command << endl; // TODO - - int ret = system( secure_command.c_str() ); - if ( ret != 0 ) - return false; - - return true; -} - -string StatusNotifierCommand::get_application_string() const -{ - // retrieve the application name from within the command string - const size_t app_begin_pos = 0; - size_t app_end_pos = CommandStr.find( " " ); - if ( app_end_pos == string::npos ) - { - app_end_pos = CommandStr.find( "\n" ); - if ( app_end_pos == string::npos ) - { - return "invalid-app"; - } - } - - return CommandStr.substr( app_begin_pos, app_end_pos ); -} - -string StatusNotifierCommand::get_arguments_string() const -{ - // retrieve the arguments string from within the command string - const size_t args_begin_pos = CommandStr.find( " " ) + 1; - const size_t args_end_pos = CommandStr.length(); - string args = CommandStr.substr( args_begin_pos, args_end_pos ); - args = escape_shellarg( args ); - - return args; -} diff --git a/src/notify/statusnotifiercommand.h b/src/notify/statusnotifiercommand.h deleted file mode 100644 index 06e0870..0000000 --- a/src/notify/statusnotifiercommand.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef STATUSNOTIFIERCOMMAND_H -#define STATUSNOTIFIERCOMMAND_H - -#include - -//----------------------------------------------------------------------------- -// StatusNotifierCommand -//----------------------------------------------------------------------------- - -/** - * @brief This class provides methods to handle status-notifier-cmd - * configuration. - */ -class StatusNotifierCommand -{ -public: - static const std::string StatusToken; - -public: - explicit StatusNotifierCommand( const std::string &status_notifier_cmd ); - virtual ~StatusNotifierCommand(); - - bool set_token_value( - const std::string &token, - const std::string &value - ); - - bool execute() const; - -private: - std::string get_application_string() const; - std::string get_arguments_string() const; - -private: - std::string CommandStr; - -}; - -#endif /* STATUSNOTIFIERCOMMAND_H */ diff --git a/src/ping/boostpinger.cpp b/src/ping/boostpinger.cpp deleted file mode 100644 index e013019..0000000 --- a/src/ping/boostpinger.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include "ping/boostpinger.h" - -#include -#include -#include - -#include - -#include "icmp/icmpchecksumcalculator.h" -#include "icmp/icmpdata.h" -#include "icmp/icmpheader.h" -#include "icmp/icmppacket.h" -#include "icmp/icmptype.h" -#include "icmp/ipv4header.h" - -using namespace std; -using namespace boost::asio; -using namespace boost::asio::ip; -using namespace boost::posix_time; - -//----------------------------------------------------------------------------- -// BoostPinger -//----------------------------------------------------------------------------- - -BoostPinger::BoostPinger( - io_service &io_serv, - string source_network_interface, - const int echo_reply_timeout_in_sec -) : - IoService( io_serv ), - DestinationEndpoint(), - Socket( io_serv, icmp::v4() ), - IcmpPacketReceiveTimer( io_serv ), - SequenceNumber( 0 ), - TimeSent( microsec_clock::universal_time() ), - ReplyBuffer(), - RepliesCount( 0 ), - EchoReplyTimeoutInSec( echo_reply_timeout_in_sec ), - PingerStatus( PingStatus_NotSent ) -{ - BOOST_ASSERT( !source_network_interface.empty() ); - - if ( !select_source_network_interface( source_network_interface ) ) - { - cerr << "Error: could not bind the socket with the local interface." - << ::strerror( errno ) << endl; - } - -} - -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. - */ -bool BoostPinger::ping( const string &destination_ip ) -{ - BOOST_ASSERT( !destination_ip.empty() ); - - uint16_t port = 0; - address destination_address = ip::address::from_string( destination_ip ); - icmp::endpoint destination_endpoint( destination_address, port ); - DestinationEndpoint = destination_endpoint; - - start_pinger(); - - bool ping_success = (PingerStatus == PingStatus_SuccessReply); - return ping_success; -} - -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(); - } -} - -IcmpPacket BoostPinger::create_echo_request( - const uint16_t sequence_number -) const -{ - const IcmpData icmp_data( "ping-message" ); - - IcmpType type = IcmpType_EchoRequest; - uint8_t code = 0; - uint16_t identifier = get_identifier(); - IcmpChecksumCalculator calculator( icmp_data.begin(), icmp_data.end() ); - uint16_t checksum = calculator.compute( - type, code, identifier, sequence_number - ); - IcmpHeader icmp_header( - type, code, checksum, identifier, sequence_number - ); - - return IcmpPacket( icmp_header, icmp_data ); -} - -void BoostPinger::send_echo_request( const IcmpPacket &icmp_packet ) -{ - boost::asio::streambuf request_buffer; - ostream os( &request_buffer ); - os << icmp_packet; - - TimeSent = microsec_clock::universal_time(); - - string dest_address_string = DestinationEndpoint.address().to_string(); - BOOST_ASSERT( !dest_address_string.empty() ); - - // Send the request - try - { - const_buffers_1 data = request_buffer.data(); - size_t bytes_sent = Socket.send_to( data, DestinationEndpoint ); - if ( bytes_sent != buffer_size( data ) ) - { - cerr << "Error: fail sending ping data." << endl; - } - } - catch ( const exception &ex ) - { - cerr << "Error: fail sending ping data. " << ex.what() << endl; - } - - schedule_timeout_echo_reply(); -} - -void BoostPinger::schedule_timeout_echo_reply() -{ - // Wait up to N seconds for a reply. - RepliesCount = 0; - (void) IcmpPacketReceiveTimer.expires_at( - TimeSent + seconds( EchoReplyTimeoutInSec ) - ); - IcmpPacketReceiveTimer.async_wait( - boost::bind( &BoostPinger::handle_timeout_echo_reply, this ) - ); -} - -void BoostPinger::handle_timeout_echo_reply() -{ - if ( RepliesCount == 0 ) - { - print_request_timeout(); - - set_ping_status( PingStatus_FailureTimeout ); - } - - schedule_next_echo_request(); -} - -void BoostPinger::schedule_next_echo_request() -{ - // Requests must be sent no less than one second apart. - const int echo_request_interval_in_sec = 1; - (void) IcmpPacketReceiveTimer.expires_at( - TimeSent + seconds( echo_request_interval_in_sec ) - ); - IcmpPacketReceiveTimer.async_wait( - boost::bind( &BoostPinger::start_send, this ) - ); -} - -void BoostPinger::start_receive() -{ - // Discard any data already in the buffer. - ReplyBuffer.consume( ReplyBuffer.size() ); - - // Wait for a reply. We prepare the buffer to receive up to 64KB. - Socket.async_receive( - ReplyBuffer.prepare( 65536 ), - boost::bind( &BoostPinger::handle_receive_icmp_packet, this, _2 ) - ); -} - -void BoostPinger::handle_receive_icmp_packet( const size_t &bytes_transferred ) -{ - // 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 ) - return; - - // Decode the reply packet. - IcmpPacket icmp_packet; - is >> icmp_packet; - - // We can receive all ICMP packets received by the host, so we need to - // filter out only the echo replies that match the our identifier and - // expected sequence number. - if ( icmp_packet.match( - IcmpType_EchoReply, get_identifier(), SequenceNumber - ) ) - { - // If this is the first reply, interrupt the echo reply timeout. - if ( RepliesCount == 0 ) - { - (void) IcmpPacketReceiveTimer.cancel(); - } - - ++RepliesCount; - - print_echo_reply( icmp_packet, bytes_transferred ); - - set_ping_status( PingStatus_SuccessReply ); - } - else if ( icmp_packet.match( - IcmpType_DestinationUnreachable, get_identifier(), SequenceNumber - ) ) - { - // If this is the first reply, interrupt the echo reply timeout. - if ( RepliesCount == 0 ) - { - (void) IcmpPacketReceiveTimer.cancel(); - } - - ++RepliesCount; - - print_destination_unreachable( icmp_packet ); - - set_ping_status( PingStatus_FailureDestinationUnreachable ); - } - - start_receive(); -} - -void BoostPinger::print_request_timeout() const -{ - cout << "Request timed out" << endl; -} - -void BoostPinger::print_echo_reply( - const IcmpPacket &icmp_packet, - const size_t &bytes_transferred -) const -{ - BOOST_ASSERT( icmp_packet.get_icmp_header().get_type() == IcmpType_EchoReply ); - - Ipv4Header ipv4_hdr = icmp_packet.get_ip_header(); - IcmpHeader icmp_hdr = icmp_packet.get_icmp_header(); - - size_t bytes_received = bytes_transferred - ipv4_hdr.get_header_length(); - string remote_address = ipv4_hdr.get_source_address().to_string(); - uint16_t sequence_number = icmp_hdr.get_sequence_number(); - int ttl = ipv4_hdr.get_time_to_live(); - ptime now = microsec_clock::universal_time(); - int elapsed_time = (now - TimeSent).total_milliseconds(); - - cout << bytes_received << " bytes " - << "from " << remote_address - << ": icmp_seq=" << sequence_number - << " ttl=" << ttl - << " time=" << elapsed_time << " ms" << endl; -} - -void BoostPinger::print_destination_unreachable( - const IcmpPacket &icmp_packet -) const -{ - BOOST_ASSERT( icmp_packet.get_icmp_header().get_type() == IcmpType_DestinationUnreachable ); - - Ipv4Header ipv4_hdr = icmp_packet.get_ip_header(); - IcmpHeader icmp_hdr = icmp_packet.get_icmp_header(); - - string local_address = ipv4_hdr.get_destination_address().to_string(); - uint16_t sequence_number = icmp_hdr.get_sequence_number(); - - cout << "From " << local_address - << " icmp_seq=" << sequence_number - << " Destination Net Unreachable" << endl; -} - -void BoostPinger::set_ping_status( BoostPinger::PingStatus ping_status ) -{ - PingerStatus = ping_status; -} - -uint16_t BoostPinger::get_identifier() const -{ - return static_cast ( ::getpid() ); -} - -/** - * Avoid the socket to drop to another network interface if the destination - * is unreachable through the binded interface. Packets are sent only from - * this interface. - * - * @param source_network_interface The network interface to bind the pinger. - * - * @return false if the bind failed. - */ -bool BoostPinger::select_source_network_interface( - const string &source_network_interface -) -{ - BOOST_ASSERT( !source_network_interface.empty() ); - - int ret = ::setsockopt( - Socket.native(), - SOL_SOCKET, - SO_BINDTODEVICE, - source_network_interface.c_str(), - source_network_interface.size() - ); - if ( ret == -1 ) - { - return false; - } - - return true; -} diff --git a/src/ping/boostpinger.h b/src/ping/boostpinger.h deleted file mode 100644 index 1ed7233..0000000 --- a/src/ping/boostpinger.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef BOOSTPINGER_H -#define BOOSTPINGER_H - -#include - -class IcmpPacket; - -//----------------------------------------------------------------------------- -// BoostPinger -//----------------------------------------------------------------------------- - -/** - * @brief This class performs ping to host using Boost Asio. - * Scope: one object per host. - */ -class BoostPinger -{ -public: - BoostPinger( - boost::asio::io_service &io_serv, - std::string source_network_interface, - const int echo_reply_timeout_in_sec - ); - virtual ~BoostPinger(); - - bool ping( const std::string &destination_ip ); - -private: - enum PingStatus - { - PingStatus_NotSent, - PingStatus_SuccessReply, - PingStatus_FailureTimeout, - PingStatus_FailureDestinationUnreachable - }; - -private: - void start_pinger(); - void stop_pinger(); - - void start_send(); - IcmpPacket create_echo_request( const uint16_t sequence_number ) const; - void send_echo_request( const IcmpPacket &icmp_packet ); - void schedule_timeout_echo_reply(); - void handle_timeout_echo_reply(); - void schedule_next_echo_request(); - - void start_receive(); - void handle_receive_icmp_packet( const std::size_t &bytes_transferred ); - - void print_request_timeout() const; - void print_echo_reply( - const IcmpPacket &icmp_packet, - const std::size_t &bytes_transferred - ) const; - void print_destination_unreachable( - const IcmpPacket &icmp_packet - ) const; - - void set_ping_status( BoostPinger::PingStatus ping_status ); - - uint16_t get_identifier() const; - - bool select_source_network_interface( - const std::string &source_network_interface - ); - -private: - boost::asio::io_service &IoService; - boost::asio::ip::icmp::endpoint DestinationEndpoint; - boost::asio::ip::icmp::socket Socket; - boost::asio::deadline_timer IcmpPacketReceiveTimer; - uint16_t SequenceNumber; - boost::posix_time::ptime TimeSent; - boost::asio::streambuf ReplyBuffer; - int RepliesCount; - int EchoReplyTimeoutInSec; - BoostPinger::PingStatus PingerStatus; - -}; - -#endif /* BOOSTPINGER_H */ diff --git a/src/ping/hoststatusanalyzer.cpp b/src/ping/hoststatusanalyzer.cpp deleted file mode 100644 index ca9f683..0000000 --- a/src/ping/hoststatusanalyzer.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "ping/hoststatusanalyzer.h" - -#include - -#include - -using namespace std; -using namespace boost; - -//----------------------------------------------------------------------------- -// HostStatusAnalyzer -//----------------------------------------------------------------------------- - -/** - * @param host_address the address of the host it has to analyze. - * @param ping_fail_percentage_limit the percentage threshold of pings that can - * fail. - * @param link_analyzer the object used to notify the status of the host. - */ -HostStatusAnalyzer::HostStatusAnalyzer( - const string &host_address, - const int ping_fail_percentage_limit, - const shared_ptr link_analyzer -) : - HostAddress( host_address ), - LinkAnalyzer( link_analyzer ), - PingFailPercentageLimit( ping_fail_percentage_limit ), - ResolvedIpCount( 0 ), - PingsPerformedCount( 0 ), - PingsFailedCount( 0 ), - ExceededPingFailedLimit( false ) -{ - BOOST_ASSERT( !HostAddress.empty() ); - BOOST_ASSERT( ( 0 <= PingFailPercentageLimit ) && ( PingFailPercentageLimit <= 100 ) ); -} - -HostStatusAnalyzer::~HostStatusAnalyzer() -{ -} - -/** - * @param resolved_ip_count the number of IPs resolved for the host. - */ -void HostStatusAnalyzer::set_resolved_ip_count( const int resolved_ip_count ) -{ - BOOST_ASSERT( 1 <= resolved_ip_count ); - - ResolvedIpCount = resolved_ip_count; -} - -/** - * @return true if the amount of failed pings given to the host exceeded the - * limit. - */ -bool HostStatusAnalyzer::exceeded_ping_failed_limit() const -{ - return ExceededPingFailedLimit; -} - -/** - * Adds a ping status (success or failure). - * @param ping_success - */ -void HostStatusAnalyzer::update_ping_statistics( bool ping_success ) -{ - BOOST_ASSERT( 1 <= ResolvedIpCount ); - BOOST_ASSERT( 0 <= PingsPerformedCount ); - BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); - - increase_ping_performed_count(); - - if ( !ping_success ) - { - increase_ping_failed_count(); - } - - // after we tried all IPs resolved for this host, we can analyze how many - // failed - if ( tried_all_resolved_ip() ) - { - analyze_ping_statistics(); - - reset_ping_counters(); - } - - BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount ); -} - -bool HostStatusAnalyzer::tried_all_resolved_ip() const -{ - BOOST_ASSERT( ( 0 <= PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) ); - - return ( PingsPerformedCount == ResolvedIpCount ); -} - -void HostStatusAnalyzer::analyze_ping_statistics() -{ - BOOST_ASSERT( !HostAddress.empty() ); - BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount ); - - // notify if the amount of pings that failed exceed the limit - if ( exceeded_ping_failed_limit() ) - { - LinkAnalyzer->notify_host_down( HostAddress ); - } - else - { - LinkAnalyzer->notify_host_up( HostAddress ); - } - -} - -void HostStatusAnalyzer::reset_ping_counters() -{ - PingsPerformedCount = 0; - PingsFailedCount = 0; -} - -void HostStatusAnalyzer::increase_ping_performed_count() -{ - ++PingsPerformedCount; - - BOOST_ASSERT( ( 0 <= PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) ); -} - -void HostStatusAnalyzer::increase_ping_failed_count() -{ - ++PingsFailedCount; - - analyze_ping_failed_count(); - - BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); -} - -void HostStatusAnalyzer::analyze_ping_failed_count() -{ - BOOST_ASSERT( ( 0 <= PingFailPercentageLimit ) && ( PingFailPercentageLimit <= 100 ) ); - BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) ); - - int ping_fail_absolute_limit = PingFailPercentageLimit / 100; // TODO possible precision loss, check with care - - // keep a boolean variable because the PingsFailedCount can be reseted - ExceededPingFailedLimit = ( PingsFailedCount > ping_fail_absolute_limit ); -} diff --git a/src/ping/hoststatusanalyzer.h b/src/ping/hoststatusanalyzer.h deleted file mode 100644 index b215319..0000000 --- a/src/ping/hoststatusanalyzer.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef HOSTSTATUSANALYZER_H -#define HOSTSTATUSANALYZER_H - -#include - -#include - -#include "notify/linkstatusanalyzer.h" - -//----------------------------------------------------------------------------- -// HostStatusAnalyzer -//----------------------------------------------------------------------------- - -/** - * @brief This class analyze the host status (up or down) based on the pings - * responses (success or failure). And notifies its status. - * Scope: one object per host. - */ -class HostStatusAnalyzer -{ -public: - HostStatusAnalyzer( - const std::string &host_address, - const int ping_fail_percentage_limit, - const boost::shared_ptr link_analyzer - ); - virtual ~HostStatusAnalyzer(); - - void set_resolved_ip_count( const int resolved_ip_count ); - bool exceeded_ping_failed_limit() const; - void update_ping_statistics( bool ping_success ); - -private: - bool tried_all_resolved_ip() const; - void analyze_ping_statistics(); - void reset_ping_counters(); - void increase_ping_performed_count(); - void increase_ping_failed_count(); - void analyze_ping_failed_count(); - -private: - std::string HostAddress; - const boost::shared_ptr LinkAnalyzer; - int PingFailPercentageLimit; - int ResolvedIpCount; - int PingsPerformedCount; - int PingsFailedCount; - bool ExceededPingFailedLimit; - -}; - -#endif /* HOSTSTATUSANALYZER_H */ diff --git a/src/ping/pinginterval.h b/src/ping/pinginterval.h deleted file mode 100644 index 0676921..0000000 --- a/src/ping/pinginterval.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef PINGINTERVAL_H -#define PINGINTERVAL_H - -//----------------------------------------------------------------------------- -// PingInterval -//----------------------------------------------------------------------------- - -/** - * @brief Class designed to behave like a scalar type (i.e. int, long), but - * with helper methods to encapsulate interval computation. - * Scope: one object per host. - */ -template -class PingInterval -{ -public: - PingInterval( T interval ); - - operator T(); - - void back_to_original(); - void speed_up(); - -private: - bool can_speed_up() const; - -private: - const T OriginalInterval; - T Interval; - -}; - - -template - PingInterval::PingInterval( - T interval - ) : - OriginalInterval( interval ), - Interval( interval ) - { - } - -template - PingInterval::operator T() - { - return Interval; - } - -template - void PingInterval::back_to_original() - { - Interval = OriginalInterval; - } - -template - void PingInterval::speed_up() - { - if ( can_speed_up() ) - Interval = Interval / 2; - } - -template - bool PingInterval::can_speed_up() const - { - T half_original = OriginalInterval / 2; - - return (Interval > half_original); - } - - -#endif /* PINGINTERVAL_H */ diff --git a/src/ping/pingscheduler.cpp b/src/ping/pingscheduler.cpp deleted file mode 100644 index ce3bed1..0000000 --- a/src/ping/pingscheduler.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "ping/pingscheduler.h" - -#include - -#include - -#include "dns/dnsresolver.h" -#include "notify/linkstatusanalyzer.h" -#include "ping/boostpinger.h" - -using namespace std; -using namespace boost; -using namespace boost::asio; -using namespace boost::posix_time; - -//----------------------------------------------------------------------------- -// PingScheduler -//----------------------------------------------------------------------------- - -PingScheduler::PingScheduler( - boost::asio::io_service &io_serv, - const string &ping_interface, - const string &ping_address, - const long ping_interval_in_sec, - const int ping_fail_percentage_limit, - shared_ptr link_analyzer - -) : - IoService( io_serv ), - LocalNetworkInterfaceName( ping_interface ), - NextPingTimer( io_serv ), - TimeSentLastPing( microsec_clock::universal_time() ), - PingIntervalInSec( ping_interval_in_sec ), - IpList( ping_address ), - HostAnalyzer( ping_address, ping_fail_percentage_limit, link_analyzer ) -{ -} - -PingScheduler::~PingScheduler() -{ -} - -bool PingScheduler::start_pinging() -{ - bool address_resolved = resolve_ping_address(); - if ( !address_resolved ) - { - return false; - } - - schedule_next_ping(); - - return true; -} - -bool PingScheduler::resolve_ping_address() -{ - bool address_resolved = IpList.resolve(); - if ( !address_resolved ) - { - return false; - } - - int resolved_ip_count = IpList.get_resolved_ip_count(); - HostAnalyzer.set_resolved_ip_count( resolved_ip_count ); - - return true; -} - -void PingScheduler::setup_ping() -{ - BOOST_ASSERT( 1 <= IpList.get_resolved_ip_count() ); - - string destination_ip = IpList.get_next_ip(); - bool ping_success = ping( destination_ip ); - - update_ping_statistics( ping_success ); - update_ping_elapsed_time(); - - schedule_next_ping(); -} - -bool PingScheduler::ping( const string &destination_ip ) const -{ - BOOST_ASSERT( !destination_ip.empty() ); - - io_service io_serv; - int echo_reply_timeout_in_sec = 5; // TODO configurable: this is the timeout to WAIT FOR the ping before considering a timeout - - BoostPinger pinger( - io_serv, - LocalNetworkInterfaceName, - echo_reply_timeout_in_sec - ); - return pinger.ping( destination_ip ); -} - -void PingScheduler::schedule_next_ping() -{ - BOOST_ASSERT( 0 < PingIntervalInSec ); - - (void) NextPingTimer.expires_from_now( seconds( PingIntervalInSec ) ); - NextPingTimer.async_wait( bind( &PingScheduler::handle_next_ping, this ) ); -} - -void PingScheduler::handle_next_ping() -{ - setup_ping(); -} - -void PingScheduler::update_ping_statistics( const bool ping_success ) -{ - HostAnalyzer.update_ping_statistics( ping_success ); - - // TODO you must call the method bellow AFTER update_ping_statistics - // Fix this method, once it has a semantic dependency with the - // update_ping_statistics method, because it depends on the PingeAnalyzer - // statistics to update the exceeded_ping_failed_limit - update_ping_interval(); -} - -void PingScheduler::update_ping_interval() -{ - // must to ping more often? - if ( HostAnalyzer.exceeded_ping_failed_limit() ) - { - PingIntervalInSec.speed_up(); - - cout << "- Speeding up ping interval to: " << PingIntervalInSec - << "s" << endl; // TODO output log - } - else - { - PingIntervalInSec.back_to_original(); - - cout << "- Stick to the original ping interval: " << PingIntervalInSec - << "s" << endl; // TODO output log - } -} - -void PingScheduler::update_ping_elapsed_time() -{ - ptime now = microsec_clock::universal_time(); - cout << "- Time elapsed since last ping: " - << (now - TimeSentLastPing).total_seconds() << "s" - << endl; // TODO output log - - TimeSentLastPing = microsec_clock::universal_time(); -} diff --git a/src/ping/pingscheduler.h b/src/ping/pingscheduler.h deleted file mode 100644 index 701bb9e..0000000 --- a/src/ping/pingscheduler.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef PINGSCHEDULER_H -#define PINGSCHEDULER_H - -#include - -#include -#include - -#include "dns/dnsresolver.h" -#include "notify/linkstatusanalyzer.h" -#include "ping/hoststatusanalyzer.h" -#include "ping/pinginterval.h" - -//----------------------------------------------------------------------------- -// PingScheduler -//----------------------------------------------------------------------------- - -/** - * @brief This class is responsible to control whether to ping a host. It - * schedules periodic pings to a host. - * Scope: one object per host. - */ -class PingScheduler -{ -public: - PingScheduler( - boost::asio::io_service &io_serv, - const std::string &ping_interface, - const std::string &ping_address, - const long ping_interval_in_sec, - const int ping_fail_percentage_limit, - boost::shared_ptr link_analyzer - ); - virtual ~PingScheduler(); - - bool start_pinging(); - -private: - bool resolve_ping_address(); - void setup_ping(); - bool ping( const std::string &destination_ip ) const; - void schedule_next_ping(); - void handle_next_ping(); - void update_ping_statistics( const bool ping_success ); - void update_ping_interval(); - void update_ping_elapsed_time(); - -private: - boost::asio::io_service &IoService; - std::string LocalNetworkInterfaceName; - boost::asio::deadline_timer NextPingTimer; - boost::posix_time::ptime TimeSentLastPing; - PingInterval PingIntervalInSec; - DnsResolver IpList; - HostStatusAnalyzer HostAnalyzer; - -}; - -//----------------------------------------------------------------------------- -// PingSchedulerItem -//----------------------------------------------------------------------------- - -typedef boost::shared_ptr PingSchedulerItem; - -#endif /* PINGSCHEDULER_H */ -- 1.7.1