18 #include <boost/bind.hpp> 19 #include <boost/pointer_cast.hpp> 26 using namespace boost::posix_time;
31 constexpr
long WARN_CLOCK_SKEW = 30;
34 constexpr
long TERM_CLOCK_SKEW = 60;
37 constexpr
long MIN_TIME_SINCE_CLOCK_SKEW_WARN = 60;
44 CommunicationState::CommunicationState(
const IOServicePtr& io_service,
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) ||
boost::function< void()> heartbeat_impl_
Pointer to the function providing heartbeat implementation.
const int HA_TERMINATED_ST
HA service terminated state.
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 bool failureDetected() const
Checks if the partner failure has been detected based on the DHCP traffic analysis.
const int HA_HOT_STANDBY_ST
Hot standby state.
int64_t getDurationInMillisecs() const
Returns duration between the poke time and current time.
void setPartnerTime(const std::string &time_text)
Provide partner's notion of time so the new clock skew can be calculated.
Holds communication state between the two HA peers.
const int HA_PARTNER_DOWN_ST
Partner down state.
void startHeartbeatInternal(const long interval=0, const boost::function< void()> &heartbeat_impl=0)
Starts recurring heartbeat.
boost::shared_ptr< Option > OptionPtr
const int HA_LOAD_BALANCING_ST
Load balancing state.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
bool isCommunicationInterrupted() const
Checks if communication with the partner is interrupted.
asiolink::IOServicePtr io_service_
Pointer to the common IO service instance.
Forward declaration to OptionInt.
const int HA_WAITING_ST
Server waiting state, i.e. waiting for another server to be ready.
long interval_
Interval specified for the heartbeat.
boost::posix_time::ptime poke_time_
Last poke time.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< OptionUint16 > OptionUint16Ptr
virtual void clearUnackedClients()
Removes information about clients which the partner server failed to respond to.
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
virtual void clearUnackedClients()=0
Removes information about clients which the partner server failed to respond to.
const int HA_READY_ST
Server ready state, i.e. synchronized database, can enable DHCP service.
boost::posix_time::ptime getPtime() const
Returns time encapsulated by this class.
int partner_state_
Last known state of the partner server.
OptionPtr getOption(uint16_t type) const
Returns shared_ptr to suboption of specific type.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv6 message appears to be unanswered.
static HttpDateTime fromRfc1123(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 1123.
void stopHeartbeat()
Stops recurring heartbeat.
This class parses and generates time values used in HTTP.
virtual void clearUnackedClients()
Removes information about clients which the partner server failed to respond to.
Defines the logger used by the top-level component of kea-dhcp-ddns.
void startHeartbeat(const long interval, const boost::function< void()> &heartbeat_impl)
Starts recurring heartbeat (public interface).
void poke()
Pokes the communication state.
std::set< std::vector< uint8_t > > unacked_clients_
Holds information about the clients which the partner server failed to respond to.
boost::posix_time::time_duration clock_skew_
Clock skew between the active servers.
CommunicationState4(const asiolink::IOServicePtr &io_service, const HAConfigPtr &config)
Constructor.
virtual void analyzeMessage(const boost::shared_ptr< dhcp::Pkt > &message)
Checks if the DHCPv4 message appears to be unanswered.
void setPartnerState(const std::string &state)
Sets partner state.
std::string logFormatClockSkew() const
Returns current clock skew value in the logger friendly format.
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 ~CommunicationState()
Destructor.
bool clockSkewShouldWarn()
Indicates whether the HA service should issue a warning about high clock skew between the active serv...
bool clockSkewShouldTerminate() const
Indicates whether the HA service should enter "terminated" state as a result of the clock skew exceed...
boost::posix_time::ptime last_clock_skew_warn_
Holds a time when last warning about too high clock skew was issued.
asiolink::IntervalTimerPtr timer_
Interval timer triggering heartbeat commands.
const int HA_SYNCING_ST
Synchronizing database state.
HAConfigPtr config_
High availability configuration.
boost::shared_ptr< HAConfig > HAConfigPtr
Pointer to the High Availability configuration structure.
const int HA_UNAVAILABLE_ST
Special state indicating that this server is unable to communicate with the partner.
bool isClockSkewGreater(const long seconds) const
Checks if the clock skew is greater than the specified number of seconds.