command_mgr.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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, "list-commands")
  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 @c isc::config::UnixCommandSocket::receiveHandler
  119. /// (located in the src/lib/config/command_socket_factory.cc)
  120. /// once the incoming connection is accepted. If end-of-file is detected, this
  121. /// method will close the socket and will uninstall itself from
  122. /// @ref isc::dhcp::IfaceMgr.
  123. ///
  124. /// @param sockfd socket descriptor of a connected socket
  125. static void commandReader(int sockfd);
  126. /// @brief Auxiliary method that removes all installed commands.
  127. ///
  128. /// The only unwipeable method is list-commands, which is internally
  129. /// handled at all times.
  130. void deregisterAll();
  131. /// @brief Adds an information about opened connection socket
  132. ///
  133. /// @param conn Connection socket to be stored
  134. void addConnection(const CommandSocketPtr& conn);
  135. /// @brief Closes connection with a specific socket descriptor
  136. ///
  137. /// @param fd socket descriptor
  138. /// @return true if closed successfully, false if not found
  139. bool closeConnection(int fd);
  140. /// @brief Returns control socket descriptor
  141. ///
  142. /// This method should be used only in tests.
  143. int getControlSocketFD() const {
  144. return (socket_->getFD());
  145. }
  146. private:
  147. /// @brief Private constructor
  148. ///
  149. /// Registers internal 'list-commands' command.
  150. CommandMgr();
  151. /// @brief 'list-commands' command handler
  152. ///
  153. /// This method implements command 'list-commands'. It returns a list of all
  154. /// currently supported commands.
  155. /// @param name name of the command (should always be 'list-commands')
  156. /// @param params additional parameters (ignored)
  157. /// @return structure that includes all currently supported commands
  158. isc::data::ConstElementPtr
  159. listCommandsHandler(const std::string& name,
  160. const isc::data::ConstElementPtr& params);
  161. typedef std::map<std::string, CommandHandler> HandlerContainer;
  162. /// @brief Container for command handlers
  163. HandlerContainer handlers_;
  164. /// @brief Control socket structure
  165. ///
  166. /// This is the socket that accepts incoming connections. There can be at
  167. /// most one (if command channel is configured).
  168. CommandSocketPtr socket_;
  169. /// @brief Sockets for open connections
  170. ///
  171. /// These are the sockets that are dedicated to handle a specific connection.
  172. /// Their number is equal to number of current control connections.
  173. std::list<CommandSocketPtr> connections_;
  174. };
  175. }; // end of isc::config namespace
  176. }; // end of isc namespace
  177. #endif