Artem Senichev | e8837d5 | 2020-06-07 11:59:04 +0300 | [diff] [blame] | 1 | // SPDX-License-Identifier: Apache-2.0 |
| 2 | // Copyright (C) 2020 YADRO |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #include <systemd/sd-bus.h> |
| 7 | |
| 8 | #include <functional> |
| 9 | #include <map> |
| 10 | #include <set> |
| 11 | #include <string> |
| 12 | #include <vector> |
| 13 | |
| 14 | /** |
| 15 | * @class DbusLoop |
| 16 | * @brief D-Bus based event loop. |
| 17 | */ |
| 18 | class DbusLoop |
| 19 | { |
| 20 | public: |
| 21 | /** @brief Set of possible values of the property. */ |
| 22 | using PropertyValues = std::set<std::string>; |
| 23 | /** @brief Map of properties: name -> watched values. */ |
| 24 | using Properties = std::map<std::string, PropertyValues>; |
| 25 | /** @brief Map of watched properties: interface -> properties. */ |
| 26 | using WatchProperties = std::map<std::string, Properties>; |
| 27 | |
| 28 | DbusLoop(); |
| 29 | ~DbusLoop(); |
| 30 | |
| 31 | /** |
| 32 | * @brief Run worker loop. |
| 33 | * |
| 34 | * @return exit code from loop |
| 35 | */ |
| 36 | int run() const; |
| 37 | |
| 38 | /** |
| 39 | * @brief Stop worker loop. |
| 40 | * |
| 41 | * @param[in] code exit code |
| 42 | */ |
| 43 | void stop(int code) const; |
| 44 | |
| 45 | /** |
| 46 | * @brief Add property change handler. |
| 47 | * |
| 48 | * @param[in] service D-Bus service name (object owner) |
| 49 | * @param[in] objPath path to the D-Bus object |
| 50 | * @param[in] props watched properties description |
| 51 | * @param[in] callback function to call when property get one the listed |
| 52 | * values |
| 53 | * |
| 54 | * @throw std::system_error in case of errors |
| 55 | */ |
| 56 | void addPropertyHandler(const std::string& objPath, |
| 57 | const WatchProperties& props, |
| 58 | std::function<void()> callback); |
| 59 | |
| 60 | /** |
| 61 | * @brief Add IO event handler. |
| 62 | * |
| 63 | * @param[in] fd file descriptor to watch |
| 64 | * @param[in] callback function to call when IO event is occurred |
| 65 | * |
| 66 | * @throw std::system_error in case of errors |
| 67 | */ |
| 68 | void addIoHandler(int fd, std::function<void()> callback); |
| 69 | |
| 70 | /** |
| 71 | * @brief Add signal handler. |
| 72 | * |
| 73 | * @param[in] signal signal to watch |
| 74 | * @param[in] callback function to call when signal is triggered |
| 75 | * |
| 76 | * @throw std::system_error in case of errors |
| 77 | */ |
| 78 | void addSignalHandler(int signal, std::function<void()> callback); |
| 79 | |
| 80 | private: |
| 81 | /** |
| 82 | * @brief D-Bus callback: message handler. |
| 83 | * See sd_bus_message_handler_t for details. |
| 84 | */ |
| 85 | static int msgCallback(sd_bus_message* msg, void* userdata, |
| 86 | sd_bus_error* err); |
| 87 | |
| 88 | /** |
| 89 | * @brief D-Bus callback: signal handler. |
| 90 | * See sd_event_signal_handler_t for details. |
| 91 | */ |
| 92 | static int signalCallback(sd_event_source* src, |
| 93 | const struct signalfd_siginfo* si, |
| 94 | void* userdata); |
| 95 | |
| 96 | /** |
| 97 | * @brief D-Bus callback: IO handler. |
| 98 | * See sd_event_io_handler_t for details. |
| 99 | */ |
| 100 | static int ioCallback(sd_event_source* src, int fd, uint32_t revents, |
| 101 | void* userdata); |
| 102 | |
| 103 | private: |
| 104 | /** @brief D-Bus connection. */ |
| 105 | sd_bus* bus; |
| 106 | /** @brief D-Bus event loop. */ |
| 107 | sd_event* event; |
| 108 | |
| 109 | /** @brief Watched properties. */ |
| 110 | WatchProperties propWatch; |
| 111 | /** @brief Property change handler. */ |
| 112 | std::function<void()> propHandler; |
| 113 | |
| 114 | /** @brief IO handler. */ |
| 115 | std::function<void()> ioHandler; |
| 116 | |
| 117 | /** @brief Signal handlers. */ |
| 118 | std::map<int, std::function<void()>> signalHandlers; |
| 119 | }; |