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.
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.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:241
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:286
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static boost::shared_ptr< CalloutHandle > createCalloutHandle()
Return callout handle.
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
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)
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const isc::log::MessageID COMMAND_PROCESS_ERROR2
const int CONTROL_RESULT_COMMAND_UNSUPPORTED
Status code indicating that the specified command is not supported.
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:26
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
Defines the logger used by the top-level component of kea-lfc.