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 msg.read(intf); 113 if (intf != _intf) 114 { 115 // Interface name does not match on object 116 return; 117 } 118 119 std::map<std::string, PropertyVariantType> props; 120 msg.read(props); 121 auto it = props.find(_prop); 122 if (it == props.cend()) 123 { 124 // Property not included in dictionary of properties changed 125 return; 126 } 127 128 // Retrieve the property's value applying any visitors necessary 129 auto value = 130 zone.getPropertyValueVisitor<T>(_intf, _prop, it->second); 131 132 _handler(zone, _path, _intf, _prop, std::forward<T>(value)); 133 } 134 else 135 { 136 try 137 { 138 auto val = zone.getPropertyByName<T>(_path, _intf, _prop); 139 _handler(zone, _path, _intf, _prop, std::forward<T>(val)); 140 } 141 catch (const sdbusplus::exception::SdBusError&) 142 { 143 // Property will not be used unless a property changed 144 // signal message is received for this property. 145 } 146 catch (const util::DBusError&) 147 { 148 // Property will not be used unless a property changed 149 // signal message is received for this property. 150 } 151 } 152 } 153 154 /** @brief Run init handler function 155 * 156 * Get the property from each member object of the group 157 * and run the handler function. 158 */ 159 void operator()(Zone& zone, const Group& group) const 160 { 161 std::for_each( 162 group.begin(), 163 group.end(), 164 [&zone, handler = std::move(_handler)](auto const& member) 165 { 166 auto path = std::get<pathPos>(member); 167 auto intf = std::get<intfPos>(member); 168 auto prop = std::get<propPos>(member); 169 try 170 { 171 auto val = zone.getPropertyByName<T>(path, intf, prop); 172 handler(zone, path, intf, prop, std::forward<T>(val)); 173 } 174 catch (const sdbusplus::exception::SdBusError&) 175 { 176 // Property value not sent to handler 177 } 178 catch (const util::DBusError&) 179 { 180 // Property value not sent to handler 181 } 182 } 183 ); 184 } 185 186 private: 187 const char* _path; 188 const char* _intf; 189 const char* _prop; 190 U _handler; 191 }; 192 193 /** 194 * @brief Used to process a Dbus properties changed signal event 195 * 196 * @param[in] path - Object path 197 * @param[in] intf - Object interface 198 * @param[in] prop - Object property 199 * @param[in] handler - Handler function to perform 200 * 201 * @tparam T - The type of the property 202 * @tparam U - The type of the handler 203 */ 204 template <typename T, typename U> 205 auto propertiesChanged(const char* path, 206 const char* intf, 207 const char* prop, 208 U&& handler) 209 { 210 return Properties<T, U>(path, 211 intf, 212 prop, 213 std::forward<U>(handler)); 214 } 215 216 /** 217 * @brief Used to get the properties of an event's group 218 * 219 * @param[in] handler - Handler function to perform 220 * 221 * @tparam T - The type of all the properties 222 * @tparam U - The type of the handler 223 */ 224 template <typename T, typename U> 225 auto getProperties(U&& handler) 226 { 227 return Properties<T, U>(std::forward<U>(handler)); 228 } 229 230 /** 231 * @struct Interfaces Added 232 * @brief A match filter functor for Dbus interfaces added signals 233 * 234 * @tparam T - The type of the property value 235 * @tparam U - The type of the handler 236 */ 237 template <typename T, typename U> 238 struct InterfacesAdded 239 { 240 InterfacesAdded() = delete; 241 ~InterfacesAdded() = default; 242 InterfacesAdded(const InterfacesAdded&) = default; 243 InterfacesAdded& operator=(const InterfacesAdded&) = default; 244 InterfacesAdded(InterfacesAdded&&) = default; 245 InterfacesAdded& operator=(InterfacesAdded&&) = default; 246 InterfacesAdded(const char* path, 247 const char* intf, 248 const char* prop, 249 U&& handler) : 250 _path(path), 251 _intf(intf), 252 _prop(prop), 253 _handler(std::forward<U>(handler)) { } 254 255 /** @brief Run signal handler function 256 * 257 * Extract the property from the InterfacesAdded 258 * message and run the handler function. 259 */ 260 void operator()(sdbusplus::bus::bus&, 261 sdbusplus::message::message& msg, 262 Zone& zone) const 263 { 264 if (msg) 265 { 266 sdbusplus::message::object_path op; 267 268 msg.read(op); 269 if (static_cast<const std::string&>(op) != _path) 270 { 271 // Object path does not match this handler's path 272 return; 273 } 274 275 std::map<std::string, std::map<std::string, 276 PropertyVariantType>> intfProp; 277 msg.read(intfProp); 278 auto itIntf = intfProp.find(_intf); 279 if (itIntf == intfProp.cend()) 280 { 281 // Interface not found on this handler's path 282 return; 283 } 284 auto itProp = itIntf->second.find(_prop); 285 if (itProp == itIntf->second.cend()) 286 { 287 // Property not found on this handler's path 288 return; 289 } 290 291 // Retrieve the property's value applying any visitors necessary 292 auto value = 293 zone.getPropertyValueVisitor<T>(_intf, _prop, itProp->second); 294 295 _handler(zone, _path, _intf, _prop, std::forward<T>(value)); 296 } 297 } 298 299 private: 300 const char* _path; 301 const char* _intf; 302 const char* _prop; 303 U _handler; 304 }; 305 306 /** 307 * @brief Used to process a Dbus interfaces added signal event 308 * 309 * @param[in] path - Object path 310 * @param[in] intf - Object interface 311 * @param[in] prop - Object property 312 * @param[in] handler - Handler function to perform 313 * 314 * @tparam T - The type of the property 315 * @tparam U - The type of the handler 316 */ 317 template <typename T, typename U> 318 auto interfacesAdded(const char* path, 319 const char* intf, 320 const char* prop, 321 U&& handler) 322 { 323 return InterfacesAdded<T, U>(path, 324 intf, 325 prop, 326 std::forward<U>(handler)); 327 } 328 329 /** 330 * @struct Interfaces Removed 331 * @brief A match filter functor for Dbus interfaces removed signals 332 * 333 * @tparam U - The type of the handler 334 */ 335 template <typename U> 336 struct InterfacesRemoved 337 { 338 InterfacesRemoved() = delete; 339 ~InterfacesRemoved() = default; 340 InterfacesRemoved(const InterfacesRemoved&) = default; 341 InterfacesRemoved& operator=(const InterfacesRemoved&) = default; 342 InterfacesRemoved(InterfacesRemoved&&) = default; 343 InterfacesRemoved& operator=(InterfacesRemoved&&) = default; 344 InterfacesRemoved(const char* path, 345 const char* intf, 346 U&& handler) : 347 _path(path), 348 _intf(intf), 349 _handler(std::forward<U>(handler)) { } 350 351 /** @brief Run signal handler function 352 * 353 * Extract the interfaces from the InterfacesRemoved 354 * message and run the handler function. 355 */ 356 void operator()(sdbusplus::bus::bus&, 357 sdbusplus::message::message& msg, 358 Zone& zone) const 359 { 360 if (msg) 361 { 362 std::vector<std::string> intfs; 363 sdbusplus::message::object_path op; 364 365 msg.read(op); 366 if (static_cast<const std::string&>(op) != _path) 367 { 368 // Object path does not match this handler's path 369 return; 370 } 371 372 msg.read(intfs); 373 auto itIntf = std::find(intfs.begin(), intfs.end(), _intf); 374 if (itIntf == intfs.cend()) 375 { 376 // Interface not found on this handler's path 377 return; 378 } 379 380 _handler(zone); 381 } 382 } 383 384 private: 385 const char* _path; 386 const char* _intf; 387 U _handler; 388 }; 389 390 /** 391 * @brief Used to process a Dbus interfaces removed signal event 392 * 393 * @param[in] path - Object path 394 * @param[in] intf - Object interface 395 * @param[in] handler - Handler function to perform 396 * 397 * @tparam U - The type of the handler 398 */ 399 template <typename U> 400 auto interfacesRemoved(const char* path, 401 const char* intf, 402 U&& handler) 403 { 404 return InterfacesRemoved<U>(path, 405 intf, 406 std::forward<U>(handler)); 407 } 408 409 /** 410 * @struct Name Owner 411 * @brief A functor for Dbus name owner signals and methods 412 * 413 * @tparam U - The type of the handler 414 */ 415 template <typename U> 416 struct NameOwner 417 { 418 NameOwner() = delete; 419 ~NameOwner() = default; 420 NameOwner(const NameOwner&) = default; 421 NameOwner& operator=(const NameOwner&) = default; 422 NameOwner(NameOwner&&) = default; 423 NameOwner& operator=(NameOwner&&) = default; 424 explicit NameOwner(U&& handler) : 425 _handler(std::forward<U>(handler)) { } 426 427 /** @brief Run signal handler function 428 * 429 * Extract the name owner from the NameOwnerChanged 430 * message and run the handler function. 431 */ 432 void operator()(sdbusplus::bus::bus& bus, 433 sdbusplus::message::message& msg, 434 Zone& zone) const 435 { 436 std::string name; 437 bool hasOwner = false; 438 if (msg) 439 { 440 // Handle NameOwnerChanged signals 441 msg.read(name); 442 443 std::string oldOwn; 444 msg.read(oldOwn); 445 446 std::string newOwn; 447 msg.read(newOwn); 448 if (!newOwn.empty()) 449 { 450 hasOwner = true; 451 } 452 _handler(zone, name, hasOwner); 453 } 454 } 455 456 void operator()(Zone& zone, 457 const Group& group) const 458 { 459 std::string name = ""; 460 bool hasOwner = false; 461 std::for_each( 462 group.begin(), 463 group.end(), 464 [&zone, &group, &name, &hasOwner, handler = std::move(_handler)]( 465 auto const& member) 466 { 467 auto path = std::get<pathPos>(member); 468 auto intf = std::get<intfPos>(member); 469 try 470 { 471 auto servName = zone.getService(path, intf); 472 if (name != servName) 473 { 474 name = servName; 475 hasOwner = util::SDBusPlus::callMethodAndRead<bool>( 476 zone.getBus(), 477 "org.freedesktop.DBus", 478 "/org/freedesktop/DBus", 479 "org.freedesktop.DBus", 480 "NameHasOwner", 481 name); 482 // Update service name owner state list of a group 483 handler(zone, name, hasOwner); 484 } 485 } 486 catch (const util::DBusMethodError& e) 487 { 488 // Failed to get service name owner state 489 name = ""; 490 hasOwner = false; 491 } 492 } 493 ); 494 } 495 496 private: 497 U _handler; 498 }; 499 500 /** 501 * @brief Used to process a Dbus name owner changed signal event 502 * 503 * @param[in] handler - Handler function to perform 504 * 505 * @tparam U - The type of the handler 506 * 507 * @return - The NameOwnerChanged signal struct 508 */ 509 template <typename U> 510 auto nameOwnerChanged(U&& handler) 511 { 512 return NameOwner<U>(std::forward<U>(handler)); 513 } 514 515 /** 516 * @brief Used to process the init of a name owner event 517 * 518 * @param[in] handler - Handler function to perform 519 * 520 * @tparam U - The type of the handler 521 * 522 * @return - The NameOwnerChanged signal struct 523 */ 524 template <typename U> 525 auto nameHasOwner(U&& handler) 526 { 527 return NameOwner<U>(std::forward<U>(handler)); 528 } 529 530 } // namespace control 531 } // namespace fan 532 } // namespace phosphor 533