1 #include <boost/asio.hpp>
2 #include <sdbusplus/asio/connection.hpp>
3 #include <sdbusplus/asio/object_server.hpp>
4 #include <sdbusplus/asio/property.hpp>
5 #include <sdbusplus/bus.hpp>
6 #include <sdbusplus/unpack_properties.hpp>
7 
8 #include <iostream>
9 
10 namespace xyz
11 {
12 namespace demo
13 {
14 
15 const std::string path = "/xyz/demo";
16 const std::string name = "xyz.demo";
17 const std::string interface = "xyz.demo.interface";
18 
19 } // namespace demo
20 } // namespace xyz
21 
22 namespace name
23 {
24 
25 const std::string greetings = "Greetings";
26 const std::string goodbyes = "Goodbyes";
27 const std::string value = "Value";
28 
29 } // namespace name
30 
31 class Application
32 {
33   public:
34     Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
35                 sdbusplus::asio::object_server& objServer) :
36         ioc_(ioc),
37         bus_(bus), objServer_(objServer)
38     {
39         demo_ = objServer_.add_unique_interface(xyz::demo::path,
40                                                 xyz::demo::interface);
41 
42         demo_->register_property_r(name::greetings, std::string(),
43                                    sdbusplus::vtable::property_::const_,
44                                    [this](const auto&) { return greetings_; });
45 
46         demo_->register_property_rw(
47             name::goodbyes, std::string(),
48             sdbusplus::vtable::property_::emits_change,
49             [this](const auto& newPropertyValue, const auto&) {
50                 goodbyes_ = newPropertyValue;
51                 return 1;
52             },
53             [this](const auto&) { return goodbyes_; });
54 
55         demo_->register_property_r(
56             name::value, uint32_t{42}, sdbusplus::vtable::property_::const_,
57             [](const auto& value) -> uint32_t { return value; });
58 
59         demo_->initialize();
60     }
61 
62     uint32_t fatalErrors() const
63     {
64         return fatalErrors_;
65     }
66 
67     auto logSystemErrorCode()
68     {
69         return [this](boost::system::error_code ec) {
70             std::cerr << "Error: " << ec << "\n";
71             ++fatalErrors_;
72         };
73     }
74 
75     void logException(const std::exception& e)
76     {
77         std::cerr << "Error: " << e.what() << "\n";
78         ++fatalErrors_;
79     }
80 
81     void logExpectedException(
82         const sdbusplus::exception::UnpackPropertyError& error)
83     {
84         std::cout << "As expected " << error.what() << " => "
85                   << error.propertyName << " is missing because "
86                   << error.reason << "\n";
87     }
88 
89     void asyncGetAllPropertiesStringTypeOnly()
90     {
91         sdbusplus::asio::getAllProperties(
92             bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface,
93             logSystemErrorCode(),
94             [this](std::vector<std::pair<
95                        std::string, std::variant<std::monostate, std::string>>>&
96                        properties) {
97                 try
98                 {
99                     std::string greetings;
100                     std::string goodbyes;
101                     sdbusplus::unpackProperties(properties, name::greetings,
102                                                 greetings, name::goodbyes,
103                                                 goodbyes);
104 
105                     std::cout << "value of greetings: " << greetings << "\n";
106                     std::cout << "value of goodbyes: " << goodbyes << "\n";
107                 }
108                 catch (const sdbusplus::exception::UnpackPropertyError& error)
109                 {
110                     logException(error);
111                 }
112 
113                 try
114                 {
115                     std::string value;
116                     sdbusplus::unpackProperties(properties, name::value, value);
117 
118                     std::cerr << "Error: it should fail because of "
119                                  "not matched type\n";
120                     ++fatalErrors_;
121                 }
122                 catch (const sdbusplus::exception::UnpackPropertyError& error)
123                 {
124                     logExpectedException(error);
125                 }
126             });
127     }
128 
129     void asyncGetAllProperties()
130     {
131         sdbusplus::asio::getAllProperties(
132             bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface,
133             logSystemErrorCode(),
134             [this](
135                 std::vector<std::pair<std::string,
136                                       std::variant<std::monostate, std::string,
137                                                    uint32_t>>>& properties) {
138                 try
139                 {
140                     std::string greetings;
141                     std::string goodbyes;
142                     uint32_t value = 0u;
143                     sdbusplus::unpackProperties(properties, name::greetings,
144                                                 greetings, name::goodbyes,
145                                                 goodbyes, name::value, value);
146 
147                     std::cout << "value of greetings: " << greetings << "\n";
148                     std::cout << "value of goodbyes: " << goodbyes << "\n";
149                     std::cout << "value of value: " << value << "\n";
150                 }
151                 catch (const sdbusplus::exception::UnpackPropertyError& error)
152                 {
153                     logException(error);
154                 }
155 
156                 try
157                 {
158                     std::string unknownProperty;
159                     sdbusplus::unpackProperties(
160                         properties, "UnknownPropertyName", unknownProperty);
161 
162                     std::cerr << "Error: it should fail because of "
163                                  "missing property\n";
164                     ++fatalErrors_;
165                 }
166                 catch (const sdbusplus::exception::UnpackPropertyError& error)
167                 {
168                     logExpectedException(error);
169                 }
170 
171                 try
172                 {
173                     uint32_t notMatchingType;
174                     sdbusplus::unpackProperties(properties, name::greetings,
175                                                 notMatchingType);
176 
177                     std::cerr << "Error: it should fail because of "
178                                  "not matched type\n";
179                     ++fatalErrors_;
180                 }
181                 catch (const sdbusplus::exception::UnpackPropertyError& error)
182                 {
183                     logExpectedException(error);
184                 }
185             });
186     }
187 
188   private:
189     boost::asio::io_context& ioc_;
190     sdbusplus::asio::connection& bus_;
191     sdbusplus::asio::object_server& objServer_;
192 
193     std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
194     std::string greetings_ = "Hello";
195     std::string goodbyes_ = "Bye";
196 
197     uint32_t fatalErrors_ = 0u;
198 };
199 
200 int main(int, char**)
201 {
202     boost::asio::io_context ioc;
203     boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
204 
205     signals.async_wait(
206         [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
207 
208     auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
209     auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
210 
211     bus->request_name(xyz::demo::name.c_str());
212 
213     Application app(ioc, *bus, *objServer);
214 
215     boost::asio::post(ioc,
216                       [&app] { app.asyncGetAllPropertiesStringTypeOnly(); });
217     boost::asio::post(ioc, [&app] { app.asyncGetAllProperties(); });
218 
219     ioc.run();
220 
221     std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
222 
223     return app.fatalErrors();
224 }
225