Kea: http_command_mgr.cc Source File

| Kea 3.2.0-git

http_command_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2024-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <asiolink/asio_wrapper.h>
10#include <config/command_mgr.h>
11#include <config/config_log.h>
12#include <config/http_command_mgr.h>
13#include <config/http_command_response_creator_factory.h>
14#include <config/http_command_response_creator.h>
15#include <config/timeouts.h>
16#include <sstream>
17#include <vector>
18
19using namespace isc;
20using namespace isc::asiolink;
21using namespace isc::config;
22using namespace isc::data;
23using namespace isc::dhcp;
24using namespace isc::http;
25using namespace std;
26
27namespace isc {
28namespace config {
29
31 class HttpCommandMgrImpl {
32public:
33
35 HttpCommandMgrImpl()
36 : io_service_(), timeout_(TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND),
37 idle_timeout_(TIMEOUT_DHCP_SERVER_IDLE_CONNECTION_TIMEOUT),
38 use_external_(true) {
39 }
40
44 void openCommandSockets(const isc::data::ConstElementPtr config);
45
52 void openCommandSocket(const isc::data::ConstElementPtr config);
53
58 void closeCommandSocket(HttpSocketInfoPtr info, bool remove);
59
63 void closeCommandSockets(bool remove = true);
64
71 ConstHttpListenerPtr getHttpListener(HttpSocketInfoPtr info) const;
72
74 IOServicePtr io_service_;
75
77 long timeout_;
78
80 long idle_timeout_;
81
83 std::map<std::pair<IOAddress, uint16_t>, HttpSocketInfoPtr> sockets_;
84
86 bool use_external_;
87};
88
89void
90HttpCommandMgrImpl::openCommandSockets(const isc::data::ConstElementPtr config) {
91 if (!config) {
92 isc_throw(BadSocketInfo, "Missing config parameters, can't create socket.");
93 }
94
95 if (config->getType() != Element::list) {
96 isc_throw(DhcpConfigError, "expected list type ("
97 << config->getPosition() << ")");
98 }
99
100 for (auto const& socket : config->listValue()) {
101 openCommandSocket(socket);
102 }
103
104 auto copy = sockets_;
105 for (auto const& data : copy) {
106 if (data.second->usable_) {
107 // If the connection can be used (just created) or reused, keep it
108 // in the list and clear the flag. It will be marked again on next
109 // configuration event if needed.
110 data.second->usable_ = false;
111 } else {
112 // If the connection can not be reused, stop it and remove it from the list.
113 closeCommandSocket(data.second, true);
114 }
115 }
116}
117
118void
119HttpCommandMgrImpl::openCommandSocket(const isc::data::ConstElementPtr config) {
120 if (!config) {
121 isc_throw(BadSocketInfo, "Missing config parameters, can't create socket.");
122 }
123
124 HttpCommandConfigPtr cmd_config(new HttpCommandConfig(config));
125
126 IOAddress server_address = cmd_config->getSocketAddress();
127 uint16_t server_port = cmd_config->getSocketPort();
128
129 // Search for the specific connection and reuse the existing one if found.
130 auto it = sockets_.find(std::make_pair(server_address, server_port));
131 if (it != sockets_.end()) {
132 auto listener = it->second->listener_;
133 if (listener) {
134 // Reconfig keeping the same address and port.
135 if (listener->getTlsContext()) {
136 if (cmd_config->getTrustAnchor().empty()) {
137 // Can not switch from HTTPS to HTTP
138 LOG_ERROR(command_logger, HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSE_FAILED)
139 .arg(server_address.toText())
140 .arg(server_port);
141 isc_throw(BadValue,
142 "Can not switch from HTTPS to HTTP sockets using the same address and port.");
143 } else {
144 // Apply TLS settings each time.
145 TlsContextPtr tls_context;
146 TlsContext::configure(tls_context,
147 TlsRole::SERVER,
148 cmd_config->getTrustAnchor(),
149 cmd_config->getCertFile(),
150 cmd_config->getKeyFile(),
151 cmd_config->getCertRequired());
152 // Overwrite the authentication setup and the http headers
153 // in the response creator config.
154 it->second->config_->setAuthConfig(cmd_config->getAuthConfig());
155 it->second->config_->setHttpHeaders(cmd_config->getHttpHeaders());
156 listener->setTlsContext(tls_context);
157 LOG_INFO(command_logger, HTTP_COMMAND_MGR_HTTPS_SERVICE_UPDATED)
158 .arg(server_address.toText())
159 .arg(server_port);
160 }
161 } else {
162 if (!cmd_config->getTrustAnchor().empty()) {
163 // Can not switch from HTTP to HTTPS
164 LOG_ERROR(command_logger, HTTP_COMMAND_MGR_HTTP_SERVICE_REUSE_FAILED)
165 .arg(server_address.toText())
166 .arg(server_port);
167 isc_throw(BadValue,
168 "Can not switch from HTTP to HTTPS sockets using the same address and port.");
169 } else {
170 // Overwrite the authentication setup and the http headers
171 // in the response creator config.
172 it->second->config_->setAuthConfig(cmd_config->getAuthConfig());
173 it->second->config_->setHttpHeaders(cmd_config->getHttpHeaders());
174 LOG_INFO(command_logger, HTTP_COMMAND_MGR_HTTP_SERVICE_UPDATED)
175 .arg(server_address.toText())
176 .arg(server_port);
177 }
178 }
179 }
180 // If the connection can be reused, mark it as usable.
181 it->second->usable_ = true;
182 return;
183 }
184
185 // Connection not found so it needs to be created.
186 // When TLS is enabled configure it.
187 bool use_https = false;
188 TlsContextPtr tls_context;
189 if (!cmd_config->getCertFile().empty()) {
190 TlsContext::configure(tls_context,
191 TlsRole::SERVER,
192 cmd_config->getTrustAnchor(),
193 cmd_config->getCertFile(),
194 cmd_config->getKeyFile(),
195 cmd_config->getCertRequired());
196 use_https = true;
197 }
198
199 // Create response creator factory first. It will be used to
200 // generate response creators. Each response creator will be used
201 // to generate answer to specific request.
202 HttpResponseCreatorFactoryPtr rfc(new HttpCommandResponseCreatorFactory(cmd_config));
203
204 // Create HTTP listener. It will open up a TCP socket and be
205 // prepared to accept incoming connection.
206 HttpListenerPtr http_listener
207 (new HttpListener(io_service_,
208 server_address,
209 server_port,
210 tls_context,
211 rfc,
212 HttpListener::RequestTimeout(timeout_),
213 HttpListener::IdleTimeout(idle_timeout_)));
214
215 // Pass the use external socket flag.
216 http_listener->addExternalSockets(use_external_);
217
218 // Instruct the HTTP listener to actually open socket, install
219 // callback and start listening.
220 http_listener->start();
221
222 HttpSocketInfoPtr socket_info(new HttpSocketInfo());
223 socket_info->config_ = cmd_config;
224 socket_info->listener_ = http_listener;
225
226 sockets_[std::make_pair(server_address, server_port)] = socket_info;
227
228 // Ok, seems we're good to go.
229 LOG_INFO(command_logger, HTTP_COMMAND_MGR_SERVICE_STARTED)
230 .arg(use_https ? "HTTPS" : "HTTP")
231 .arg(server_address.toText())
232 .arg(server_port);
233}
234
235void
236HttpCommandMgrImpl::closeCommandSocket(HttpSocketInfoPtr info, bool remove) {
237 bool use_https = false;
238 if (info) {
239 ostringstream ep;
240 use_https = !info->config_->getCertFile().empty();
241 ep << "bound to address " << info->config_->getSocketAddress()
242 << " port " << info->config_->getSocketPort();
243
244 LOG_INFO(command_logger, HTTP_COMMAND_MGR_SERVICE_STOPPING)
245 .arg(use_https ? "HTTPS" : "HTTP")
246 .arg(ep.str());
247 info->listener_->stop();
248 if (remove) {
249 auto it = sockets_.find(std::make_pair(info->config_->getSocketAddress(), info->config_->getSocketPort()));
250 if (it != sockets_.end()) {
251 sockets_.erase(it);
252 }
253 }
254 // We have stopped listeners but there may be some pending handlers
255 // related to these listeners. Need to invoke these handlers.
256 try {
257 io_service_->pollOne();
258 } catch (...) {
259 }
260 } else {
261 closeCommandSockets(remove);
262 }
263}
264
265void
266HttpCommandMgrImpl::closeCommandSockets(bool remove) {
267 auto copy = sockets_;
268 for (auto const& data : copy) {
269 closeCommandSocket(data.second, remove);
270 }
271}
272
273 ConstHttpListenerPtr
274HttpCommandMgrImpl::getHttpListener(HttpSocketInfoPtr info) const {
275 // Return the most recent listener or null.
276 if (info) {
277 auto it = sockets_.find(std::make_pair(info->config_->getSocketAddress(), info->config_->getSocketPort()));
278 if (it != sockets_.end()) {
279 return (it->second->listener_);
280 }
281 } else if (sockets_.size()) {
282 return (sockets_.begin()->second->listener_);
283 }
284 return (ConstHttpListenerPtr());
285}
286
287 HttpCommandMgr&
288HttpCommandMgr::instance() {
289 static HttpCommandMgr http_cmd_mgr;
290 return (http_cmd_mgr);
291}
292
293HttpCommandMgr::HttpCommandMgr() : impl_(new HttpCommandMgrImpl()) {
294}
295
296void
297HttpCommandMgr::setIOService(const IOServicePtr& io_service) {
298 impl_->io_service_ = io_service;
299}
300
301void
302HttpCommandMgr::setConnectionTimeout(const long timeout) {
303 impl_->timeout_ = timeout;
304}
305
306void
307HttpCommandMgr::setIdleConnectionTimeout(const long timeout) {
308 impl_->idle_timeout_ = timeout;
309}
310
311void
312HttpCommandMgr::addExternalSockets(bool use_external) {
313 impl_->use_external_ = use_external;
314}
315
316void
317HttpCommandMgr::openCommandSocket(const isc::data::ConstElementPtr config) {
318 impl_->openCommandSocket(config);
319}
320
321void
322HttpCommandMgr::openCommandSockets(const isc::data::ConstElementPtr config) {
323 impl_->openCommandSockets(config);
324}
325
326void
327HttpCommandMgr::closeCommandSocket(HttpSocketInfoPtr info, bool remove) {
328 impl_->closeCommandSocket(info, remove);
329}
330
331void
332HttpCommandMgr::closeCommandSockets() {
333 impl_->closeCommandSockets();
334}
335
336 ConstHttpListenerPtr
337HttpCommandMgr::getHttpListener(HttpSocketInfoPtr info) const {
338 return (impl_->getHttpListener(info));
339}
340
341} // end of isc::config
342} // end of isc
asio_wrapper.h
Element::list
@ list
Definition data.h:159
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::asiolink::IOAddress
The IOAddress class represents an IP addresses (version agnostic).
Definition io_address.h:53
isc::asiolink::IOAddress::toText
std::string toText() const
Convert the address to a string.
Definition io_address.cc:60
isc::config::BadSocketInfo
An exception indicating that specified socket parameters are invalid.
Definition command_mgr.h:17
isc::config::HttpCommandConfig
HTTP command config aka HTTP control socket info class.
Definition http_command_config.h:22
isc::config::HttpCommandMgrImpl
Implementation of the HttpCommandMgr.
Definition http_command_mgr.cc:31
isc::config::HttpCommandMgrImpl::use_external_
bool use_external_
Use external sockets flag.
Definition http_command_mgr.cc:86
isc::config::HttpCommandMgrImpl::sockets_
std::map< std::pair< IOAddress, uint16_t >, HttpSocketInfoPtr > sockets_
The HTTP/HTTPS socket data (configuration, listener, etc.).
Definition http_command_mgr.cc:83
isc::config::HttpCommandMgrImpl::openCommandSockets
void openCommandSockets(const isc::data::ConstElementPtr config)
Open http control sockets using configuration.
Definition http_command_mgr.cc:90
isc::config::HttpCommandMgrImpl::idle_timeout_
long idle_timeout_
Idle connection timeout.
Definition http_command_mgr.cc:80
isc::config::HttpCommandMgrImpl::io_service_
IOServicePtr io_service_
Pointer to the IO service.
Definition http_command_mgr.cc:74
isc::config::HttpCommandMgrImpl::closeCommandSockets
void closeCommandSockets(bool remove=true)
Close control socket.
Definition http_command_mgr.cc:266
isc::config::HttpCommandMgrImpl::HttpCommandMgrImpl
HttpCommandMgrImpl()
Constructor.
Definition http_command_mgr.cc:35
isc::config::HttpCommandMgrImpl::closeCommandSocket
void closeCommandSocket(HttpSocketInfoPtr info, bool remove)
Close control socket.
Definition http_command_mgr.cc:236
isc::config::HttpCommandMgrImpl::openCommandSocket
void openCommandSocket(const isc::data::ConstElementPtr config)
Open http control socket using configuration.
Definition http_command_mgr.cc:119
isc::config::HttpCommandMgrImpl::timeout_
long timeout_
Connection timeout.
Definition http_command_mgr.cc:77
isc::config::HttpCommandMgrImpl::getHttpListener
ConstHttpListenerPtr getHttpListener(HttpSocketInfoPtr info) const
Returns a const pointer to the HTTP listener.
Definition http_command_mgr.cc:274
isc::config::HttpCommandMgr
HTTP Commands Manager implementation for the Kea servers.
Definition http_command_mgr.h:23
isc::config::HttpCommandMgr::openCommandSocket
void openCommandSocket(const isc::data::ConstElementPtr config)
Open http control socket using configuration.
Definition http_command_mgr.cc:317
isc::config::HttpCommandMgr::setIdleConnectionTimeout
void setIdleConnectionTimeout(const long timeout)
Override default idle connection timeout.
Definition http_command_mgr.cc:307
isc::config::HttpCommandMgr::getHttpListener
isc::http::ConstHttpListenerPtr getHttpListener(HttpSocketInfoPtr info=HttpSocketInfoPtr()) const
Returns a const pointer to the HTTP listener.
Definition http_command_mgr.cc:337
isc::config::HttpCommandMgr::closeCommandSockets
void closeCommandSockets()
Close http control sockets.
Definition http_command_mgr.cc:332
isc::config::HttpCommandMgr::setConnectionTimeout
void setConnectionTimeout(const long timeout)
Override default connection timeout.
Definition http_command_mgr.cc:302
isc::config::HttpCommandMgr::addExternalSockets
void addExternalSockets(bool use_external=true)
Use external sockets flag.
Definition http_command_mgr.cc:312
isc::config::HttpCommandMgr::instance
static HttpCommandMgr & instance()
HttpCommandMgr is a singleton class.
Definition http_command_mgr.cc:288
isc::config::HttpCommandMgr::setIOService
void setIOService(const asiolink::IOServicePtr &io_service)
Sets IO service to be used by the http command manager.
Definition http_command_mgr.cc:297
isc::config::HttpCommandMgr::openCommandSockets
void openCommandSockets(const isc::data::ConstElementPtr config)
Open http control sockets using configuration.
Definition http_command_mgr.cc:322
isc::config::HttpCommandMgr::closeCommandSocket
void closeCommandSocket(HttpSocketInfoPtr info=HttpSocketInfoPtr(), bool remove=true)
Close http control socket.
Definition http_command_mgr.cc:327
isc::config::HttpCommandResponseCreatorFactory
HTTP response creator factory for HTTP control socket.
Definition http_command_response_creator_factory.h:27
isc::dhcp::DhcpConfigError
To be removed. Please use ConfigError instead.
Definition dhcp_config_error.h:58
isc::http::HttpListener
HTTP listener.
Definition listener.h:52
command_mgr.h
config_log.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
http_command_mgr.h
http_command_response_creator.h
http_command_response_creator_factory.h
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
isc::asiolink
Definition addr_utilities.cc:170
isc::asiolink::TlsContextPtr
boost::shared_ptr< TlsContext > TlsContextPtr
The type of shared pointers to TlsContext objects.
Definition common_tls.h:37
isc::asiolink::IOServicePtr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
Definition io_service.h:35
isc::asiolink::SERVER
@ SERVER
Definition common_tls.h:31
isc::config
Definition command_interpreter.cc:23
isc::config::HTTP_COMMAND_MGR_HTTPS_SERVICE_UPDATED
const isc::log::MessageID HTTP_COMMAND_MGR_HTTPS_SERVICE_UPDATED
Definition config_messages.h:42
isc::config::HTTP_COMMAND_MGR_SERVICE_STARTED
const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STARTED
Definition config_messages.h:45
isc::config::HttpSocketInfoPtr
boost::shared_ptr< HttpSocketInfo > HttpSocketInfoPtr
Pointer to a HttpSocketInfo object.
Definition http_command_config.h:249
isc::config::HTTP_COMMAND_MGR_SERVICE_STOPPING
const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STOPPING
Definition config_messages.h:46
isc::config::TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND
constexpr long TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND
Timeout for the DHCP server to receive command over the unix domain socket.
Definition timeouts.h:17
isc::config::HTTP_COMMAND_MGR_HTTP_SERVICE_REUSE_FAILED
const isc::log::MessageID HTTP_COMMAND_MGR_HTTP_SERVICE_REUSE_FAILED
Definition config_messages.h:43
isc::config::HTTP_COMMAND_MGR_HTTP_SERVICE_UPDATED
const isc::log::MessageID HTTP_COMMAND_MGR_HTTP_SERVICE_UPDATED
Definition config_messages.h:44
isc::config::HttpCommandConfigPtr
boost::shared_ptr< HttpCommandConfig > HttpCommandConfigPtr
Pointer to a HttpCommandConfig object.
Definition http_command_config.h:226
isc::config::command_logger
isc::log::Logger command_logger("commands")
Command processing Logger.
Definition config_log.h:21
isc::config::HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSE_FAILED
const isc::log::MessageID HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSE_FAILED
Definition config_messages.h:41
isc::config::TIMEOUT_DHCP_SERVER_IDLE_CONNECTION_TIMEOUT
constexpr long TIMEOUT_DHCP_SERVER_IDLE_CONNECTION_TIMEOUT
Timeout for the idle connection to be closed.
Definition timeouts.h:20
isc::data
Definition base_stamped_element.cc:12
isc::data::copy
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1522
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::db::info
@ info
Definition db_log.h:126
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::http
Definition auth_config.h:19
isc::http::ConstHttpListenerPtr
boost::shared_ptr< const HttpListener > ConstHttpListenerPtr
Pointer to the const HttpListener.
Definition listener.h:159
isc::http::HttpListenerPtr
boost::shared_ptr< HttpListener > HttpListenerPtr
Pointer to the HttpListener.
Definition listener.h:156
isc::http::HttpResponseCreatorFactoryPtr
boost::shared_ptr< HttpResponseCreatorFactory > HttpResponseCreatorFactoryPtr
Pointer to the HttpResponseCreatorFactory.
Definition response_creator_factory.h:54
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
isc::config::HttpSocketInfo
Structure used to store HTTP/HTTPS connection data.
Definition http_command_config.h:230
isc::http::HttpListener::IdleTimeout
Idle connection timeout.
Definition listener.h:67
isc::http::HttpListener::RequestTimeout
HTTP request timeout value.
Definition listener.h:56
timeouts.h