Kea 2.2.0
base_command_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2022 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
11#include <config/config_log.h>
13#include <hooks/hooks_manager.h>
14#include <functional>
15
16using namespace isc::data;
17using namespace isc::hooks;
18namespace ph = std::placeholders;
19
20namespace {
21
23struct BaseCommandMgrHooks {
24 int hook_index_command_processed_;
25
27 BaseCommandMgrHooks() {
28 hook_index_command_processed_ = HooksManager::registerHook("command_processed");
29 }
30};
31
32// Declare a Hooks object. As this is outside any function or method, it
33// will be instantiated (and the constructor run) when the module is loaded.
34// As a result, the hook indexes will be defined before any method in this
35// module is called.
36BaseCommandMgrHooks Hooks;
37
38}; // anonymous namespace
39
40namespace isc {
41namespace config {
42
44 registerCommand("list-commands", std::bind(&BaseCommandMgr::listCommandsHandler,
45 this, ph::_1, ph::_2));
46}
47
48void
49BaseCommandMgr::registerCommand(const std::string& cmd, CommandHandler handler) {
50 if (!handler) {
51 isc_throw(InvalidCommandHandler, "Specified command handler is NULL");
52 }
53
54 HandlerContainer::const_iterator it = handlers_.find(cmd);
55 if (it != handlers_.end()) {
56 isc_throw(InvalidCommandName, "Handler for command '" << cmd
57 << "' is already installed.");
58 }
59
60 HandlersPair handlers;
61 handlers.handler = handler;
62 handlers_.insert(make_pair(cmd, handlers));
63
65}
66
67void
69 ExtendedCommandHandler handler) {
70 if (!handler) {
71 isc_throw(InvalidCommandHandler, "Specified command handler is NULL");
72 }
73
74 HandlerContainer::const_iterator it = handlers_.find(cmd);
75 if (it != handlers_.end()) {
76 isc_throw(InvalidCommandName, "Handler for command '" << cmd
77 << "' is already installed.");
78 }
79
80 HandlersPair handlers;
81 handlers.extended_handler = handler;
82 handlers_.insert(make_pair(cmd, handlers));
83
85}
86
87void
88BaseCommandMgr::deregisterCommand(const std::string& cmd) {
89 if (cmd == "list-commands") {
91 "Can't uninstall internal command 'list-commands'");
92 }
93
94 HandlerContainer::iterator it = handlers_.find(cmd);
95 if (it == handlers_.end()) {
96 isc_throw(InvalidCommandName, "Handler for command '" << cmd
97 << "' not found.");
98 }
99 handlers_.erase(it);
100
102}
103
104void
106
107 // No need to log anything here. deregisterAll is not used in production
108 // code, just in tests.
109 handlers_.clear();
110 registerCommand("list-commands",
111 std::bind(&BaseCommandMgr::listCommandsHandler, this, ph::_1, ph::_2));
112}
113
116 if (!cmd) {
118 "Command processing failed: NULL command parameter"));
119 }
120
121 try {
122 ConstElementPtr arg;
123 std::string name = parseCommand(arg, cmd);
124
126
127 ConstElementPtr response = handleCommand(name, arg, cmd);
128
129 // If there any callouts for command-processed hook point call them
130 if (HooksManager::calloutsPresent(Hooks.hook_index_command_processed_)) {
131 // Commands are not associated with anything so there's no pre-existing
132 // callout.
133 CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
134
135 // Add the command name, arguments, and response to the callout context
136 callout_handle->setArgument("name", name);
137 callout_handle->setArgument("arguments", arg);
138 callout_handle->setArgument("response", response);
139
140 // Call callouts
141 HooksManager::callCallouts(Hooks.hook_index_command_processed_,
142 *callout_handle);
143
144 // Refresh the response from the callout context in case it was modified.
145 // @todo Should we allow this?
146 callout_handle->getArgument("response", response);
147 }
148
149 return (response);
150
151 } catch (const Exception& e) {
154 std::string("Error during command processing: ")
155 + e.what()));
156 }
157}
158
160BaseCommandMgr::handleCommand(const std::string& cmd_name,
161 const ConstElementPtr& params,
162 const ConstElementPtr& original_cmd) {
163 auto it = handlers_.find(cmd_name);
164 if (it == handlers_.end()) {
165 // Ok, there's no such command.
167 "'" + cmd_name + "' command not supported."));
168 }
169
170 // Call the actual handler and return whatever it returned
171 if (it->second.handler) {
172 return (it->second.handler(cmd_name, params));
173 }
174 return (it->second.extended_handler(cmd_name, params, original_cmd));
175}
176
178BaseCommandMgr::listCommandsHandler(const std::string& /* name */,
180 using namespace isc::data;
181 ElementPtr commands = Element::createList();
182 for (HandlerContainer::const_iterator it = handlers_.begin();
183 it != handlers_.end(); ++it) {
184 commands->add(Element::create(it->first));
185 }
186 return (createAnswer(CONTROL_RESULT_SUCCESS, commands));
187}
188
189
190} // namespace isc::config
191} // namespace isc
CtrlAgentHooks Hooks
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
HandlerContainer handlers_
Container for command handlers.
virtual isc::data::ConstElementPtr processCommand(const isc::data::ConstElementPtr &cmd)
Triggers command processing.
std::function< isc::data::ConstElementPtr(const std::string &name, const isc::data::ConstElementPtr &params)> CommandHandler
Defines command handler type.
void registerCommand(const std::string &cmd, CommandHandler handler)
Registers specified command handler for a given command.
void deregisterAll()
Auxiliary method that removes all installed commands.
void registerExtendedCommand(const std::string &cmd, ExtendedCommandHandler handler)
Registers specified command handler for a given command.
virtual isc::data::ConstElementPtr handleCommand(const std::string &cmd_name, const isc::data::ConstElementPtr &params, const isc::data::ConstElementPtr &original_cmd)
Handles the command having a given name and arguments.
std::function< isc::data::ConstElementPtr(const std::string &name, const isc::data::ConstElementPtr &params, const isc::data::ConstElementPtr &original)> ExtendedCommandHandler
Defines extended command handler type.
void deregisterCommand(const std::string &cmd)
Deregisters specified command handler.
Exception indicating that the handler specified is not valid.
Exception indicating that the command name is not valid.
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.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const isc::log::MessageID COMMAND_EXTENDED_REGISTERED
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
const isc::log::MessageID COMMAND_DEREGISTERED
const isc::log::MessageID COMMAND_RECEIVED
std::string parseCommand(ConstElementPtr &arg, ConstElementPtr command)
const isc::log::MessageID COMMAND_PROCESS_ERROR2
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
const isc::log::MessageID COMMAND_REGISTERED
const int DBG_COMMAND
Definition: config_log.h:24
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
isc::log::Logger command_logger("commands")
Command processing Logger.
Definition: config_log.h:21
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
Defines the logger used by the top-level component of kea-lfc.