ccsession.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright (C) 2009 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. // $Id$
  15. #ifndef __CCSESSION_H
  16. #define __CCSESSION_H 1
  17. #include <string>
  18. #include <config/config_data.h>
  19. #include <config/module_spec.h>
  20. #include <cc/session.h>
  21. #include <cc/data.h>
  22. namespace isc {
  23. namespace config {
  24. ///
  25. /// \brief Creates a standard config/command level success answer message
  26. /// (i.e. of the form { "result": [ 0 ] }
  27. /// \return Standard command/config success answer message
  28. isc::data::ConstElementPtr createAnswer();
  29. ///
  30. /// \brief Creates a standard config/command level answer message
  31. /// (i.e. of the form { "result": [ rcode, arg ] }
  32. /// If rcode != 0, arg must be a StringElement
  33. ///
  34. /// \param rcode The return code (0 for success)
  35. /// \param arg For rcode == 0, this is an optional argument of any
  36. /// Element type. For rcode == 1, this argument is mandatory,
  37. /// and must be a StringElement containing an error description
  38. /// \return Standard command/config answer message
  39. isc::data::ConstElementPtr createAnswer(const int rcode,
  40. isc::data::ConstElementPtr arg);
  41. ///
  42. /// \brief Creates a standard config/command level answer message
  43. /// (i.e. of the form { "result": [ rcode, arg ] }
  44. ///
  45. /// \param rcode The return code (0 for success)
  46. /// \param arg A string to put into the StringElement argument
  47. /// \return Standard command/config answer message
  48. isc::data::ConstElementPtr createAnswer(const int rcode,
  49. const std::string& arg);
  50. ///
  51. /// Parses a standard config/command level answer message
  52. ///
  53. /// \param rcode This value will be set to the return code contained in
  54. /// the message
  55. /// \param msg The message to parse
  56. /// \return The optional argument in the message, or an empty ElementPtr
  57. /// if there was no argument. If rcode != 0, this contains a
  58. /// StringElement with the error description.
  59. isc::data::ConstElementPtr parseAnswer(int &rcode,
  60. isc::data::ConstElementPtr msg);
  61. ///
  62. /// \brief Creates a standard config/command command message with no
  63. /// argument (of the form { "command": [ "my_command" ] }
  64. ///
  65. /// \param command The command string
  66. /// \return The created message
  67. isc::data::ConstElementPtr createCommand(const std::string& command);
  68. ///
  69. /// \brief Creates a standard config/command command message with the
  70. /// given argument (of the form { "command": [ "my_command", arg ] }
  71. ///
  72. /// \param command The command string
  73. /// \param arg The optional argument for the command. This can be of
  74. /// any Element type, but it should conform to the .spec file.
  75. /// \return The created message
  76. isc::data::ConstElementPtr createCommand(const std::string& command,
  77. isc::data::ConstElementPtr arg);
  78. ///
  79. /// \brief Parses the given command into a string containing the actual
  80. /// command and an ElementPtr containing the optional argument.
  81. ///
  82. /// \param arg This value will be set to the ElementPtr pointing to
  83. /// the argument, or to an empty ElementPtr if there was none.
  84. /// \param command The command message containing the command (as made
  85. /// by createCommand()
  86. /// \return The command string
  87. std::string parseCommand(isc::data::ConstElementPtr& arg,
  88. isc::data::ConstElementPtr command);
  89. ///
  90. /// \brief A standard cc session exception that is thrown if a function
  91. /// is there is a problem with one of the messages
  92. ///
  93. // todo: include types and called function in the exception
  94. class CCSessionError : public isc::Exception {
  95. public:
  96. CCSessionError(const char* file, size_t line, const char* what) :
  97. isc::Exception(file, line, what) {}
  98. };
  99. ///
  100. /// \brief This module keeps a connection to the command channel,
  101. /// holds configuration information, and handles messages from
  102. /// the command channel
  103. ///
  104. class ModuleCCSession : public ConfigData {
  105. public:
  106. /**
  107. * Initialize a config/command session
  108. *
  109. * @param spec_file_name The name of the file containing the
  110. * module specification.
  111. * @param session A Session object over which configuration and command
  112. * data are exchanged.
  113. * @param config_handler A callback function pointer to be called when
  114. * configuration of the local module needs to be updated.
  115. * This must refer to a valid object of a concrete derived class of
  116. * AbstractSession without establishing the session.
  117. * Note: the design decision on who is responsible for establishing the
  118. * session is in flux, and may change in near future.
  119. * @param command_handler A callback function pointer to be called when
  120. * a control command from a remote agent needs to be performed on the
  121. * local module.
  122. */
  123. ModuleCCSession(const std::string& spec_file_name,
  124. isc::cc::AbstractSession& session,
  125. isc::data::ConstElementPtr(*config_handler)(
  126. isc::data::ConstElementPtr new_config) = NULL,
  127. isc::data::ConstElementPtr(*command_handler)(
  128. const std::string& command,
  129. isc::data::ConstElementPtr args) = NULL
  130. );
  131. /**
  132. * Optional optimization for checkCommand loop; returns true
  133. * if there are unhandled queued messages in the cc session.
  134. * (if either this is true or there is data on the socket found
  135. * by the select() call on getSocket(), run checkCommand())
  136. *
  137. * @return true if there are unhandled queued messages
  138. */
  139. bool hasQueuedMsgs() const;
  140. /**
  141. * Check if there is a command or config change on the command
  142. * session. If so, the appropriate handler is called if set.
  143. * If not set, a default answer is returned.
  144. * This is a non-blocking read; if there is nothing this function
  145. * will return 0.
  146. */
  147. int checkCommand();
  148. /**
  149. * The config handler function should expect an ElementPtr containing
  150. * the full configuration where non-default values have been set.
  151. * Later we might want to think about more granular control
  152. * (i.e. this does not scale to for instance lists containing
  153. * 100000 zones, where the whole list is passed every time a single
  154. * thing changes)
  155. */
  156. void setConfigHandler(isc::data::ConstElementPtr(*config_handler)(
  157. isc::data::ConstElementPtr new_config))
  158. {
  159. config_handler_ = config_handler;
  160. }
  161. /**
  162. * Set a command handler; the function that is passed takes an
  163. * ElementPtr, pointing to a list element, containing
  164. * [ module_name, command_name, arg1, arg2, ... ]
  165. * The returned ElementPtr should look like
  166. * { "result": [ return_value, result_value ] }
  167. * result value here is optional and depends on the command
  168. *
  169. * This protocol is very likely to change.
  170. */
  171. void setCommandHandler(isc::data::ConstElementPtr(*command_handler)(
  172. const std::string& command,
  173. isc::data::ConstElementPtr args))
  174. {
  175. command_handler_ = command_handler;
  176. }
  177. /**
  178. * Gives access to the configuration values of a different module
  179. * Once this function has been called with the name of the specification
  180. * file of the module you want the configuration of, you can use
  181. * \c getRemoteConfigValue() to get a specific setting.
  182. * Changes are automatically updated, but you cannot specify handlers
  183. * for those changes, must use \c getRemoteConfigValue() to get a value
  184. * This function will subscribe to the relevant module channel.
  185. *
  186. * \param spec_file_name The path to the specification file of
  187. * the module we want to have configuration
  188. * values from
  189. * \return The name of the module specified in the given specification
  190. * file
  191. */
  192. std::string addRemoteConfig(const std::string& spec_file_name);
  193. /**
  194. * Removes the module with the given name from the remote config
  195. * settings. If the module was not added with \c addRemoteConfig(),
  196. * nothing happens.
  197. */
  198. void removeRemoteConfig(const std::string& module_name);
  199. /**
  200. * Returns the current configuration value for the given module
  201. * name at the given identifier. See \c ConfigData::getValue() for
  202. * more details.
  203. * Raises a ModuleCCSessionError if the module name is unknown
  204. * Raises a DataNotFoundError if the identifier does not exist
  205. * in the specification.
  206. *
  207. * \param module_name The name of the module to get a config value for
  208. * \param identifier The identifier of the config value
  209. * \return The configuration setting at the given identifier
  210. */
  211. isc::data::ConstElementPtr getRemoteConfigValue(
  212. const std::string& module_name,
  213. const std::string& identifier) const;
  214. private:
  215. ModuleSpec readModuleSpecification(const std::string& filename);
  216. void startCheck();
  217. std::string module_name_;
  218. isc::cc::AbstractSession& session_;
  219. ModuleSpec module_specification_;
  220. isc::data::ConstElementPtr handleConfigUpdate(
  221. isc::data::ConstElementPtr new_config);
  222. isc::data::ConstElementPtr(*config_handler_)(
  223. isc::data::ConstElementPtr new_config);
  224. isc::data::ConstElementPtr(*command_handler_)(
  225. const std::string& command,
  226. isc::data::ConstElementPtr args);
  227. std::map<std::string, ConfigData> remote_module_configs_;
  228. void updateRemoteConfig(const std::string& module_name,
  229. isc::data::ConstElementPtr new_config);
  230. };
  231. }
  232. }
  233. #endif // __CCSESSION_H
  234. // Local Variables:
  235. // mode: c++
  236. // End: