1 #pragma once 2 3 #include "types.hpp" 4 #include "sdbusplus.hpp" 5 #include <phosphor-logging/log.hpp> 6 7 namespace phosphor 8 { 9 namespace fan 10 { 11 namespace control 12 { 13 class Zone; 14 15 using namespace phosphor::fan; 16 using namespace sdbusplus::bus::match; 17 using namespace phosphor::logging; 18 19 /** 20 * @brief Create a zone handler function object 21 * 22 * @param[in] handler - The handler being created 23 * 24 * @return - The created zone handler function object 25 */ 26 template <typename T> 27 auto make_zoneHandler(T&& handler) 28 { 29 return ZoneHandler(std::forward<T>(handler)); 30 } 31 32 /** 33 * @brief Create a trigger function object 34 * 35 * @param[in] trigger - The trigger being created 36 * 37 * @return - The created trigger function object 38 */ 39 template <typename T> 40 auto make_trigger(T&& trigger) 41 { 42 return Trigger(std::forward<T>(trigger)); 43 } 44 45 /** 46 * @brief Create a handler function object 47 * 48 * @param[in] handler - The handler being created 49 * 50 * @return - The created handler function object 51 */ 52 template <typename T, typename U> 53 auto make_handler(U&& handler) 54 { 55 return T(std::forward<U>(handler)); 56 } 57 58 /** 59 * @brief Create an action function object 60 * 61 * @param[in] action - The action being created 62 * 63 * @return - The created action function object 64 */ 65 template <typename T> 66 auto make_action(T&& action) 67 { 68 return Action(std::forward<T>(action)); 69 } 70 71 /** 72 * @struct Properties 73 * @brief A set of match filter functors for Dbus property values. Each 74 * functor provides an associated process for retrieving the value 75 * for a given property and providing it to the given handler function. 76 * 77 * @tparam T - The type of the property value 78 * @tparam U - The type of the handler 79 */ 80 template <typename T, typename U> 81 struct Properties 82 { 83 Properties() = delete; 84 ~Properties() = default; 85 Properties(const Properties&) = default; 86 Properties& operator=(const Properties&) = default; 87 Properties(Properties&&) = default; 88 Properties& operator=(Properties&&) = default; 89 explicit Properties(U&& handler) : 90 _handler(std::forward<U>(handler)) { } 91 Properties(const char* path, 92 const char* intf, 93 const char* prop, 94 U&& handler) : 95 _path(path), 96 _intf(intf), 97 _prop(prop), 98 _handler(std::forward<U>(handler)) { } 99 100 /** @brief Run signal handler function 101 * 102 * Extract the property from the PropertiesChanged 103 * message and run the handler function. 104 */ 105 void operator()(sdbusplus::bus::bus& bus, 106 sdbusplus::message::message& msg, 107 Zone& zone) const 108 { 109 if (msg) 110 { 111 std::string intf; 112 std::map<std::string, sdbusplus::message::variant<T>> props; 113 114 msg.read(intf); 115 if (intf != _intf) 116 { 117 // Interface name does not match on object 118 return; 119 } 120 121 msg.read(props); 122 auto it = props.find(_prop); 123 if (it == props.cend()) 124 { 125 // Property not included in dictionary of properties changed 126 return; 127 } 128 129 _handler(zone, _path, _intf, _prop, std::forward<T>( 130 sdbusplus::message::variant_ns::get<T>(it->second))); 131 } 132 else 133 { 134 try 135 { 136 auto val = zone.getPropertyByName<T>(_path, _intf, _prop); 137 _handler(zone, _path, _intf, _prop, std::forward<T>(val)); 138 } 139 catch (const sdbusplus::exception::SdBusError&) 140 { 141 // Property will not be used unless a property changed 142 // signal message is received for this property. 143 } 144 catch (const util::DBusError&) 145 { 146 // Property will not be used unless a property changed 147 // signal message is received for this property. 148 } 149 } 150 } 151 152 /** @brief Run init handler function 153 * 154 * Get the property from each member object of the group 155 * and run the handler function. 156 */ 157 void operator()(Zone& zone, const Group& group) const 158 { 159 std::for_each( 160 group.begin(), 161 group.end(), 162 [&zone, handler = std::move(_handler)](auto const& member) 163 { 164 auto path = std::get<pathPos>(member); 165 auto intf = std::get<intfPos>(member); 166 auto prop = std::get<propPos>(member); 167 try 168 { 169 auto val = zone.getPropertyByName<T>(path, intf, prop); 170 handler(zone, path, intf, prop, std::forward<T>(val)); 171 } 172 catch (const sdbusplus::exception::SdBusError&) 173 { 174 // Property value not sent to handler 175 } 176 catch (const util::DBusError&) 177 { 178 // Property value not sent to handler 179 } 180 } 181 ); 182 } 183 184 private: 185 const char* _path; 186 const char* _intf; 187 const char* _prop; 188 U _handler; 189 }; 190 191 /** 192 * @brief Used to process a Dbus properties changed signal event 193 * 194 * @param[in] path - Object path 195 * @param[in] intf - Object interface 196 * @param[in] prop - Object property 197 * @param[in] handler - Handler function to perform 198 * 199 * @tparam T - The type of the property 200 * @tparam U - The type of the handler 201 */ 202 template <typename T, typename U> 203 auto propertiesChanged(const char* path, 204 const char* intf, 205 const char* prop, 206 U&& handler) 207 { 208 return Properties<T, U>(path, 209 intf, 210 prop, 211 std::forward<U>(handler)); 212 } 213 214 /** 215 * @brief Used to get the properties of an event's group 216 * 217 * @param[in] handler - Handler function to perform 218 * 219 * @tparam T - The type of all the properties 220 * @tparam U - The type of the handler 221 */ 222 template <typename T, typename U> 223 auto getProperties(U&& handler) 224 { 225 return Properties<T, U>(std::forward<U>(handler)); 226 } 227 228 /** 229 * @struct Interfaces Added 230 * @brief A match filter functor for Dbus interfaces added signals 231 * 232 * @tparam T - The type of the property value 233 * @tparam U - The type of the handler 234 */ 235 template <typename T, typename U> 236 struct InterfacesAdded 237 { 238 InterfacesAdded() = delete; 239 ~InterfacesAdded() = default; 240 InterfacesAdded(const InterfacesAdded&) = default; 241 InterfacesAdded& operator=(const InterfacesAdded&) = default; 242 InterfacesAdded(InterfacesAdded&&) = default; 243 InterfacesAdded& operator=(InterfacesAdded&&) = default; 244 InterfacesAdded(const char* path, 245 const char* intf, 246 const char* prop, 247 U&& handler) : 248 _path(path), 249 _intf(intf), 250 _prop(prop), 251 _handler(std::forward<U>(handler)) { } 252 253 /** @brief Run signal handler function 254 * 255 * Extract the property from the InterfacesAdded 256 * message and run the handler function. 257 */ 258 void operator()(sdbusplus::bus::bus&, 259 sdbusplus::message::message& msg, 260 Zone& zone) const 261 { 262 if (msg) 263 { 264 std::map<std::string, 265 std::map<std::string, 266 sdbusplus::message::variant<T>>> intfProp; 267 sdbusplus::message::object_path op; 268 269 msg.read(op); 270 if (static_cast<const std::string&>(op) != _path) 271 { 272 // Object path does not match this handler's path 273 return; 274 } 275 276 msg.read(intfProp); 277 auto itIntf = intfProp.find(_intf); 278 if (itIntf == intfProp.cend()) 279 { 280 // Interface not found on this handler's path 281 return; 282 } 283 auto itProp = itIntf->second.find(_prop); 284 if (itProp == itIntf->second.cend()) 285 { 286 // Property not found on this handler's path 287 return; 288 } 289 290 _handler(zone, _path, _intf, _prop, std::forward<T>( 291 sdbusplus::message::variant_ns::get<T>(itProp->second))); 292 } 293 } 294 295 private: 296 const char* _path; 297 const char* _intf; 298 const char* _prop; 299 U _handler; 300 }; 301 302 /** 303 * @brief Used to process a Dbus interfaces added signal event 304 * 305 * @param[in] path - Object path 306 * @param[in] intf - Object interface 307 * @param[in] prop - Object property 308 * @param[in] handler - Handler function to perform 309 * 310 * @tparam T - The type of the property 311 * @tparam U - The type of the handler 312 */ 313 template <typename T, typename U> 314 auto interfacesAdded(const char* path, 315 const char* intf, 316 const char* prop, 317 U&& handler) 318 { 319 return InterfacesAdded<T, U>(path, 320 intf, 321 prop, 322 std::forward<U>(handler)); 323 } 324 325 /** 326 * @struct Interfaces Removed 327 * @brief A match filter functor for Dbus interfaces removed signals 328 * 329 * @tparam U - The type of the handler 330 */ 331 template <typename U> 332 struct InterfacesRemoved 333 { 334 InterfacesRemoved() = delete; 335 ~InterfacesRemoved() = default; 336 InterfacesRemoved(const InterfacesRemoved&) = default; 337 InterfacesRemoved& operator=(const InterfacesRemoved&) = default; 338 InterfacesRemoved(InterfacesRemoved&&) = default; 339 InterfacesRemoved& operator=(InterfacesRemoved&&) = default; 340 InterfacesRemoved(const char* path, 341 const char* intf, 342 U&& handler) : 343 _path(path), 344 _intf(intf), 345 _handler(std::forward<U>(handler)) { } 346 347 /** @brief Run signal handler function 348 * 349 * Extract the interfaces from the InterfacesRemoved 350 * message and run the handler function. 351 */ 352 void operator()(sdbusplus::bus::bus&, 353 sdbusplus::message::message& msg, 354 Zone& zone) const 355 { 356 if (msg) 357 { 358 std::vector<std::string> intfs; 359 sdbusplus::message::object_path op; 360 361 msg.read(op); 362 if (static_cast<const std::string&>(op) != _path) 363 { 364 // Object path does not match this handler's path 365 return; 366 } 367 368 msg.read(intfs); 369 auto itIntf = std::find(intfs.begin(), intfs.end(), _intf); 370 if (itIntf == intfs.cend()) 371 { 372 // Interface not found on this handler's path 373 return; 374 } 375 376 _handler(zone); 377 } 378 } 379 380 private: 381 const char* _path; 382 const char* _intf; 383 U _handler; 384 }; 385 386 /** 387 * @brief Used to process a Dbus interfaces removed signal event 388 * 389 * @param[in] path - Object path 390 * @param[in] intf - Object interface 391 * @param[in] handler - Handler function to perform 392 * 393 * @tparam U - The type of the handler 394 */ 395 template <typename U> 396 auto interfacesRemoved(const char* path, 397 const char* intf, 398 U&& handler) 399 { 400 return InterfacesRemoved<U>(path, 401 intf, 402 std::forward<U>(handler)); 403 } 404 405 /** 406 * @struct Name Owner 407 * @brief A functor for Dbus name owner signals and methods 408 * 409 * @tparam U - The type of the handler 410 */ 411 template <typename U> 412 struct NameOwner 413 { 414 NameOwner() = delete; 415 ~NameOwner() = default; 416 NameOwner(const NameOwner&) = default; 417 NameOwner& operator=(const NameOwner&) = default; 418 NameOwner(NameOwner&&) = default; 419 NameOwner& operator=(NameOwner&&) = default; 420 explicit NameOwner(U&& handler) : 421 _handler(std::forward<U>(handler)) { } 422 423 /** @brief Run signal handler function 424 * 425 * Extract the name owner from the NameOwnerChanged 426 * message and run the handler function. 427 */ 428 void operator()(sdbusplus::bus::bus& bus, 429 sdbusplus::message::message& msg, 430 Zone& zone) const 431 { 432 std::string name; 433 bool hasOwner = false; 434 if (msg) 435 { 436 // Handle NameOwnerChanged signals 437 msg.read(name); 438 439 std::string oldOwn; 440 msg.read(oldOwn); 441 442 std::string newOwn; 443 msg.read(newOwn); 444 if (!newOwn.empty()) 445 { 446 hasOwner = true; 447 } 448 _handler(zone, name, hasOwner); 449 } 450 } 451 452 void operator()(Zone& zone, 453 const Group& group) const 454 { 455 std::string name = ""; 456 bool hasOwner = false; 457 std::for_each( 458 group.begin(), 459 group.end(), 460 [&zone, &group, &name, &hasOwner, handler = std::move(_handler)]( 461 auto const& member) 462 { 463 auto path = std::get<pathPos>(member); 464 auto intf = std::get<intfPos>(member); 465 try 466 { 467 auto servName = zone.getService(path, intf); 468 if (name != servName) 469 { 470 name = servName; 471 hasOwner = util::SDBusPlus::callMethodAndRead<bool>( 472 zone.getBus(), 473 "org.freedesktop.DBus", 474 "/org/freedesktop/DBus", 475 "org.freedesktop.DBus", 476 "NameHasOwner", 477 name); 478 // Update service name owner state list of a group 479 handler(zone, name, hasOwner); 480 } 481 } 482 catch (const util::DBusMethodError& e) 483 { 484 // Failed to get service name owner state 485 name = ""; 486 hasOwner = false; 487 } 488 } 489 ); 490 } 491 492 private: 493 U _handler; 494 }; 495 496 /** 497 * @brief Used to process a Dbus name owner changed signal event 498 * 499 * @param[in] handler - Handler function to perform 500 * 501 * @tparam U - The type of the handler 502 * 503 * @return - The NameOwnerChanged signal struct 504 */ 505 template <typename U> 506 auto nameOwnerChanged(U&& handler) 507 { 508 return NameOwner<U>(std::forward<U>(handler)); 509 } 510 511 /** 512 * @brief Used to process the init of a name owner event 513 * 514 * @param[in] handler - Handler function to perform 515 * 516 * @tparam U - The type of the handler 517 * 518 * @return - The NameOwnerChanged signal struct 519 */ 520 template <typename U> 521 auto nameHasOwner(U&& handler) 522 { 523 return NameOwner<U>(std::forward<U>(handler)); 524 } 525 526 } // namespace control 527 } // namespace fan 528 } // namespace phosphor 529