base_command_mgr.h 7.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef BASE_COMMAND_MGR_H
#define BASE_COMMAND_MGR_H

#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <boost/function.hpp>
#include <map>
#include <string>

namespace isc {
namespace config {

/// @brief Exception indicating that the handler specified is not valid
class InvalidCommandHandler : public Exception {
public:
    InvalidCommandHandler(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief Exception indicating that the command name is not valid
class InvalidCommandName : public Exception {
public:
    InvalidCommandName(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief Commands Manager, responsible for processing external commands.
///
/// Commands Manager is a generic interface for handling external commands.
/// Commands are received over control sockets. Derivations of this class
/// provide implementations of the control socket layers, e.g. unix domain
/// sockets, TCP sockets etc. This base class merely provides methods to manage
/// command handling functions, i.e. register commands, deregister commands.
/// It also includes a @ref BaseCommandMgr::processCommand method which
/// uses the command as an input and invokes appropriate handlers.
///
/// The commands and responses are formatted using JSON.
44
/// See http://oldkea.isc.org/wiki/StatsDesign for details.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
///
/// Below is an example of the command using JSON format:
/// @code
/// {
///     "command": "statistic-get",
///     "arguments": {
///         "name": "received-packets"
///     }
/// }
/// @endcode
///
/// And the response is:
///
/// @code
/// {
///     "result": 0,
61
///     "arguments": {
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
///         "received-packets": [ [ 1234, "2015-04-15 12:34:45.123" ] ]
///     }
/// }
/// @endcode
///
/// BaseCommandsMgr does not implement the commands (except one,
/// "list-commands") itself, but rather provides an interface
/// (see @ref registerCommand, @ref deregisterCommand, @ref processCommand)
/// for other components to use it.
class BaseCommandMgr {
public:

    /// @brief Defines command handler type
    ///
    /// Command handlers are expected to use this format.
    ///
    /// @param name name of the commands
    /// @param params parameters specific to the command
    /// @return response (created with createAnswer())
    typedef boost::function<isc::data::ConstElementPtr (const std::string& name,
        const isc::data::ConstElementPtr& params)> CommandHandler;

84 85 86 87 88 89 90 91 92 93 94 95 96 97
    /// @brief Defines extended command handler type.
    ///
    /// This command handler includes third parameter which holds the
    /// entire command control message. The handler can retrieve
    /// additional information from this parameter, e.g. 'service'.
    ///
    /// @param name name of the commands
    /// @param params parameters specific to the command
    /// @param original original control command.
    /// @return response (created with createAnswer())
    typedef boost::function<isc::data::ConstElementPtr (const std::string& name,
        const isc::data::ConstElementPtr& params,
        const isc::data::ConstElementPtr& original)> ExtendedCommandHandler;

98 99
    /// @brief Constructor.
    ///
100
    /// Registers hookpoint "command-processed"
101 102 103 104 105 106 107 108 109 110
    /// Registers "list-commands" command.
    BaseCommandMgr();

    /// @brief Destructor.
    virtual ~BaseCommandMgr() { };

    /// @brief Triggers command processing.
    ///
    /// This method processes specified command. The command is specified using
    /// a single Element. See @ref BaseCommandMgr for description of its syntax.
111 112
    /// After the command has been handled, callouts for the hook point,
    /// "command-processed" will be invoked.
113 114 115
    ///
    /// @param cmd Pointer to the data element representing command in JSON
    /// format.
116
    isc::data::ConstElementPtr
117 118 119 120 121 122 123 124
    processCommand(const isc::data::ConstElementPtr& cmd);

    /// @brief Registers specified command handler for a given command
    ///
    /// @param cmd Name of the command to be handled.
    /// @param handler Pointer to the method that will handle the command.
    void registerCommand(const std::string& cmd, CommandHandler handler);

125 126 127 128 129 130 131 132 133 134 135 136 137
    /// @brief Registers specified command handler for a given command.
    ///
    /// This variant of the method uses extended command handler which, besides
    /// command name and arguments, also has a third parameter 'original_cmd'
    /// in its signature. Such handlers can retrieve additional parameters from
    /// the command, e.g. 'service' indicating where the command should be
    /// routed.
    ///
    /// @param cmd Name of the command to be handled.
    /// @param handler Pointer to the method that will handle the command.
    void registerExtendedCommand(const std::string& cmd,
                                 ExtendedCommandHandler handler);

138 139 140
    /// @brief Deregisters specified command handler.
    ///
    /// @param cmd Name of the command that's no longer handled.
141
    void deregisterCommand(const std::string& cmd);
142 143 144 145 146

    /// @brief Auxiliary method that removes all installed commands.
    ///
    /// The only unwipeable method is list-commands, which is internally
    /// handled at all times.
147
    void deregisterAll();
148 149 150

protected:

151 152
    /// @brief Handles the command having a given name and arguments.
    ///
153
    /// This method can be overridden in the derived classes to provide
154
    /// custom logic for processing commands. For example, the
155
    /// @ref HookedCommandMgr extends this method to delegate commands
156 157 158 159
    /// processing to a hook library.
    ///
    /// @param cmd_name Command name.
    /// @param params Command arguments.
160 161 162
    /// @param original_cmd Pointer to the entire command received. It may
    /// be sometimes useful to retrieve additional parameters from this
    /// command.
163 164 165 166 167
    ///
    /// @return Pointer to the const data element representing response
    /// to a command.
    virtual isc::data::ConstElementPtr
    handleCommand(const std::string& cmd_name,
168 169 170 171 172 173 174
                  const isc::data::ConstElementPtr& params,
                  const isc::data::ConstElementPtr& original_cmd);

    struct HandlersPair {
        CommandHandler handler;
        ExtendedCommandHandler extended_handler;
    };
175

176
    /// @brief Type of the container for command handlers.
177
    typedef std::map<std::string, HandlersPair> HandlerContainer;
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

    /// @brief Container for command handlers.
    HandlerContainer handlers_;

private:

    /// @brief 'list-commands' command handler.
    ///
    /// This method implements command 'list-commands'. It returns a list of all
    /// currently supported commands.
    ///
    /// @param name Name of the command (should always be 'list-commands').
    /// @param params Additional parameters (ignored).
    ///
    /// @return Pointer to the structure that includes all currently supported
    /// commands.
    isc::data::ConstElementPtr
    listCommandsHandler(const std::string& name,
                        const isc::data::ConstElementPtr& params);
};

} // end of namespace isc::config
} // end of namespace isc

#endif