21#include <boost/pointer_cast.hpp>
22#include <boost/bind.hpp>
23#include <boost/make_shared.hpp>
24#include <boost/weak_ptr.hpp>
46 : io_service_(io_service), network_state_(network_state), config_(config),
47 server_type_(server_type), client_(*io_service), communication_state_(),
48 query_filter_(config), pending_requests_() {
196 if (
config_->getThisServerConfig()->isAutoFailover()) {
359 unsigned int dhcp_disable_timeout =
360 static_cast<unsigned int>(
config_->getSyncTimeout() / 1000);
361 if (dhcp_disable_timeout == 0) {
362 ++dhcp_disable_timeout;
366 std::string status_message;
368 config_->getFailoverPeerConfig()->getName(),
369 dhcp_disable_timeout);
497 std::string partner_state_name =
getStateLabel(partner_state);
500 boost::to_upper(current_state_name);
501 boost::to_upper(new_state_name);
502 boost::to_upper(partner_state_name);
506 .arg(current_state_name)
508 .arg(partner_state_name);
527 .arg(new_state_name);
529 }
else if (!
config_->amSendingLeaseUpdates()) {
532 .arg(new_state_name);
539 .arg(new_state_name);
559 boost::to_upper(state_name);
572 return (inScopeInternal(query4));
577 return (inScopeInternal(query6));
580template<
typename QueryPtrType>
582HAService::inScopeInternal(QueryPtrType& query) {
584 std::string scope_class;
603 boost::to_upper(current_state_name);
613 boost::to_upper(current_state_name);
615 .arg(
config_->getThisServerName())
616 .arg(current_state_name);
619 }
else if (should_enable && !
network_state_->isServiceEnabled()) {
621 boost::to_upper(current_state_name);
623 .arg(
config_->getThisServerName())
624 .arg(current_state_name);
683 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
696 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
702 for (
auto l = leases->begin(); l != leases->end(); ++l) {
723 for (
auto p = peers_configs.begin(); p != peers_configs.end(); ++p) {
736 for (
auto l = deleted_leases->begin(); l != deleted_leases->end(); ++l) {
742 for (
auto l = leases->begin(); l != leases->end(); ++l) {
751template<
typename QueryPtrType>
760 request->setBodyAsJson(command);
770 boost::weak_ptr<typename QueryPtrType::element_type> weak_query(query);
774 [
this, weak_query, parking_lot, config]
775 (
const boost::system::error_code& ec,
777 const std::string& error_str) {
781 QueryPtrType query = weak_query.lock();
783 isc_throw(Unexpected,
"query is null while receiving response from"
784 " HA peer. This is programmatic error");
793 bool lease_update_success =
true;
796 if (ec || !error_str.empty()) {
797 LOG_WARN(ha_logger, HA_LEASE_UPDATE_COMMUNICATIONS_FAILED)
798 .arg(query->getLabel())
799 .arg(config->getLogLabel())
800 .arg(ec ? ec.message() : error_str);
804 lease_update_success = false;
810 verifyAsyncResponse(response);
812 } catch (
const std::exception& ex) {
814 .arg(query->getLabel())
815 .arg(config->getLogLabel())
819 lease_update_success =
false;
826 if (lease_update_success) {
830 communication_state_->poke();
834 parking_lot->drop(query);
835 communication_state_->setPartnerState(
"unavailable");
839 auto it = pending_requests_.find(query);
843 if (it == pending_requests_.end() || (--pending_requests_[query] <= 0)) {
844 parking_lot->unpark(query);
848 if (it != pending_requests_.end()) {
849 pending_requests_.erase(it);
857 runModel(HA_LEASE_UPDATES_COMPLETE_EVT);
862 if (pending_requests_.count(query) == 0) {
863 pending_requests_[query] = 1;
866 ++pending_requests_[query];
873 if (!config_->amSendingLeaseUpdates()) {
878 if (peer_config->getRole() == HAConfig::PeerConfig::BACKUP) {
883 if (config_->getThisServerConfig()->getRole() == HAConfig::PeerConfig::BACKUP) {
889 switch (getCurrState()) {
902HAService::processHeartbeat() {
904 std::string state_label = getState(getCurrState())->getLabel();
915HAService::asyncSendHeartbeat() {
921 request->setBodyAsJson(CommandCreator::createHeartbeat(server_type_));
929 client_.asyncSendRequest(partner_config->getUrl(), request, response,
930 [
this, partner_config]
931 (
const boost::system::error_code& ec,
933 const std::string& error_str) {
941 bool heartbeat_success = true;
944 if (ec || !error_str.empty()) {
945 LOG_WARN(ha_logger, HA_HEARTBEAT_COMMUNICATIONS_FAILED)
946 .arg(partner_config->getLogLabel())
947 .arg(ec ? ec.message() : error_str);
948 heartbeat_success = false;
956 ConstElementPtr args = verifyAsyncResponse(response);
957 if (!args || args->getType() != Element::map) {
958 isc_throw(CtrlChannelError,
"returned arguments in the response"
962 ConstElementPtr state = args->get(
"state");
963 if (!state || state->getType() != Element::string) {
964 isc_throw(CtrlChannelError,
"server state not returned in response"
965 " to a ha-heartbeat command or it is not a string");
969 communication_state_->setPartnerState(state->stringValue());
971 ConstElementPtr date_time = args->get(
"date-time");
972 if (!date_time || date_time->getType() != Element::string) {
973 isc_throw(CtrlChannelError,
"date-time not returned in response"
974 " to a ha-heartbeat command or it is not a string");
977 communication_state_->setPartnerTime(date_time->stringValue());
979 } catch (
const std::exception& ex) {
981 .arg(partner_config->getLogLabel())
983 heartbeat_success =
false;
989 if (heartbeat_success) {
990 communication_state_->poke();
995 communication_state_->setPartnerState(
"unavailable");
1004 runModel(HA_HEARTBEAT_COMPLETE_EVT);
1009HAService::scheduleHeartbeat() {
1010 if (!communication_state_->isHeartbeatRunning()) {
1016HAService::startHeartbeat() {
1017 if (config_->getHeartbeatDelay() > 0) {
1018 communication_state_->startHeartbeat(config_->getHeartbeatDelay(),
1019 boost::bind(&HAService::asyncSendHeartbeat,
1026 const std::string& server_name,
1027 const unsigned int max_period,
1035 request->setBodyAsJson(CommandCreator::createDHCPDisable(max_period,
1037 request->finalize();
1045 [
this, remote_config, post_request_action]
1046 (
const boost::system::error_code& ec,
1048 const std::string& error_str) {
1056 std::string error_message;
1059 if (ec || !error_str.empty()) {
1060 error_message = (ec ? ec.message() : error_str);
1061 LOG_ERROR(ha_logger, HA_DHCP_DISABLE_COMMUNICATIONS_FAILED)
1062 .arg(remote_config->getLogLabel())
1063 .arg(error_message);
1069 static_cast<void>(verifyAsyncResponse(response));
1071 } catch (
const std::exception& ex) {
1072 error_message = ex.what();
1074 .arg(remote_config->getLogLabel())
1075 .arg(error_message);
1081 if (!error_message.empty()) {
1082 communication_state_->setPartnerState(
"unavailable");
1086 if (post_request_action) {
1087 post_request_action(error_message.empty(),
1095 const std::string& server_name,
1102 request->setBodyAsJson(CommandCreator::createDHCPEnable(server_type_));
1103 request->finalize();
1111 [
this, remote_config, post_request_action]
1112 (
const boost::system::error_code& ec,
1114 const std::string& error_str) {
1122 std::string error_message;
1125 if (ec || !error_str.empty()) {
1126 error_message = (ec ? ec.message() : error_str);
1127 LOG_ERROR(ha_logger, HA_DHCP_ENABLE_COMMUNICATIONS_FAILED)
1128 .arg(remote_config->getLogLabel())
1129 .arg(error_message);
1135 static_cast<void>(verifyAsyncResponse(response));
1137 } catch (
const std::exception& ex) {
1138 error_message = ex.what();
1140 .arg(remote_config->getLogLabel())
1141 .arg(error_message);
1147 if (!error_message.empty()) {
1148 communication_state_->setPartnerState(
"unavailable");
1152 if (post_request_action) {
1153 post_request_action(error_message.empty(),
1160HAService::localDisableDHCPService() {
1161 network_state_->disableService();
1165HAService::localEnableDHCPService() {
1166 network_state_->enableService();
1170HAService::asyncSyncLeases() {
1174 unsigned int dhcp_disable_timeout =
1175 static_cast<unsigned int>(config_->getSyncTimeout() / 1000);
1176 if (dhcp_disable_timeout == 0) {
1178 dhcp_disable_timeout = 1;
1181 asyncSyncLeases(client_, config_->getFailoverPeerConfig()->getName(),
1182 dhcp_disable_timeout,
LeasePtr(), null_action);
1187 const std::string& server_name,
1188 const unsigned int max_period,
1191 const bool dhcp_disabled) {
1197 asyncDisableDHCPService(http_client, server_name, max_period,
1198 [
this, &http_client, server_name, max_period, last_lease,
1199 post_sync_action, dhcp_disabled]
1200 (
const bool success,
const std::string& error_message) {
1207 asyncSyncLeasesInternal(http_client, server_name, max_period,
1208 last_lease, post_sync_action,
true);
1211 post_sync_action(success, error_message, dhcp_disabled);
1218 const std::string& server_name,
1219 const unsigned int max_period,
1222 const bool dhcp_disabled) {
1229 if (server_type_ == HAServerType::DHCPv4) {
1230 request->setBodyAsJson(CommandCreator::createLease4GetPage(
1231 boost::dynamic_pointer_cast<Lease4>(last_lease), config_->getSyncPageLimit()));
1234 request->setBodyAsJson(CommandCreator::createLease6GetPage(
1235 boost::dynamic_pointer_cast<Lease6>(last_lease), config_->getSyncPageLimit()));
1237 request->finalize();
1245 [
this, partner_config, post_sync_action, &http_client, server_name,
1246 max_period, dhcp_disabled]
1247 (
const boost::system::error_code& ec,
1249 const std::string& error_str) {
1253 LeasePtr last_lease;
1261 std::string error_message;
1264 if (ec || !error_str.empty()) {
1265 error_message = (ec ? ec.message() : error_str);
1266 LOG_ERROR(ha_logger, HA_LEASES_SYNC_COMMUNICATIONS_FAILED)
1267 .arg(partner_config->getLogLabel())
1268 .arg(error_message);
1273 ConstElementPtr args = verifyAsyncResponse(response);
1276 if (args && (args->getType() != Element::map)) {
1277 isc_throw(CtrlChannelError,
1278 "arguments in the received response must be a map");
1281 ConstElementPtr leases = args->get(
"leases");
1282 if (!leases || (leases->getType() != Element::list)) {
1283 isc_throw(CtrlChannelError,
1284 "server response does not contain leases argument or this"
1285 " argument is not a list");
1289 const auto& leases_element = leases->listValue();
1291 LOG_INFO(ha_logger, HA_LEASES_SYNC_LEASE_PAGE_RECEIVED)
1292 .arg(leases_element.size())
1295 for (auto l = leases_element.begin(); l != leases_element.end(); ++l) {
1298 if (server_type_ == HAServerType::DHCPv4) {
1299 Lease4Ptr lease = Lease4::fromElement(*l);
1302 Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(lease->addr_);
1303 if (!existing_lease) {
1305 LeaseMgrFactory::instance().addLease(lease);
1307 } else if (existing_lease->cltt_ < lease->cltt_) {
1310 LeaseMgrFactory::instance().updateLease4(lease);
1313 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE4_SKIP)
1314 .arg(lease->addr_.toText())
1315 .arg(lease->subnet_id_);
1321 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
1322 (l + 1 == leases_element.end())) {
1323 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
1327 Lease6Ptr lease = Lease6::fromElement(*l);
1330 Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(lease->type_,
1332 if (!existing_lease) {
1334 LeaseMgrFactory::instance().addLease(lease);
1336 } else if (existing_lease->cltt_ < lease->cltt_) {
1339 LeaseMgrFactory::instance().updateLease6(lease);
1342 LOG_DEBUG(ha_logger, DBGLVL_TRACE_BASIC, HA_LEASE_SYNC_STALE_LEASE6_SKIP)
1343 .arg(lease->addr_.toText())
1344 .arg(lease->subnet_id_);
1350 if ((leases_element.size() >= config_->getSyncPageLimit()) &&
1351 (l + 1 == leases_element.end())) {
1352 last_lease = boost::dynamic_pointer_cast<Lease>(lease);
1357 } catch (const std::exception& ex) {
1358 LOG_WARN(ha_logger, HA_LEASE_SYNC_FAILED)
1364 } catch (
const std::exception& ex) {
1365 error_message = ex.what();
1367 .arg(partner_config->getLogLabel())
1368 .arg(error_message);
1374 if (!error_message.empty()) {
1375 communication_state_->setPartnerState(
"unavailable");
1377 }
else if (last_lease) {
1380 asyncSyncLeases(http_client, server_name, max_period, last_lease,
1381 post_sync_action, dhcp_disabled);
1386 if (post_sync_action) {
1387 post_sync_action(error_message.empty(),
1395HAService::processSynchronize(
const std::string& server_name,
1396 const unsigned int max_period) {
1397 std::string answer_message;
1398 int sync_status = synchronize(answer_message, server_name, max_period);
1403HAService::synchronize(std::string& status_message,
const std::string& server_name,
1404 const unsigned int max_period) {
1408 asyncSyncLeases(client, server_name, max_period,
Lease4Ptr(),
1409 [&](
const bool success,
const std::string& error_message,
1410 const bool dhcp_disabled) {
1415 status_message = error_message;
1421 if (dhcp_disabled) {
1422 asyncEnableDHCPService(client, server_name,
1423 [&](
const bool success,
1424 const std::string& error_message) {
1428 if (!success && status_message.empty()) {
1429 status_message = error_message;
1459 if (!status_message.empty()) {
1460 postNextEvent(HA_SYNCING_FAILED_EVT);
1464 .arg(status_message);
1471 status_message =
"Lease database synchronization complete.";
1472 postNextEvent(HA_SYNCING_SUCCEEDED_EVT);
1483HAService::processScopes(
const std::vector<std::string>& scopes) {
1485 query_filter_.serveScopes(scopes);
1486 adjustNetworkState();
1488 }
catch (
const std::exception& ex) {
1496HAService::processContinue() {
1507 boost::dynamic_pointer_cast<HttpResponseJson>(response);
1508 if (!json_response) {
1524 if (body->empty()) {
1534 std::ostringstream s;
1537 s << args->stringValue() <<
", ";
1540 s <<
"error code " << rcode;
The IOService class is a wrapper for the ASIO io_service class.
void run()
Start the underlying event loop.
void stop()
Stop the underlying event loop.
A standard control channel exception that is thrown if a function is there is a problem with one of t...
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static data::ConstElementPtr createLease4Delete(const dhcp::Lease4 &lease4)
Creates lease4-del command.
static data::ConstElementPtr createLease4Update(const dhcp::Lease4 &lease4)
Creates lease4-update command.
static data::ConstElementPtr createLease6Update(const dhcp::Lease6 &lease6)
Creates lease6-update command.
static data::ConstElementPtr createLease6Delete(const dhcp::Lease6 &lease6)
Creates lease6-del command.
Holds communication state between DHCPv4 servers.
Holds communication state between DHCPv6 servers.
static std::string roleToString(const HAConfig::PeerConfig::Role &role)
Returns role name.
std::map< std::string, PeerConfigPtr > PeerConfigMap
Map of the servers' configurations.
static std::string HAModeToString(const HAMode &ha_mode)
Returns HA mode name.
boost::shared_ptr< PeerConfig > PeerConfigPtr
Pointer to the server's configuration.
bool inScope(dhcp::Pkt4Ptr &query4)
Checks if the DHCPv4 query should be processed by this server.
void adjustNetworkState()
Enables or disables network state depending on the served scopes.
static const int HA_HEARTBEAT_COMPLETE_EVT
Finished heartbeat commannd.
void asyncSendLeaseUpdate(const QueryPtrType &query, const HAConfig::PeerConfigPtr &config, const data::ConstElementPtr &command, const hooks::ParkingLotHandlePtr &parking_lot)
Asynchronously sends lease update to the peer.
void verboseTransition(const unsigned state)
Transitions to a desired state and logs it.
http::HttpClient client_
HTTP client instance used to send lease updates.
HAConfigPtr config_
Pointer to the HA hooks library configuration.
bool shouldTerminate() const
Indicates if the server should transition to the terminated state as a result of high clock skew.
void terminatedStateHandler()
Handler for "terminated" state.
dhcp::NetworkStatePtr network_state_
Pointer to the state of the DHCP service (enabled/disabled).
HAService(const asiolink::IOServicePtr &io_service, const dhcp::NetworkStatePtr &network_state, const HAConfigPtr &config, const HAServerType &server_type=HAServerType::DHCPv4)
Constructor.
void scheduleHeartbeat()
Schedules asynchronous heartbeat to a peer if it is not scheduled.
QueryFilter query_filter_
Selects queries to be processed/dropped.
virtual void verifyEvents()
Verifies events used by the HA service.
void conditionalLogPausedState() const
Logs if the server is paused in the current state.
bool unpause()
Unpauses the HA state machine with logging.
void serveDefaultScopes()
Instructs the HA service to serve default scopes.
size_t asyncSendLeaseUpdates(const dhcp::Pkt4Ptr &query, const dhcp::Lease4CollectionPtr &leases, const dhcp::Lease4CollectionPtr &deleted_leases, const hooks::ParkingLotHandlePtr &parking_lot)
Schedules asynchronous IPv4 leases updates.
static const int HA_SYNCING_SUCCEEDED_EVT
Lease database synchroniation succeeded.
virtual void defineEvents()
Defines events used by the HA service.
asiolink::IOServicePtr io_service_
Pointer to the IO service object shared between this hooks library and the DHCP server.
CommunicationStatePtr communication_state_
Holds communication state with a peer.
static const int HA_SYNCING_FAILED_EVT
Lease database synchronization failed.
std::function< void(const bool, const std::string &)> PostRequestCallback
Callback invoked when request was sent and a response received or an error occurred.
void readyStateHandler()
Handler for "ready" state.
virtual void defineStates()
Defines states of the HA service.
void backupStateHandler()
Handler for the "backup" state.
int synchronize(std::string &status_message, const std::string &server_name, const unsigned int max_period)
Synchronizes lease database with a partner.
void normalStateHandler()
Handler for the "hot-standby" and "load-balancing" states.
void waitingStateHandler()
Handler for "waiting" state.
bool shouldSendLeaseUpdates(const HAConfig::PeerConfigPtr &peer_config) const
Checks if the lease updates should be sent as result of leases allocation or release.
static const int HA_LEASE_UPDATES_COMPLETE_EVT
Finished lease updates commands.
void partnerDownStateHandler()
Handler for "partner-down" state.
bool shouldPartnerDown() const
Indicates if the server should transition to the partner down state.
std::function< void(const bool, const std::string &, const bool)> PostSyncCallback
Callback invoked when lease database synchronization is complete.
void syncingStateHandler()
Handler for "syncing" state.
bool inScope(const dhcp::Pkt4Ptr &query4, std::string &scope_class) const
Checks if this server should process the DHCPv4 query.
void serveFailoverScopes()
Enable scopes required in failover case.
void serveDefaultScopes()
Serve default scopes for the given HA mode.
void serveNoScopes()
Disables all scopes.
void asyncSendRequest(const Url &url, const HttpRequestPtr &request, const HttpResponsePtr &response, const RequestHandler &request_callback, const RequestTimeout &request_timeout=RequestTimeout(10000), const ConnectHandler &connect_callback=ConnectHandler())
Queues new asynchronous HTTP request.
This class parses and generates time values used in HTTP.
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
const EventPtr & getEvent(unsigned int value)
Fetches the event referred to by value.
std::string getStateLabel(const int state) const
Fetches the label associated with an state value.
void unpauseModel()
Unpauses state model.
bool isModelPaused() const
Returns whether or not the model is paused.
virtual void defineEvents()
Populates the set of events.
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
unsigned int getNextEvent() const
Fetches the model's next event.
void defineEvent(unsigned int value, const std::string &label)
Adds an event value and associated label to the set of events.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
virtual void verifyEvents()
Validates the contents of the set of events.
bool doOnEntry()
Checks if on entry flag is true.
static const int NOP_EVT
Signifies that no event has occurred.
void startModel(const int start_state)
Begins execution of the model.
virtual void defineStates()
Populates the set of states.
unsigned int getCurrState() const
Fetches the model's current state.
Utility class to measure code execution times.
void stop()
Stops the stopwatch.
std::string logFormatLastDuration() const
Returns the last measured duration in the format directly usable in log messages.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
An abstract API for lease database.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
std::string ClientClass
Defines a single class name.
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const int HA_HOT_STANDBY_ST
Hot standby state.
isc::log::Logger ha_logger("ha-hooks")
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.
HAServerType
Lists possible server types for which HA service is created.
const int HA_BACKUP_ST
Backup state.
const int HA_SYNCING_ST
Synchronizing database state.
std::string stateToString(int state)
Returns state name.
const int HA_READY_ST
Server ready state, i.e. synchronized database, can enable DHCP service.
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
boost::shared_ptr< PostHttpRequestJson > PostHttpRequestJsonPtr
Pointer to PostHttpRequestJson.
boost::shared_ptr< HttpResponseJson > HttpResponseJsonPtr
Pointer to the HttpResponseJson object.
boost::shared_ptr< HttpResponse > HttpResponsePtr
Pointer to the HttpResponse object.
Defines the logger used by the top-level component of kea-dhcp-ddns.
HTTP request/response timeout value.
static const HttpVersion & HTTP_11()
HTTP version 1.1.