HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- bool status = HooksManager::loadLibraries(loaded);
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ bool status = HooksManager::loadLibraries(loaded, multi_threading_enabled);
if (!status) {
isc_throw(Unexpected, "Failed to reload hooks libraries "
"(WARNING: libreload is deprecated).");
ControlledDhcpv4Srv::commandConfigReloadHandler(const string&,
ConstElementPtr /*args*/) {
// Get configuration file name.
- std::string file = ControlledDhcpv4Srv::getInstance()->getConfigFile();
+ string file = ControlledDhcpv4Srv::getInstance()->getConfigFile();
try {
LOG_INFO(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION).arg(file);
auto result = loadConfigFile(file);
ConstElementPtr cfg = CfgMgr::instance().getCurrentCfg()->toElement();
size = writeConfigFile(filename, cfg);
} catch (const isc::Exception& ex) {
- return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config:")
+ return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config: ")
+ ex.what()));
}
if (size == 0) {
/// @brief Configure DHCPv4 server using the configuration file specified.
///
- /// This utility method is called whenever we know a filename of the config
- /// and need to load it. It calls config-set command once the content of
- /// the file has been loaded and verified to be a sane JSON configuration.
- /// config-set handler will process the config file (load it as current
- /// configuration).
- ///
/// This function is used to both configure the DHCP server on its startup
/// and dynamically reconfigure the server when SIGHUP signal is received.
///
/// It fetches DHCPv4 server's configuration from the 'Dhcp4' section of
/// the JSON configuration file.
///
+ /// This utility method is called whenever we know a filename of the config
+ /// and need to load it. It calls config-set command once the content of
+ /// the file has been loaded and verified to be a sane JSON configuration.
+ /// config-set handler will process the config file (apply it as current
+ /// configuration).
+ ///
/// @param file_name name of the file to be loaded
/// @return status of the file loading and outcome of config-set
isc::data::ConstElementPtr
/// @brief Initiates shutdown procedure for the whole DHCPv4 server.
/// @param exit_value integer value to the process should exit with.
- void shutdownServer(int exit_value);
+ virtual void shutdownServer(int exit_value);
/// @brief Command processor
///
/// in them.
///
/// Currently supported commands are:
- /// - config-reload
- /// - config-test
/// - shutdown
/// - libreload
+ /// - config-reload
+ /// - config-set
+ /// - config-get
+ /// - config-test
+ /// - dhcp-disable
+ /// - dhcp-enable
+ /// - version-get
+ /// - build-report
/// - leases-reclaim
+ /// - config-write
/// ...
///
/// @note It never throws.
}
private:
-
/// @brief Callback that will be called from iface_mgr when data
/// is received over control socket.
///
#include <dhcpsrv/cfg_multi_threading.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/db_type.h>
-#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/host_mgr.h>
+#include <dhcpsrv/lease_mgr_factory.h>
#include <hooks/hooks.h>
#include <hooks/hooks_manager.h>
#include <process/cfgrpt/config_report.h>
ControlledDhcpv6Srv* ControlledDhcpv6Srv::server_ = NULL;
+void
+ControlledDhcpv6Srv::init(const std::string& file_name) {
+ // Keep the call timestamp.
+ start_ = boost::posix_time::second_clock::universal_time();
+
+ // Configure the server using JSON file.
+ ConstElementPtr result = loadConfigFile(file_name);
+
+ int rcode;
+ ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
+ if (rcode != CONTROL_RESULT_SUCCESS) {
+ string reason = comment ? comment->stringValue() :
+ "no details available";
+ isc_throw(isc::BadValue, reason);
+ }
+
+ // We don't need to call openActiveSockets() or startD2() as these
+ // methods are called in processConfig() which is called by
+ // processCommand("config-set", ...)
+
+ // Set signal handlers. When the SIGHUP is received by the process
+ // the server reconfiguration will be triggered. When SIGTERM or
+ // SIGINT will be received, the server will start shutting down.
+ signal_set_.reset(new IOSignalSet(getIOService(), signalHandler));
+
+ signal_set_->add(SIGINT);
+ signal_set_->add(SIGHUP);
+ signal_set_->add(SIGTERM);
+}
+
+void ControlledDhcpv6Srv::cleanup() {
+ signal_set_.reset();
+ getIOService()->poll();
+}
+
ConstElementPtr
ControlledDhcpv6Srv::loadConfigFile(const std::string& file_name) {
// This is a configuration backend implementation that reads the
try {
if (file_name.empty()) {
// Basic sanity check: file name must not be empty.
- isc_throw(isc::BadValue, "JSON configuration file not specified. Please "
- "use -c command line option.");
+ isc_throw(isc::BadValue, "JSON configuration file not specified."
+ " Please use -c command line option.");
}
// Read contents of the file and parse it as JSON
return (result);
}
-void
-ControlledDhcpv6Srv::init(const std::string& file_name) {
- // Keep the call timestamp.
- start_ = boost::posix_time::second_clock::universal_time();
-
- // Configure the server using JSON file.
- ConstElementPtr result = loadConfigFile(file_name);
-
- int rcode;
- ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
- if (rcode != CONTROL_RESULT_SUCCESS) {
- string reason = comment ? comment->stringValue() :
- "no details available";
- isc_throw(isc::BadValue, reason);
- }
-
- // We don't need to call openActiveSockets() or startD2() as these
- // methods are called in processConfig() which is called by
- // processCommand("config-set", ...)
-
- // Set signal handlers. When the SIGHUP is received by the process
- // the server reconfiguration will be triggered. When SIGTERM or
- // SIGINT will be received, the server will start shutting down.
- signal_set_.reset(new IOSignalSet(getIOService(), signalHandler));
-
- signal_set_->add(SIGINT);
- signal_set_->add(SIGHUP);
- signal_set_->add(SIGTERM);
-}
-
-void ControlledDhcpv6Srv::cleanup() {
- signal_set_.reset();
- getIOService()->poll();
-}
-
ConstElementPtr
ControlledDhcpv6Srv::commandShutdownHandler(const string&, ConstElementPtr args) {
if (!ControlledDhcpv6Srv::getInstance()) {
HookLibsCollection loaded = HooksManager::getLibraryInfo();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
- bool status = HooksManager::loadLibraries(loaded);
+ bool multi_threading_enabled = true;
+ uint32_t thread_count = 0;
+ uint32_t queue_size = 0;
+ CfgMultiThreading::extract(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading(),
+ multi_threading_enabled, thread_count, queue_size);
+ bool status = HooksManager::loadLibraries(loaded, multi_threading_enabled);
if (!status) {
- isc_throw(Unexpected, "Failed to reload hooks libraries"
- " (WARNING: libreload is deprecated).");
+ isc_throw(Unexpected, "Failed to reload hooks libraries "
+ "(WARNING: libreload is deprecated).");
}
} catch (const std::exception& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_HOOKS_LIBS_RELOAD_FAIL);
ControlledDhcpv6Srv::commandConfigReloadHandler(const string&,
ConstElementPtr /*args*/) {
// Get configuration file name.
- std::string file = ControlledDhcpv6Srv::getInstance()->getConfigFile();
+ string file = ControlledDhcpv6Srv::getInstance()->getConfigFile();
try {
LOG_INFO(dhcp6_logger, DHCP6_DYNAMIC_RECONFIGURATION).arg(file);
auto result = loadConfigFile(file);
ConstElementPtr cfg = CfgMgr::instance().getCurrentCfg()->toElement();
size = writeConfigFile(filename, cfg);
} catch (const isc::Exception& ex) {
- return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config:")
+ return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config: ")
+ ex.what()));
}
if (size == 0) {
return (configureDhcp6Server(*srv, config, true));
}
-ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t server_port,
- uint16_t client_port)
+ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t server_port /*= DHCP6_SERVER_PORT*/,
+ uint16_t client_port /*= 0*/)
: Dhcpv6Srv(server_port, client_port), timer_mgr_(TimerMgr::instance()) {
if (getInstance()) {
isc_throw(InvalidOperation,
CommandMgr::instance().registerCommand("config-reload",
std::bind(&ControlledDhcpv6Srv::commandConfigReloadHandler, this, ph::_1, ph::_2));
+ CommandMgr::instance().registerCommand("config-set",
+ std::bind(&ControlledDhcpv6Srv::commandConfigSetHandler, this, ph::_1, ph::_2));
+
CommandMgr::instance().registerCommand("config-test",
std::bind(&ControlledDhcpv6Srv::commandConfigTestHandler, this, ph::_1, ph::_2));
CommandMgr::instance().registerCommand("config-write",
std::bind(&ControlledDhcpv6Srv::commandConfigWriteHandler, this, ph::_1, ph::_2));
+ CommandMgr::instance().registerCommand("dhcp-enable",
+ std::bind(&ControlledDhcpv6Srv::commandDhcpEnableHandler, this, ph::_1, ph::_2));
+
CommandMgr::instance().registerCommand("dhcp-disable",
std::bind(&ControlledDhcpv6Srv::commandDhcpDisableHandler, this, ph::_1, ph::_2));
- CommandMgr::instance().registerCommand("dhcp-enable",
- std::bind(&ControlledDhcpv6Srv::commandDhcpEnableHandler, this, ph::_1, ph::_2));
+ CommandMgr::instance().registerCommand("libreload",
+ std::bind(&ControlledDhcpv6Srv::commandLibReloadHandler, this, ph::_1, ph::_2));
CommandMgr::instance().registerCommand("leases-reclaim",
std::bind(&ControlledDhcpv6Srv::commandLeasesReclaimHandler, this, ph::_1, ph::_2));
CommandMgr::instance().registerCommand("server-tag-get",
std::bind(&ControlledDhcpv6Srv::commandServerTagGetHandler, this, ph::_1, ph::_2));
- CommandMgr::instance().registerCommand("libreload",
- std::bind(&ControlledDhcpv6Srv::commandLibReloadHandler, this, ph::_1, ph::_2));
-
- CommandMgr::instance().registerCommand("config-set",
- std::bind(&ControlledDhcpv6Srv::commandConfigSetHandler, this, ph::_1, ph::_2));
-
CommandMgr::instance().registerCommand("shutdown",
std::bind(&ControlledDhcpv6Srv::commandShutdownHandler, this, ph::_1, ph::_2));
CommandMgr::instance().registerCommand("statistic-get",
std::bind(&StatsMgr::statisticGetHandler, ph::_1, ph::_2));
- CommandMgr::instance().registerCommand("statistic-get-all",
- std::bind(&StatsMgr::statisticGetAllHandler, ph::_1, ph::_2));
-
CommandMgr::instance().registerCommand("statistic-reset",
std::bind(&StatsMgr::statisticResetHandler, ph::_1, ph::_2));
- CommandMgr::instance().registerCommand("statistic-reset-all",
- std::bind(&StatsMgr::statisticResetAllHandler, ph::_1, ph::_2));
-
CommandMgr::instance().registerCommand("statistic-remove",
std::bind(&StatsMgr::statisticRemoveHandler, ph::_1, ph::_2));
+ CommandMgr::instance().registerCommand("statistic-get-all",
+ std::bind(&StatsMgr::statisticGetAllHandler, ph::_1, ph::_2));
+
+ CommandMgr::instance().registerCommand("statistic-reset-all",
+ std::bind(&StatsMgr::statisticResetAllHandler, ph::_1, ph::_2));
+
CommandMgr::instance().registerCommand("statistic-remove-all",
std::bind(&StatsMgr::statisticRemoveAllHandler, ph::_1, ph::_2));
/// in them.
///
/// Currently supported commands are:
- /// - config-reload
- /// - config-test
/// - shutdown
/// - libreload
+ /// - config-reload
+ /// - config-set
+ /// - config-get
+ /// - config-test
+ /// - dhcp-disable
+ /// - dhcp-enable
+ /// - version-get
+ /// - build-report
/// - leases-reclaim
+ /// - config-write
/// ...
///
/// @note It never throws.
}
private:
-
/// @brief Callback that will be called from iface_mgr when data
/// is received over control socket.
///
}
IOServicePtr io_service(new IOService());
- HttpClient client(*io_service);
+ HttpClient client(*io_service, false);
boost::system::error_code received_ec;
string receive_errmsg;
HttpResponseJsonPtr response(new HttpResponseJson());
// Create the client and(or) listener as appropriate.
if (!config_->getEnableMultiThreading()) {
// Not configured for multi-threading, start a client in ST mode.
- client_.reset(new HttpClient(*io_service_, 0));
+ client_.reset(new HttpClient(*io_service_, false));
} else {
// Create an MT-mode client.
- client_.reset(new HttpClient(*io_service_,
+ client_.reset(new HttpClient(*io_service_, true,
config_->getHttpClientThreads(), true));
// If we're configured to use our own listener create and start it.
HAService::synchronize(std::string& status_message, const std::string& server_name,
const unsigned int max_period) {
IOService io_service;
- HttpClient client(io_service);
+ HttpClient client(io_service, false);
asyncSyncLeases(client, server_name, max_period, Lease4Ptr(),
[&](const bool success, const std::string& error_message,
}
IOService io_service;
- HttpClient client(io_service);
+ HttpClient client(io_service, false);
auto remote_config = config_->getFailoverPeerConfig();
bool updates_successful = true;
bool
HAService::sendHAReset() {
IOService io_service;
- HttpClient client(io_service);
+ HttpClient client(io_service, false);
auto remote_config = config_->getFailoverPeerConfig();
bool reset_successful = true;
HttpResponseJsonPtr response = boost::make_shared<HttpResponseJson>();
IOService io_service;
- HttpClient client(io_service);
+ HttpClient client(io_service, false);
boost::system::error_code captured_ec;
std::string captured_error_message;
HttpResponseJsonPtr response = boost::make_shared<HttpResponseJson>();
IOService io_service;
- HttpClient client(io_service);
+ HttpClient client(io_service, false);
std::string error_message;
.arg(port_)
.arg(tls_context_ ? "true" : "false");
} catch (const std::exception& ex) {
+ thread_io_service_.reset();
+ http_listener_.reset();
+ thread_pool_.reset();
isc_throw(Unexpected, "CmdHttpListener::run failed:" << ex.what());
}
}
IoServiceThreadPoolPtr thread_pool_;
};
-HttpClient::HttpClient(IOService& io_service, size_t thread_pool_size,
- bool defer_thread_start /* = false */) {
+HttpClient::HttpClient(IOService& io_service, bool multi_threading_enabled,
+ size_t thread_pool_size, bool defer_thread_start) {
+ if (!multi_threading_enabled && thread_pool_size) {
+ isc_throw(InvalidOperation,
+ "HttpClient thread_pool_size must be zero "
+ "when Kea core multi-threading is disabled");
+ }
+
impl_.reset(new HttpClientImpl(io_service, thread_pool_size,
defer_thread_start));
}
/// @brief Constructor.
///
/// @param io_service IO service to be used by the HTTP client.
+ /// @param multi_threading_enabled The flag which indicates if MT is enabled.
/// @param thread_pool_size maximum number of threads in the thread pool.
/// A value greater than zero enables multi-threaded mode and sets the
/// maximum number of concurrent connections per URL. A value of zero
/// the thread pool threads will be created and started, with the
/// operational state being RUNNING. Applicable only when thread-pool size
/// is greater than zero.
- explicit HttpClient(asiolink::IOService& io_service, size_t thread_pool_size = 0,
+ explicit HttpClient(asiolink::IOService& io_service,
+ bool multi_threading_enabled,
+ size_t thread_pool_size = 0,
bool defer_thread_start = false);
/// @brief Destructor.
}
// Create an MT client with num_threads
- ASSERT_NO_THROW_LOG(client_.reset(new HttpClient(io_service_, num_threads, true)));
+ ASSERT_NO_THROW_LOG(client_.reset(new HttpClient(io_service_,
+ num_threads ? true : false,
+ num_threads, true)));
ASSERT_TRUE(client_);
if (num_threads_ == 0) {
}
// Create an instant start, MT client with num_threads
- ASSERT_NO_THROW_LOG(client_.reset(new HttpClient(io_service_, num_threads, true)));
+ ASSERT_NO_THROW_LOG(client_.reset(new HttpClient(io_service_, true, num_threads, true)));
ASSERT_TRUE(client_);
// Start the requisite number of requests:
// Verifies we can construct and destruct, in both single
// and multi-threaded modes.
TEST_F(MultiThreadingHttpClientTest, basics) {
- MultiThreadingMgr::instance().setMode(false);
HttpClientPtr client;
// Value of 0 for thread_pool_size means single-threaded.
- ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, 0)));
+ ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, false)));
ASSERT_TRUE(client);
ASSERT_FALSE(client->getThreadIOService());
// Make sure destruction doesn't throw.
ASSERT_NO_THROW_LOG(client.reset());
- // Enable Kea core multi-threading.
- MultiThreadingMgr::instance().setMode(true);
+ // Non-zero thread-pool-size means multi-threaded mode, should throw.
+ ASSERT_THROW_MSG(client.reset(new HttpClient(io_service_, false, 1)), InvalidOperation,
+ "HttpClient thread_pool_size must be zero "
+ "when Kea core multi-threading is disabled");
+ ASSERT_FALSE(client);
// Multi-threaded construction should work now.
- ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, 3)));
+ ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, true, 3)));
ASSERT_TRUE(client);
// Verify that it has an internal IOService and that thread pool size
ASSERT_NO_THROW_LOG(client.reset());
// Create another multi-threaded instance.
- ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, 3)));
+ ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, true, 3)));
// Make sure destruction doesn't throw.
ASSERT_NO_THROW_LOG(client.reset());
// Verifies we can construct with deferred start.
TEST_F(MultiThreadingHttpClientTest, deferredStart) {
- MultiThreadingMgr::instance().setMode(true);
HttpClientPtr client;
size_t thread_pool_size = 3;
// Create MT client with deferred start.
- ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, thread_pool_size, true)));
+ ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, true, thread_pool_size, true)));
ASSERT_TRUE(client);
// Client should be STOPPED, with no threads.
// Verifies we can restart after stop.
TEST_F(MultiThreadingHttpClientTest, restartAfterStop) {
- MultiThreadingMgr::instance().setMode(true);
HttpClientPtr client;
size_t thread_pool_size = 3;
// Create MT client with instant start.
- ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, thread_pool_size)));
+ ASSERT_NO_THROW_LOG(client.reset(new HttpClient(io_service_, true, thread_pool_size)));
ASSERT_TRUE(client);
// Verify we're started.
ASSERT_NO_THROW(listener_.start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
ASSERT_NO_THROW(listener2_.start());
// Create the client. It will be communicating with the two servers.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URLs on which the servers are available.
Url url1("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL on which the server is available.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener3_.start());
// Create the client that will communicate with this server.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of this server.
Url url("http://127.0.0.1:18125");
/// server is unreachable.
void testUnreachable () {
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server. This server is down.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_.start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
ASSERT_NO_THROW(listener_.start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
ASSERT_NO_THROW(listener_->start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
ASSERT_NO_THROW(listener2_->start());
// Create the client. It will be communicating with the two servers.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URLs on which the servers are available.
Url url1("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Create a second client context.
TlsContextPtr client_context2;
ASSERT_NO_THROW(listener3_->start());
// Create the client that will communicate with this server.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of this server.
Url url("http://127.0.0.1:18125");
/// server is unreachable.
void testUnreachable () {
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server. This server is down.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create the client.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
// Specify the URL of the server.
Url url("http://127.0.0.1:18123");
ASSERT_NO_THROW(listener_->start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
ASSERT_NO_THROW(listener_->start());
// Create a client and specify the URL on which the server can be reached.
- HttpClient client(io_service_);
+ HttpClient client(io_service_, false);
Url url("http://127.0.0.1:18123");
// Initiate request to the server.
.arg(port_)
.arg(tls_context_ ? "true" : "false");
} catch (const std::exception& ex) {
+ thread_io_service_.reset();
+ tcp_listener_.reset();
+ thread_pool_.reset();
isc_throw(Unexpected, "MtTcpListenerMgr::start failed:" << ex.what());
}
}