command_mgr.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef COMMAND_MGR_H
  15. #define COMMAND_MGR_H
  16. #include <cc/data.h>
  17. #include <config/command_socket.h>
  18. #include <boost/noncopyable.hpp>
  19. #include <boost/function.hpp>
  20. #include <string>
  21. #include <list>
  22. #include <map>
  23. namespace isc {
  24. namespace config {
  25. /// @brief CommandMgr exception indicating that the handler specified is not valid
  26. class InvalidCommandHandler : public Exception {
  27. public:
  28. InvalidCommandHandler(const char* file, size_t line, const char* what) :
  29. isc::Exception(file, line, what) { };
  30. };
  31. /// @brief CommandMgr exception indicating that the command name is not valid
  32. class InvalidCommandName : public Exception {
  33. public:
  34. InvalidCommandName(const char* file, size_t line, const char* what) :
  35. isc::Exception(file, line, what) { };
  36. };
  37. /// @brief Commands Manager, responsible for processing external commands
  38. ///
  39. /// Commands Manager is a generic interface for handling external commands.
  40. /// Commands can be received over control sockets. Currently unix socket is
  41. /// supported, but additional type (udp, tcp, https etc.) may be added later.
  42. /// The commands and responses are sent in JSON format.
  43. /// See http://kea.isc.org/wiki/StatsDesign for details.
  44. ///
  45. /// In general, the command has the following format:
  46. /// {
  47. /// "command": "statistic-get",
  48. /// "arguments": {
  49. /// "name": "received-packets"
  50. /// }
  51. /// }
  52. ///
  53. /// And the response is:
  54. ///
  55. /// {
  56. /// "result": 0,
  57. /// "observations": {
  58. /// "received-packets": [ [ 1234, "2015-04-15 12:34:45.123" ] ]
  59. /// }
  60. /// }
  61. ///
  62. /// CommandsMgr does not implement the commands (except one, "commands-list")
  63. /// itself, but rather provides an interface (see @ref registerCommand,
  64. /// @ref deregisterCommand, @ref processCommand) for other components to use
  65. /// it. The @ref CommandHandler type is specified in a way to easily use
  66. /// existing command handlers in DHCPv4 and DHCPv6 components.
  67. class CommandMgr : public boost::noncopyable {
  68. public:
  69. /// @brief Defines command handler type
  70. ///
  71. /// Command handlers are expected to use this format.
  72. /// @param name name of the commands
  73. /// @param params parameters specific to the command
  74. /// @return response (created with createAnswer())
  75. typedef boost::function<isc::data::ConstElementPtr (const std::string& name,
  76. const isc::data::ConstElementPtr& params)> CommandHandler;
  77. /// @brief CommandMgr is a singleton class. This method returns reference
  78. /// to its sole instance.
  79. ///
  80. /// @return the only existing instance of the manager
  81. static CommandMgr& instance();
  82. /// @brief Opens control socket with paramters specified in socket_info
  83. ///
  84. /// Currently supported types are:
  85. /// - unix (required parameters: socket-type: unix, socket-name:/unix/path)
  86. ///
  87. /// This method will close previously open command socket (if exists).
  88. ///
  89. /// @throw CommandSocketError if socket creation fails.
  90. /// @throw SocketError if command socket is already open.
  91. ///
  92. /// @param socket_info describes control socket parameters
  93. /// @return object representing a socket
  94. CommandSocketPtr
  95. openCommandSocket(const isc::data::ConstElementPtr& socket_info);
  96. /// @brief Shuts down any open control sockets
  97. void closeCommandSocket();
  98. /// @brief Registers specified command handler for a given command
  99. ///
  100. /// @param cmd name of the command to be handled
  101. /// @param handler pointer to the method that will handle the command
  102. void registerCommand(const std::string& cmd, CommandHandler handler);
  103. /// @brief Deregisters specified command handler
  104. ///
  105. /// @param cmd name of the command that's no longer handled
  106. void deregisterCommand(const std::string& cmd);
  107. /// @brief Triggers command processing
  108. ///
  109. /// This method processes specified command. The command is specified using
  110. /// a single Element. See @ref CommandMgr for description of its syntax.
  111. /// Typically, this method is called internally, when there's a new data
  112. /// received over control socket. However, in some cases (e.g. signal received)
  113. /// it may be called by external code explicitly. Hence this method is public.
  114. isc::data::ConstElementPtr processCommand(const isc::data::ConstElementPtr& cmd);
  115. /// @brief Reads data from a socket, parses as JSON command and processes it
  116. ///
  117. /// This method is used to handle traffic on connected socket. This callback
  118. /// is installed by the @ref connectionAcceptor once the incoming connection
  119. /// is accepted. If end-of-file is detected, this method will close the socket
  120. /// and will uninstall itself from @ref isc::dhcp::IfaceMgr.
  121. ///
  122. /// @param sockfd socket descriptor of a connected socket
  123. static void commandReader(int sockfd);
  124. /// @brief Auxiliary method that removes all installed commands.
  125. ///
  126. /// The only unwipeable method is list-commands, which is internally
  127. /// handled at all times.
  128. void deregisterAll();
  129. /// @brief Adds an information about opened connection socket
  130. ///
  131. /// @param conn Connection socket to be stored
  132. void addConnection(const CommandSocketPtr& conn);
  133. /// @brief Closes connection with a specific socket descriptor
  134. ///
  135. /// @param fd socket descriptor
  136. /// @return true if closed successfully, false if not found
  137. bool closeConnection(int fd);
  138. /// @brief Returns control socket descriptor
  139. ///
  140. /// This method should be used only in tests.
  141. int getControlSocketFD() const {
  142. return (socket_->getFD());
  143. }
  144. private:
  145. /// @brief Private constructor
  146. ///
  147. /// Registers internal 'list-commands' command.
  148. CommandMgr();
  149. /// @brief 'list-commands' command handler
  150. ///
  151. /// This method implements command 'list-commands'. It returns a list of all
  152. /// currently supported commands.
  153. /// @param name name of the command (should always be 'list-commands')
  154. /// @param params additional parameters (ignored)
  155. /// @return structure that includes all currently supported commands
  156. isc::data::ConstElementPtr
  157. listCommandsHandler(const std::string& name,
  158. const isc::data::ConstElementPtr& params);
  159. typedef std::map<std::string, CommandHandler> HandlerContainer;
  160. /// @brief Container for command handlers
  161. HandlerContainer handlers_;
  162. /// @brief Control socket structure
  163. ///
  164. /// This is the socket that accepts incoming connections. There can be at
  165. /// most one (if command channel is configured).
  166. CommandSocketPtr socket_;
  167. /// @brief Sockets for open connections
  168. ///
  169. /// These are the sockets that are dedicated to handle a specific connection.
  170. /// Their number is equal to number of current control connections.
  171. std::list<CommandSocketPtr> connections_;
  172. };
  173. }; // end of isc::config namespace
  174. }; // end of isc namespace
  175. #endif