18#include <boost/bind.hpp>
19#include <boost/pointer_cast.hpp>
26using namespace boost::posix_time;
31constexpr long WARN_CLOCK_SKEW = 30;
34constexpr long TERM_CLOCK_SKEW = 60;
37constexpr long MIN_TIME_SINCE_CLOCK_SKEW_WARN = 60;
46 : io_service_(io_service), config_(config), timer_(), interval_(0),
47 poke_time_(
boost::posix_time::microsec_clock::universal_time()),
48 heartbeat_impl_(0), partner_state_(-1), clock_skew_(0, 0, 0, 0),
49 last_clock_skew_warn_() {
58 if (state ==
"hot-standby") {
60 }
else if (state ==
"load-balancing") {
62 }
else if (state ==
"partner-down") {
64 }
else if (state ==
"ready") {
66 }
else if (state ==
"syncing") {
68 }
else if (state ==
"terminated") {
70 }
else if (state ==
"waiting") {
72 }
else if (state ==
"unavailable") {
82 const boost::function<
void()>& heartbeat_impl) {
88 const boost::function<
void()>& heartbeat_impl) {
89 bool settings_modified =
false;
94 settings_modified =
true;
101 " to the heartbeat implementation is not specified");
107 settings_modified |= (
interval_ != interval);
115 " for the heartbeat timer is not specified");
122 if (settings_modified) {
140 boost::posix_time::ptime prev_poke_time =
poke_time_;
142 poke_time_ = boost::posix_time::microsec_clock::universal_time();
155 boost::posix_time::time_duration duration_since_poke =
poke_time_ - prev_poke_time;
156 if (duration_since_poke.total_seconds() > 0) {
168 ptime now = boost::posix_time::microsec_clock::universal_time();
170 return (duration.total_milliseconds());
188 ptime now = boost::posix_time::microsec_clock::universal_time();
195 (since_warn_duration.total_seconds() > MIN_TIME_SINCE_CLOCK_SKEW_WARN)) {
227 std::ostringstream s;
231 s <<
clock_skew_.invert_sign().total_seconds() <<
"s behind";
249 Pkt4Ptr msg = boost::dynamic_pointer_cast<Pkt4>(message);
256 uint16_t secs = msg->getSecs();
261 if ((secs > 255) && ((secs & 0xFF) == 0)) {
262 secs = ((secs >> 8) | (secs << 8));
268 if (secs * 1000 <=
config_->getMaxAckDelay()) {
275 auto existing_requests =
unacked_clients_.equal_range(msg->getHWAddr()->hwaddr_);
279 std::vector<uint8_t> client_id;
282 client_id = opt_client_id->getData();
287 for (
auto r = existing_requests.first; r != existing_requests.second; ++r) {
288 if (r->second == client_id) {
296 unacked_clients_.insert(std::make_pair(msg->getHWAddr()->hwaddr_, client_id));
301 return ((
config_->getMaxUnackedClients() == 0) ||
318 Pkt6Ptr msg = boost::dynamic_pointer_cast<Pkt6>(message);
328 if (!elapsed_time || elapsed_time->getValue() * 10 <=
config_->getMaxAckDelay()) {
342 return ((
config_->getMaxUnackedClients() == 0) ||
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
Forward declaration to OptionInt.
OptionPtr getOption(uint16_t type) const
Returns shared_ptr to suboption of specific type.
virtual void clearUnackedClients()
Removes information about clients which the partner server failed to respond to.
std::multimap< std::vector< uint8_t >, std::vector< uint8_t > > unacked_clients_
Holds information about the clients which the partner server failed to respond to.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
CommunicationState4(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
std::set< std::vector< uint8_t > > unacked_clients_
Holds information about the clients which the partner server failed to respond to.
CommunicationState6(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
virtual bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
virtual void clearUnackedClients()
Removes information about clients which the partner server failed to respond to.
Holds communication state between the two HA peers.
void startHeartbeatInternal(const long interval=0, const boost::function< void()> &heartbeat_impl=0)
Starts recurring heartbeat.
bool isCommunicationInterrupted() const
Checks if communication with the partner is interrupted.
boost::function< void()> heartbeat_impl_
Pointer to the function providing heartbeat implementation.
bool clockSkewShouldWarn()
Indicates whether the HA service should issue a warning about high clock skew between the active serv...
std::string logFormatClockSkew() const
Returns current clock skew value in the logger friendly format.
void setPartnerState(const std::string &state)
Sets partner state.
virtual ~CommunicationState()
Destructor.
HAConfigPtr config_
High availability configuration.
virtual void clearUnackedClients()=0
Removes information about clients which the partner server failed to respond to.
bool isClockSkewGreater(const long seconds) const
Checks if the clock skew is greater than the specified number of seconds.
long interval_
Interval specified for the heartbeat.
void stopHeartbeat()
Stops recurring heartbeat.
void setPartnerTime(const std::string &time_text)
Provide partner's notion of time so the new clock skew can be calculated.
asiolink::IOServicePtr io_service_
Pointer to the common IO service instance.
boost::posix_time::time_duration clock_skew_
Clock skew between the active servers.
bool clockSkewShouldTerminate() const
Indicates whether the HA service should enter "terminated" state as a result of the clock skew exceed...
boost::posix_time::ptime poke_time_
Last poke time.
CommunicationState(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
int partner_state_
Last known state of the partner server.
boost::posix_time::ptime last_clock_skew_warn_
Holds a time when last warning about too high clock skew was issued.
void startHeartbeat(const long interval, const boost::function< void()> &heartbeat_impl)
Starts recurring heartbeat (public interface).
int64_t getDurationInMillisecs() const
Returns duration between the poke time and current time.
asiolink::IntervalTimerPtr timer_
Interval timer triggering heartbeat commands.
void poke()
Pokes the communication state.
This class parses and generates time values used in HTTP.
boost::posix_time::ptime getPtime() const
Returns time encapsulated by this class.
static HttpDateTime fromRfc1123(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 1123.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint16 > OptionUint16Ptr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
@ DHO_DHCP_CLIENT_IDENTIFIER
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< Option > OptionPtr
const int HA_HOT_STANDBY_ST
Hot standby state.
const int HA_UNAVAILABLE_ST
Special state indicating that this server is unable to communicate with the partner.
const int HA_TERMINATED_ST
HA service terminated state.
const int HA_LOAD_BALANCING_ST
Load balancing state.
const int HA_PARTNER_DOWN_ST
Partner down state.
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
const int HA_WAITING_ST
Server waiting state, i.e. waiting for another server to be ready.
const int HA_SYNCING_ST
Synchronizing database state.
const int HA_READY_ST
Server ready state, i.e. synchronized database, can enable DHCP service.
Defines the logger used by the top-level component of kea-dhcp-ddns.