HttpCommandMgrImpl()
: io_service_(), timeout_(TIMEOUT_AGENT_RECEIVE_COMMAND),
idle_timeout_(TIMEOUT_AGENT_IDLE_CONNECTION_TIMEOUT),
- current_config_(), http_listeners_(), active_(0) {
+ current_config_(), http_listeners_(), active_(0),
+ use_external_(true) {
}
/// @brief Configure control socket from configuration.
/// @brief Number of active listeners (0 or 1).
size_t active_;
+
+ /// @brief Use external sockets flag.
+ bool use_external_;
};
void
config->getCertRequired());
use_https = true;
}
+
// Create response creator factory first. It will be used to
// generate response creators. Each response creator will be used
// to generate answer to specific request.
HttpResponseCreatorFactoryPtr rfc(new HttpCommandResponseCreatorFactory(config));
+
// Create HTTP listener. It will open up a TCP socket and be
// prepared to accept incoming connection.
HttpListenerPtr http_listener
rfc,
HttpListener::RequestTimeout(timeout_),
HttpListener::IdleTimeout(idle_timeout_)));
+
+ // Pass the use external socket flag.
+ http_listener->addExternalSockets(use_external_);
+
// Instruct the HTTP listener to actually open socket, install
// callback and start listening.
http_listener->start();
impl_->idle_timeout_ = timeout;
}
+void
+HttpCommandMgr::addExternalSockets(bool use_external) {
+ impl_->use_external_ = use_external;
+}
+
void
HttpCommandMgr::configure(HttpCommandConfigPtr config) {
impl_->configure(config);
#include <cc/command_interpreter.h>
#include <config/http_command_mgr.h>
#include <config/command_mgr.h>
+#include <dhcp/iface_mgr.h>
#include <http/response.h>
#include <http/response_parser.h>
#include <http/testutils/test_http_client.h>
}
test_timer_.cancel();
resetState();
+ IfaceMgr::instance().deleteAllExternalSockets();
}
/// @brief Resets state.
io_service_->stopAndPoll();
HttpCommandMgr::instance().setIOService(IOServicePtr());
}
+ HttpCommandMgr::instance().addExternalSockets(true);
}
/// @brief Constructs a complete HTTP POST given a request body.
/// Verifies the configure and close of HttpCommandMgr.
TEST_F(HttpCommandMgrTest, basic) {
- // Make sure we can confiugure one.
+ // Make sure we can configure one.
ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
auto listener = HttpCommandMgr::instance().getHttpListener();
ASSERT_TRUE(listener);
EXPECT_FALSE(HttpCommandMgr::instance().getHttpListener());
}
+/// Verifies the use external socket flag of HttpCommandMgr.
+TEST_F(HttpCommandMgrTest, useExternal) {
+ // Default is to use external sockets.
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
+ auto listener = HttpCommandMgr::instance().getHttpListener();
+ ASSERT_TRUE(listener);
+ int fd = listener->getNative();
+ EXPECT_NE(-1, fd);
+ EXPECT_TRUE(IfaceMgr::instance().isExternalSocket(fd));
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().close());
+
+ // Change to no external sockets.
+ HttpCommandMgr::instance().addExternalSockets(false);
+
+ // Retry: now the listener is not added as an external socket
+ // to the interface manager.
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
+ listener = HttpCommandMgr::instance().getHttpListener();
+ ASSERT_TRUE(listener);
+ fd = listener->getNative();
+ EXPECT_NE(-1, fd);
+ EXPECT_FALSE(IfaceMgr::instance().isExternalSocket(fd));
+}
+
/// Verifies the configure and close of HttpCommandMgr with TLS.
TEST_F(HttpCommandMgrTest, basicTls) {
string ca_dir(string(TEST_CA_DIR));
EXPECT_FALSE(HttpCommandMgr::instance().getHttpListener());
}
+/// Verifies the use external socket flag of HttpCommandMgr with TLS.
+TEST_F(HttpCommandMgrTest, useExternalTls) {
+ string ca_dir(string(TEST_CA_DIR));
+ // Setup TLS for the manager.
+ http_config_->setSocketType("https");
+ http_config_->setTrustAnchor(ca_dir + string("/kea-ca.crt"));
+ http_config_->setCertFile(ca_dir + string("/kea-server.crt"));
+ http_config_->setKeyFile(ca_dir + string("/kea-server.key"));
+
+ // Default is to use external sockets.
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
+ auto listener = HttpCommandMgr::instance().getHttpListener();
+ ASSERT_TRUE(listener);
+ int fd = listener->getNative();
+ EXPECT_NE(-1, fd);
+ EXPECT_TRUE(IfaceMgr::instance().isExternalSocket(fd));
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().close());
+
+ // Change to no external sockets.
+ HttpCommandMgr::instance().addExternalSockets(false);
+
+ // Retry: now the listener is not added as an external socket
+ // to the interface manager.
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
+ listener = HttpCommandMgr::instance().getHttpListener();
+ ASSERT_TRUE(listener);
+ fd = listener->getNative();
+ EXPECT_NE(-1, fd);
+ EXPECT_FALSE(IfaceMgr::instance().isExternalSocket(fd));
+}
+
// This test verifies that an HTTP connection can be established and used to
// transmit an HTTP request and receive the response.
TEST_F(HttpCommandMgrTest, command) {
EXPECT_EQ(hr->getBody(), "[ { \"arguments\": [ \"bar\" ], \"result\": 0 } ]");
}
+// This test verifies that an HTTP connection can be established and used to
+// transmit an HTTP request and receive the response (no external sockets).
+TEST_F(HttpCommandMgrTest, commandNoExternal) {
+ // Change to no external sockets.
+ HttpCommandMgr::instance().addExternalSockets(false);
+
+ // Configure.
+ ASSERT_NO_THROW_LOG(HttpCommandMgr::instance().configure(http_config_));
+ EXPECT_TRUE(HttpCommandMgr::instance().getHttpListener());
+
+ // Now let's send a "foo" command. This should create a client, connect
+ // to our listener, post our request and retrieve our reply.
+ ASSERT_NO_THROW(startRequest("{\"command\": \"foo\"}"));
+ ASSERT_TRUE(client_);
+ ASSERT_NO_THROW(runIOService());
+ ASSERT_TRUE(client_);
+
+ // Parse the response into an HttpResponse.
+ HttpResponsePtr hr;
+ ASSERT_NO_THROW_LOG(hr = parseResponse(client_->getResponse()));
+
+ // We should have a response from our command handler.
+ EXPECT_EQ(hr->getBody(), "[ { \"arguments\": [ \"bar\" ], \"result\": 0 } ]");
+}
+
} // end of anonymous namespace
}
tls_acceptor->asyncAccept(*tls_socket_, cb);
}
- if (use_external_) {
- auto& iface_mgr = IfaceMgr::instance ();
- if (tcp_socket_) {
- iface_mgr.addExternalSocket(tcp_socket_->getNative(), 0);
- }
- if (tls_socket_) {
- iface_mgr.addExternalSocket(tls_socket_->getNative(), 0);
- }
- watch_socket_.reset(new WatchSocket());
- iface_mgr.addExternalSocket(watch_socket_->getSelectFd(), 0);
- }
} catch (const std::exception& ex) {
isc_throw(HttpConnectionError, "unable to start accepting TCP "
"connections: " << ex.what());
.arg(static_cast<unsigned>(request_timeout_/1000));
}
+ if (use_external_) {
+ auto& iface_mgr = IfaceMgr::instance ();
+ if (tcp_socket_) {
+ iface_mgr.addExternalSocket(tcp_socket_->getNative(), 0);
+ }
+ if (tls_socket_) {
+ iface_mgr.addExternalSocket(tls_socket_->getNative(), 0);
+ }
+ watch_socket_.reset(new WatchSocket());
+ iface_mgr.addExternalSocket(watch_socket_->getSelectFd(), 0);
+ }
+
setupRequestTimer();
doHandshake();
}