1 // Copyright (C) 2013-2020 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 #ifndef LIBRARY_HANDLE_H 8 #define LIBRARY_HANDLE_H 9 10 #include <string> 11 #include <cc/data.h> 12 13 namespace isc { 14 namespace hooks { 15 16 // Forward declarations 17 class CalloutHandle; 18 class CalloutManager; 19 20 /// Typedef for a callout pointer. (Callouts must have "C" linkage.) 21 extern "C" { 22 typedef int (*CalloutPtr)(CalloutHandle&); 23 }; 24 25 /// @brief Library handle 26 /// 27 /// This class is accessed by the user library when registering callouts, 28 /// either by the library's load() function, or by one of the callouts 29 /// themselves. 30 /// 31 /// It is really little more than a shell around the CalloutManager. By 32 /// presenting this object to the user-library callouts, callouts can manage 33 /// the callout list for their own library, but cannot affect the callouts 34 /// registered by other libraries. 35 /// 36 /// (This restriction is achieved by the CalloutManager maintaining the concept 37 /// of the "current library". When a callout is registered - either by the 38 /// library's load() function, or by a callout in the library - the registration 39 /// information includes the library active at the time. When that callout is 40 /// called, the CalloutManager uses that information to set the "current 41 /// library": the registration functions only operator on data whose 42 /// associated library is equal to the "current library".) 43 /// 44 /// As of Kea 1.3.0 release, the @ref LibraryHandle can be used by the hook 45 /// libraries to install control command handlers and dynamically register 46 /// hook points with which the handlers are associated. For example, if the 47 /// hook library supports control-command 'foo-bar' it should register its 48 /// handler similarly to this: 49 /// @code 50 /// int load(LibraryHandle& libhandle) { 51 /// libhandle.registerCommandCallout("foo-bar", foo_bar_handler); 52 /// return (0); 53 /// } 54 /// @endcode 55 /// 56 /// which will result in automatic creation of the hook point for the command 57 /// (if one doesn't exist) and associating the callout 'foo_bar_handler' with 58 /// this hook point as a handler for the command. 59 60 class LibraryHandle { 61 public: 62 63 /// @brief Constructor 64 /// 65 /// @param manager Back reference to the containing CalloutManager. 66 /// This reference is used to access appropriate methods in that 67 /// object. Note that the reference is safe - the only instance 68 /// of the LibraryHandle in the system is as a member of the 69 /// CalloutManager to which it points. 70 /// 71 /// @param index Index of the library to which the LibraryHandle applies. 72 /// If negative, the library index as set in the CalloutManager is 73 /// used. Note: although -1 is a valid argument value for 74 /// @ref isc::hooks::CalloutManager::setLibraryIndex(), in this class 75 /// it is used as a sentinel to indicate that the library index in 76 /// @ref isc::hooks::CalloutManager should not be set or reset. 77 LibraryHandle(CalloutManager& manager, int index = -1) callout_manager_(manager)78 : callout_manager_(manager), index_(index) {} 79 80 /// @brief Register a callout on a hook 81 /// 82 /// Registers a callout function with a given hook. The callout is added 83 /// to the end of the callouts for the current library that are associated 84 /// with that hook. 85 /// 86 /// @param name Name of the hook to which the callout is added. 87 /// @param callout Pointer to the callout function to be registered. 88 /// 89 /// @throw NoSuchHook The hook name is unrecognized. 90 /// @throw Unexpected The hook name is valid but an internal data structure 91 /// is of the wrong size. 92 void registerCallout(const std::string& name, CalloutPtr callout); 93 94 /// @brief Register control command handler 95 /// 96 /// Registers control command handler by creating a hook point for this 97 /// command (if it doesn't exist) and associating the callout as a command 98 /// handler. It is possible to register multiple command handlers for the 99 /// same control command because command handlers are implemented as callouts. 100 /// 101 /// @param command_name Command name for which handler should be installed. 102 /// @param callout Pointer to the command handler implemented as a callout. 103 void registerCommandCallout(const std::string& command_name, CalloutPtr callout); 104 105 /// @brief De-Register a callout on a hook 106 /// 107 /// Searches through the functions registered by the current library with 108 /// the named hook and removes all entries matching the callout. It does 109 /// not affect callouts registered by other libraries. 110 /// 111 /// @param name Name of the hook from which the callout is removed. 112 /// @param callout Pointer to the callout function to be removed. 113 /// 114 /// @return true if a one or more callouts were deregistered. 115 /// 116 /// @throw NoSuchHook The hook name is unrecognized. 117 /// @throw Unexpected The hook name is valid but an internal data structure 118 /// is of the wrong size. 119 bool deregisterCallout(const std::string& name, CalloutPtr callout); 120 121 /// @brief Removes all callouts on a hook 122 /// 123 /// Removes all callouts associated with a given hook that were registered. 124 /// by the current library. It does not affect callouts that were 125 /// registered by other libraries. 126 /// 127 /// @param name Name of the hook from which the callouts are removed. 128 /// 129 /// @return true if one or more callouts were deregistered. 130 /// 131 /// @throw NoSuchHook Thrown if the hook name is unrecognized. 132 bool deregisterAllCallouts(const std::string& name); 133 134 135 /// @brief Returns configuration parameter for the library. 136 /// 137 /// This method returns configuration parameters specified in the 138 /// configuration file. Here's the example. Let's assume that there 139 /// are two hook libraries configured: 140 /// 141 /// "hooks-libraries": [ 142 /// { 143 /// "library": "/opt/charging.so", 144 /// "parameters": {} 145 /// }, 146 /// { 147 /// "library": "/opt/local/notification.so", 148 /// "parameters": { 149 /// "mail": "alarm@example.com", 150 /// "floor": 42, 151 /// "debug": false, 152 /// "users": [ "alice", "bob", "charlie" ], 153 /// "header": { 154 /// "french": "bonjour", 155 /// "klingon": "yl'el" 156 /// } 157 /// } 158 /// } 159 ///] 160 /// 161 /// The first library has no parameters, so regardless of the name 162 /// specified, for that library getParameter will always return NULL. 163 /// 164 /// For the second parameter, depending the following calls will return: 165 /// - x = getParameter("mail") will return instance of 166 /// isc::data::StringElement. The content can be accessed with 167 /// x->stringValue() and will return std::string. 168 /// - x = getParameter("floor") will return an instance of isc::data::IntElement. 169 /// The content can be accessed with x->intValue() and will return int. 170 /// - x = getParameter("debug") will return an instance of isc::data::BoolElement. 171 /// Its value can be accessed with x->boolValue() and will return bool. 172 /// - x = getParameter("users") will return an instance of ListElement. 173 /// Its content can be accessed with the following methods: 174 /// x->size(), x->get(index) 175 /// - x = getParameter("header") will return an instance of isc::data::MapElement. 176 /// Its content can be accessed with the following methods: 177 /// x->find("klingon"), x->contains("french"), x->size() 178 /// 179 /// For more examples and complete API, see documentation for 180 /// @ref isc::data::Element class and its derivatives: 181 /// - @ref isc::data::IntElement 182 /// - @ref isc::data::DoubleElement 183 /// - @ref isc::data::BoolElement 184 /// - @ref isc::data::StringElement 185 /// - @ref isc::data::ListElement 186 /// - @ref isc::data::MapElement 187 /// 188 /// Another good way to learn how to use Element interface is to look at the 189 /// unittests in data_unittests.cc. 190 /// 191 /// @param name text name of the parameter. 192 /// @return ElementPtr representing requested parameter (may be null, if 193 /// there is no such parameter.) 194 isc::data::ConstElementPtr 195 getParameter(const std::string& name); 196 197 /// @brief Get configuration parameter common code. 198 /// 199 /// @return configuration parameters. 200 isc::data::ConstElementPtr getParameters(); 201 202 /// @brief Returns names of configuration parameters for the library. 203 /// 204 /// This method returns a vector of strings reflecting names of 205 /// configuration parameters specified in the configuration file. 206 /// 207 /// @note: kept for backward compatibility. 208 /// @return a vector with parameter entry names. 209 std::vector<std::string> getParameterNames(); 210 211 private: 212 /// @brief Copy constructor 213 /// 214 /// Private (with no implementation) as it makes no sense to copy an object 215 /// of this type. All code receives a reference to an existing handle which 216 /// is tied to a particular CalloutManager. Creating a copy of that handle 217 /// runs the risk of a "dangling pointer" to the original handle's callout 218 /// manager. 219 /// 220 /// @param Unused - should be the object to copy. 221 LibraryHandle(const LibraryHandle&); 222 223 /// @brief Assignment operator 224 /// 225 /// Declared private like the copy constructor for the same reasons. It too 226 /// has no implementation. 227 /// 228 /// @param Unused - should be the object to copy. 229 LibraryHandle& operator=(const LibraryHandle&); 230 231 /// Back pointer to the collection object for the library 232 CalloutManager& callout_manager_; 233 234 /// Library index to which this handle applies. -1 indicates that it 235 /// applies to whatever index is current in the CalloutManager. 236 int index_; 237 }; 238 239 } // namespace util 240 } // namespace isc 241 242 #endif // LIBRARY_HANDLE_H 243