moved time duration measurement of ping from scheduler to pingers
[pingcheck] / src / icmp / icmppinger.h
1 // Boost pinger (c) 2011 by Guilherme Maciel Ferreira / Intra2net AG
2 // Based upon work copyright (c) 2003-2010 Christopher M. Kohlhoff (ping.cpp)
3 // Modified 2014 by Christian Herdtweck, Intra2net AG
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef ICMP_PINGER_H
9 #define ICMP_PINGER_H
10
11 #include <stdint.h>
12
13 #include <string>
14 #include <set>
15
16 #include <boost/asio.hpp>
17 #include <boost/function.hpp>
18 #include <boost/shared_ptr.hpp>
19
20 #include "host/pinger.h"
21 #include "host/pingstatus.h"
22 #include "icmp/icmppacket.h"
23
24
25 using boost::asio::ip::icmp;
26
27 class IcmpPinger;
28 typedef boost::shared_ptr<IcmpPinger> IcmpPingerItem;
29
30 class IcmpPacketDistributor;
31 typedef boost::shared_ptr<IcmpPacketDistributor> IcmpPacketDistributorItem;
32
33 typedef boost::shared_ptr<icmp::socket> SocketItem;
34
35 //-----------------------------------------------------------------------------
36 // IcmpPacketDistributor
37 //-----------------------------------------------------------------------------
38
39
40 class IcmpPacketDistributor
41 {
42 public:
43     bool register_pinger( const IcmpPingerItem &new_pinger );
44     bool unregister_pinger( const IcmpPingerItem &old_pinger );
45
46     SocketItem get_socket() const;
47
48     static IcmpPacketDistributorItem get_distributor(
49             const icmp::socket::protocol_type &protocol,
50             const std::string &network_interface,
51             const IoServiceItem io_serv
52     );
53
54     static IcmpPacketDistributorItem get_distributor(
55             const icmp::socket::protocol_type &protocol,
56             const std::string &network_interface
57     );
58
59     static void clean_up_all();
60
61     ~IcmpPacketDistributor();
62
63 private:
64     // hide away constructor, copy constructor and assignment operator
65     IcmpPacketDistributor(
66             const icmp::socket::protocol_type &protocol,
67             const std::string &network_interface,
68             const IoServiceItem io_serv
69     );
70     IcmpPacketDistributor(IcmpPacketDistributor const&);
71     void operator=(IcmpPacketDistributor const&);
72
73     void register_receive_handler();
74     void handle_receive( const boost::system::error_code &error,
75                          const size_t &bytes_transferred );
76     void clean_up();
77
78 private:
79     /// Network layer protocol used to ping, IPv4 or IPv6
80     icmp::socket::protocol_type Protocol;
81
82     /// The socket object
83     SocketItem Socket;
84
85     /// The buffer where the data received will be placed
86     boost::asio::streambuf ReplyBuffer;
87
88     std::set<IcmpPingerItem> PingerList;
89
90     // for each IP protocol (v4/v6) and each network interface (string),
91     //   there can only be one IcmpPacketDistributor instance
92     typedef std::pair<icmp::socket::protocol_type, std::string>
93                                                  DistributorInstanceIdentifier;
94
95     struct InstanceIdentifierComparator
96     {
97         bool operator() ( const DistributorInstanceIdentifier &a,
98                           const DistributorInstanceIdentifier &b ) const ;
99     };
100
101     typedef std::map<DistributorInstanceIdentifier, IcmpPacketDistributorItem,
102                      InstanceIdentifierComparator> map_type;
103     /// Instances, one for each (protocol, interface) - pair
104     static map_type Instances;
105 };
106
107 //-----------------------------------------------------------------------------
108 // IcmpPinger
109 //-----------------------------------------------------------------------------
110
111 /**
112  * @brief This class performs an ICMP ping to host using Boost Asio.
113  * Scope: one object per host.
114  */
115 class IcmpPinger : public Pinger
116 {
117 public:
118     static PingerItem create(
119             const IoServiceItem io_serv,
120             const boost::asio::ip::icmp::socket::protocol_type &protocol,
121             const std::string &source_network_interface,
122             const int echo_reply_timeout_in_sec
123     );
124
125     virtual ~IcmpPinger();
126
127     virtual void ping(
128             const boost::asio::ip::address &destination_ip,
129             const uint16_t destination_port,
130             boost::function<void(PingStatus,long)> ping_done_callback
131     );
132
133     virtual void stop_pinging();
134
135     bool handle_receive_icmp_packet(const IcmpPacketItem icmp_packet,
136                                     const size_t bytes_transferred
137     );
138
139 private:
140     IcmpPinger(
141             const IoServiceItem io_serv,
142             const boost::asio::ip::icmp::socket::protocol_type &protocol,
143             const int echo_reply_timeout_in_sec,
144             const IcmpPacketDistributorItem distributor
145     );
146
147     void set_destination_endpoint(const boost::asio::ip::address &destination);
148
149     bool start_send();
150     bool send_echo_request( const IcmpPacketItem icmp_packet );
151     void schedule_timeout_echo_reply();
152     void handle_timeout(const boost::system::error_code &error);
153
154     void set_ping_status( PingStatus ping_status );
155
156 private:
157     IcmpPacketDistributorItem PacketDistributor;
158
159     /// The destination host
160     boost::asio::ip::icmp::endpoint DestinationEndpoint;
161     /// Network layer protocol used to ping, IPv4 or IPv6
162     boost::asio::ip::icmp::socket::protocol_type Protocol;
163     /// The timer of ICMP packet receive, triggers the timeout to avoid infinite
164     /// wait
165     boost::asio::deadline_timer IcmpPacketReceiveTimer;
166     /// ICMP packet identifier
167     uint16_t Identifier;
168     /// ICMP packet sequence_number
169     uint16_t SequenceNumber;
170     /// The time when the last ICMP packet was sent
171     boost::posix_time::ptime TimeSent;
172     /// Flag to indicate if we got a reply or not
173     bool ReplyReceived;
174     /// The amount of time to wait for the reply
175     int EchoReplyTimeoutInSec;
176     /// The status of the pinger
177     PingStatus PingerStatus;
178     /// Callback to notify when the ping is done (got reply/timeout)
179     boost::function< void(PingStatus,long) > PingDoneCallback;
180     /// prefix to logging output lines
181     std::string LogPrefix;
182 };
183
184 #endif // ICMP_PINGER_H