xref: /aosp_15_r20/external/libbrillo/brillo/dbus/data_serialization.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <brillo/dbus/data_serialization.h>
6 
7 #include <base/logging.h>
8 #include <brillo/any.h>
9 #include <brillo/variant_dictionary.h>
10 
11 namespace brillo {
12 namespace dbus_utils {
13 
AppendValueToWriter(dbus::MessageWriter * writer,bool value)14 void AppendValueToWriter(dbus::MessageWriter* writer, bool value) {
15   writer->AppendBool(value);
16 }
17 
AppendValueToWriter(dbus::MessageWriter * writer,uint8_t value)18 void AppendValueToWriter(dbus::MessageWriter* writer, uint8_t value) {
19   writer->AppendByte(value);
20 }
21 
AppendValueToWriter(dbus::MessageWriter * writer,int16_t value)22 void AppendValueToWriter(dbus::MessageWriter* writer, int16_t value) {
23   writer->AppendInt16(value);
24 }
25 
AppendValueToWriter(dbus::MessageWriter * writer,uint16_t value)26 void AppendValueToWriter(dbus::MessageWriter* writer, uint16_t value) {
27   writer->AppendUint16(value);
28 }
29 
AppendValueToWriter(dbus::MessageWriter * writer,int32_t value)30 void AppendValueToWriter(dbus::MessageWriter* writer, int32_t value) {
31   writer->AppendInt32(value);
32 }
33 
AppendValueToWriter(dbus::MessageWriter * writer,uint32_t value)34 void AppendValueToWriter(dbus::MessageWriter* writer, uint32_t value) {
35   writer->AppendUint32(value);
36 }
37 
AppendValueToWriter(dbus::MessageWriter * writer,int64_t value)38 void AppendValueToWriter(dbus::MessageWriter* writer, int64_t value) {
39   writer->AppendInt64(value);
40 }
41 
AppendValueToWriter(dbus::MessageWriter * writer,uint64_t value)42 void AppendValueToWriter(dbus::MessageWriter* writer, uint64_t value) {
43   writer->AppendUint64(value);
44 }
45 
AppendValueToWriter(dbus::MessageWriter * writer,double value)46 void AppendValueToWriter(dbus::MessageWriter* writer, double value) {
47   writer->AppendDouble(value);
48 }
49 
AppendValueToWriter(dbus::MessageWriter * writer,const std::string & value)50 void AppendValueToWriter(dbus::MessageWriter* writer,
51                          const std::string& value) {
52   writer->AppendString(value);
53 }
54 
AppendValueToWriter(dbus::MessageWriter * writer,const char * value)55 void AppendValueToWriter(dbus::MessageWriter* writer, const char* value) {
56   AppendValueToWriter(writer, std::string(value));
57 }
58 
AppendValueToWriter(dbus::MessageWriter * writer,const dbus::ObjectPath & value)59 void AppendValueToWriter(dbus::MessageWriter* writer,
60                          const dbus::ObjectPath& value) {
61   writer->AppendObjectPath(value);
62 }
63 
AppendValueToWriter(dbus::MessageWriter * writer,const FileDescriptor & value)64 void AppendValueToWriter(dbus::MessageWriter* writer,
65                          const FileDescriptor& value) {
66   writer->AppendFileDescriptor(value.get());
67 }
68 
AppendValueToWriter(dbus::MessageWriter * writer,const brillo::Any & value)69 void AppendValueToWriter(dbus::MessageWriter* writer,
70                          const brillo::Any& value) {
71   value.AppendToDBusMessageWriter(writer);
72 }
73 
74 ///////////////////////////////////////////////////////////////////////////////
75 
PopValueFromReader(dbus::MessageReader * reader,bool * value)76 bool PopValueFromReader(dbus::MessageReader* reader, bool* value) {
77   dbus::MessageReader variant_reader(nullptr);
78   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
79          reader->PopBool(value);
80 }
81 
PopValueFromReader(dbus::MessageReader * reader,uint8_t * value)82 bool PopValueFromReader(dbus::MessageReader* reader, uint8_t* value) {
83   dbus::MessageReader variant_reader(nullptr);
84   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
85          reader->PopByte(value);
86 }
87 
PopValueFromReader(dbus::MessageReader * reader,int16_t * value)88 bool PopValueFromReader(dbus::MessageReader* reader, int16_t* value) {
89   dbus::MessageReader variant_reader(nullptr);
90   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
91          reader->PopInt16(value);
92 }
93 
PopValueFromReader(dbus::MessageReader * reader,uint16_t * value)94 bool PopValueFromReader(dbus::MessageReader* reader, uint16_t* value) {
95   dbus::MessageReader variant_reader(nullptr);
96   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
97          reader->PopUint16(value);
98 }
99 
PopValueFromReader(dbus::MessageReader * reader,int32_t * value)100 bool PopValueFromReader(dbus::MessageReader* reader, int32_t* value) {
101   dbus::MessageReader variant_reader(nullptr);
102   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
103          reader->PopInt32(value);
104 }
105 
PopValueFromReader(dbus::MessageReader * reader,uint32_t * value)106 bool PopValueFromReader(dbus::MessageReader* reader, uint32_t* value) {
107   dbus::MessageReader variant_reader(nullptr);
108   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
109          reader->PopUint32(value);
110 }
111 
PopValueFromReader(dbus::MessageReader * reader,int64_t * value)112 bool PopValueFromReader(dbus::MessageReader* reader, int64_t* value) {
113   dbus::MessageReader variant_reader(nullptr);
114   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
115          reader->PopInt64(value);
116 }
117 
PopValueFromReader(dbus::MessageReader * reader,uint64_t * value)118 bool PopValueFromReader(dbus::MessageReader* reader, uint64_t* value) {
119   dbus::MessageReader variant_reader(nullptr);
120   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
121          reader->PopUint64(value);
122 }
123 
PopValueFromReader(dbus::MessageReader * reader,double * value)124 bool PopValueFromReader(dbus::MessageReader* reader, double* value) {
125   dbus::MessageReader variant_reader(nullptr);
126   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
127          reader->PopDouble(value);
128 }
129 
PopValueFromReader(dbus::MessageReader * reader,std::string * value)130 bool PopValueFromReader(dbus::MessageReader* reader, std::string* value) {
131   dbus::MessageReader variant_reader(nullptr);
132   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
133          reader->PopString(value);
134 }
135 
PopValueFromReader(dbus::MessageReader * reader,dbus::ObjectPath * value)136 bool PopValueFromReader(dbus::MessageReader* reader, dbus::ObjectPath* value) {
137   dbus::MessageReader variant_reader(nullptr);
138   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
139          reader->PopObjectPath(value);
140 }
141 
PopValueFromReader(dbus::MessageReader * reader,base::ScopedFD * value)142 bool PopValueFromReader(dbus::MessageReader* reader,
143                         base::ScopedFD* value) {
144   dbus::MessageReader variant_reader(nullptr);
145   return details::DescendIntoVariantIfPresent(&reader, &variant_reader) &&
146          reader->PopFileDescriptor(value);
147 }
148 
149 namespace {
150 
151 // Helper methods for PopValueFromReader(dbus::MessageReader*, Any*)
152 // implementation. Pops a value of particular type from |reader| and assigns
153 // it to |value| of type Any.
154 template<typename T>
PopTypedValueFromReader(dbus::MessageReader * reader,brillo::Any * value)155 bool PopTypedValueFromReader(dbus::MessageReader* reader,
156                              brillo::Any* value) {
157   T data{};
158   if (!PopValueFromReader(reader, &data))
159     return false;
160   *value = std::move(data);
161   return true;
162 }
163 
164 // std::vector<T> overload.
165 template<typename T>
PopTypedArrayFromReader(dbus::MessageReader * reader,brillo::Any * value)166 bool PopTypedArrayFromReader(dbus::MessageReader* reader,
167                              brillo::Any* value) {
168   return PopTypedValueFromReader<std::vector<T>>(reader, value);
169 }
170 
171 // std::map<KEY, VALUE> overload.
172 template<typename KEY, typename VALUE>
PopTypedMapFromReader(dbus::MessageReader * reader,brillo::Any * value)173 bool PopTypedMapFromReader(dbus::MessageReader* reader, brillo::Any* value) {
174   return PopTypedValueFromReader<std::map<KEY, VALUE>>(reader, value);
175 }
176 
177 // Helper methods for reading common ARRAY signatures into a Variant.
178 // Note that only common types are supported. If an additional specific
179 // type signature is required, feel free to add support for it.
PopArrayValueFromReader(dbus::MessageReader * reader,brillo::Any * value)180 bool PopArrayValueFromReader(dbus::MessageReader* reader,
181                              brillo::Any* value) {
182   std::string signature = reader->GetDataSignature();
183   if (signature == "ab")
184     return PopTypedArrayFromReader<bool>(reader, value);
185   else if (signature == "ay")
186     return PopTypedArrayFromReader<uint8_t>(reader, value);
187   else if (signature == "an")
188     return PopTypedArrayFromReader<int16_t>(reader, value);
189   else if (signature == "aq")
190     return PopTypedArrayFromReader<uint16_t>(reader, value);
191   else if (signature == "ai")
192     return PopTypedArrayFromReader<int32_t>(reader, value);
193   else if (signature == "au")
194     return PopTypedArrayFromReader<uint32_t>(reader, value);
195   else if (signature == "ax")
196     return PopTypedArrayFromReader<int64_t>(reader, value);
197   else if (signature == "at")
198     return PopTypedArrayFromReader<uint64_t>(reader, value);
199   else if (signature == "ad")
200     return PopTypedArrayFromReader<double>(reader, value);
201   else if (signature == "as")
202     return PopTypedArrayFromReader<std::string>(reader, value);
203   else if (signature == "ao")
204     return PopTypedArrayFromReader<dbus::ObjectPath>(reader, value);
205   else if (signature == "av")
206     return PopTypedArrayFromReader<brillo::Any>(reader, value);
207   else if (signature == "a{ss}")
208     return PopTypedMapFromReader<std::string, std::string>(reader, value);
209   else if (signature == "a{sv}")
210     return PopTypedValueFromReader<brillo::VariantDictionary>(reader, value);
211   else if (signature == "aa{ss}")
212     return PopTypedArrayFromReader<
213         std::map<std::string, std::string>>(reader, value);
214   else if (signature == "aa{sv}")
215     return PopTypedArrayFromReader<brillo::VariantDictionary>(reader, value);
216   else if (signature == "a{sa{ss}}")
217     return PopTypedMapFromReader<
218         std::string, std::map<std::string, std::string>>(reader, value);
219   else if (signature == "a{sa{sv}}")
220     return PopTypedMapFromReader<
221         std::string, brillo::VariantDictionary>(reader, value);
222   else if (signature == "a{say}")
223     return PopTypedMapFromReader<
224         std::string, std::vector<uint8_t>>(reader, value);
225   else if (signature == "a{uv}")
226     return PopTypedMapFromReader<uint32_t, brillo::Any>(reader, value);
227   else if (signature == "a(su)")
228     return PopTypedArrayFromReader<
229         std::tuple<std::string, uint32_t>>(reader, value);
230   else if (signature == "a{uu}")
231     return PopTypedMapFromReader<uint32_t, uint32_t>(reader, value);
232   else if (signature == "a(uu)")
233     return PopTypedArrayFromReader<
234         std::tuple<uint32_t, uint32_t>>(reader, value);
235   else if (signature == "a(ubay)")
236     return PopTypedArrayFromReader<
237         std::tuple<uint32_t, bool, std::vector<uint8_t>>>(reader, value);
238 
239   // When a use case for particular array signature is found, feel free
240   // to add handing for it here.
241   LOG(ERROR) << "Variant de-serialization of array containing data of "
242              << "type '" << signature << "' is not yet supported";
243   return false;
244 }
245 
246 // Helper methods for reading common STRUCT signatures into a Variant.
247 // Note that only common types are supported. If an additional specific
248 // type signature is required, feel free to add support for it.
PopStructValueFromReader(dbus::MessageReader * reader,brillo::Any * value)249 bool PopStructValueFromReader(dbus::MessageReader* reader,
250                               brillo::Any* value) {
251   std::string signature = reader->GetDataSignature();
252   if (signature == "(ii)")
253     return PopTypedValueFromReader<std::tuple<int, int>>(reader, value);
254   else if (signature == "(ss)")
255     return PopTypedValueFromReader<std::tuple<std::string, std::string>>(reader,
256                                                                          value);
257   else if (signature == "(ub)")
258     return PopTypedValueFromReader<std::tuple<uint32_t, bool>>(reader, value);
259   else if (signature == "(uu)")
260     return PopTypedValueFromReader<std::tuple<uint32_t, uint32_t>>(reader,
261                                                                    value);
262   else if (signature == "(ua{sv})")
263     return PopTypedValueFromReader<
264         std::tuple<uint32_t, brillo::VariantDictionary>>(reader, value);
265 
266   // When a use case for particular struct signature is found, feel free
267   // to add handing for it here.
268   LOG(ERROR) << "Variant de-serialization of structs of type '" << signature
269              << "' is not yet supported";
270   return false;
271 }
272 
273 }  // anonymous namespace
274 
PopValueFromReader(dbus::MessageReader * reader,brillo::Any * value)275 bool PopValueFromReader(dbus::MessageReader* reader, brillo::Any* value) {
276   dbus::MessageReader variant_reader(nullptr);
277   if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader))
278     return false;
279 
280   switch (reader->GetDataType()) {
281     case dbus::Message::BYTE:
282       return PopTypedValueFromReader<uint8_t>(reader, value);
283     case dbus::Message::BOOL:
284       return PopTypedValueFromReader<bool>(reader, value);
285     case dbus::Message::INT16:
286       return PopTypedValueFromReader<int16_t>(reader, value);
287     case dbus::Message::UINT16:
288       return PopTypedValueFromReader<uint16_t>(reader, value);
289     case dbus::Message::INT32:
290       return PopTypedValueFromReader<int32_t>(reader, value);
291     case dbus::Message::UINT32:
292       return PopTypedValueFromReader<uint32_t>(reader, value);
293     case dbus::Message::INT64:
294       return PopTypedValueFromReader<int64_t>(reader, value);
295     case dbus::Message::UINT64:
296       return PopTypedValueFromReader<uint64_t>(reader, value);
297     case dbus::Message::DOUBLE:
298       return PopTypedValueFromReader<double>(reader, value);
299     case dbus::Message::STRING:
300       return PopTypedValueFromReader<std::string>(reader, value);
301     case dbus::Message::OBJECT_PATH:
302       return PopTypedValueFromReader<dbus::ObjectPath>(reader, value);
303     case dbus::Message::ARRAY:
304       return PopArrayValueFromReader(reader, value);
305     case dbus::Message::STRUCT:
306       return PopStructValueFromReader(reader, value);
307     case dbus::Message::DICT_ENTRY:
308       LOG(ERROR) << "Variant of DICT_ENTRY is invalid";
309       return false;
310     case dbus::Message::VARIANT:
311       LOG(ERROR) << "Variant containing a variant is invalid";
312       return false;
313     case dbus::Message::UNIX_FD:
314       CHECK(dbus::IsDBusTypeUnixFdSupported()) << "UNIX_FD data not supported";
315       // File descriptors don't use copyable types. Cannot be returned via
316       // brillo::Any. Fail here.
317       LOG(ERROR) << "Cannot return FileDescriptor via Any";
318       return false;
319     default:
320       LOG(FATAL) << "Unknown D-Bus data type: " << variant_reader.GetDataType();
321       return false;
322   }
323 }
324 
325 }  // namespace dbus_utils
326 }  // namespace brillo
327