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 14 void AppendValueToWriter(dbus::MessageWriter* writer, bool value) { 15 writer->AppendBool(value); 16 } 17 18 void AppendValueToWriter(dbus::MessageWriter* writer, uint8_t value) { 19 writer->AppendByte(value); 20 } 21 22 void AppendValueToWriter(dbus::MessageWriter* writer, int16_t value) { 23 writer->AppendInt16(value); 24 } 25 26 void AppendValueToWriter(dbus::MessageWriter* writer, uint16_t value) { 27 writer->AppendUint16(value); 28 } 29 30 void AppendValueToWriter(dbus::MessageWriter* writer, int32_t value) { 31 writer->AppendInt32(value); 32 } 33 34 void AppendValueToWriter(dbus::MessageWriter* writer, uint32_t value) { 35 writer->AppendUint32(value); 36 } 37 38 void AppendValueToWriter(dbus::MessageWriter* writer, int64_t value) { 39 writer->AppendInt64(value); 40 } 41 42 void AppendValueToWriter(dbus::MessageWriter* writer, uint64_t value) { 43 writer->AppendUint64(value); 44 } 45 46 void AppendValueToWriter(dbus::MessageWriter* writer, double value) { 47 writer->AppendDouble(value); 48 } 49 50 void AppendValueToWriter(dbus::MessageWriter* writer, 51 const std::string& value) { 52 writer->AppendString(value); 53 } 54 55 void AppendValueToWriter(dbus::MessageWriter* writer, const char* value) { 56 AppendValueToWriter(writer, std::string(value)); 57 } 58 59 void AppendValueToWriter(dbus::MessageWriter* writer, 60 const dbus::ObjectPath& value) { 61 writer->AppendObjectPath(value); 62 } 63 64 void AppendValueToWriter(dbus::MessageWriter* writer, 65 const dbus::FileDescriptor& value) { 66 writer->AppendFileDescriptor(value); 67 } 68 69 void AppendValueToWriter(dbus::MessageWriter* writer, 70 const brillo::Any& value) { 71 value.AppendToDBusMessageWriter(writer); 72 } 73 74 /////////////////////////////////////////////////////////////////////////////// 75 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 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 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 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 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 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 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 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 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 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 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 142 bool PopValueFromReader(dbus::MessageReader* reader, 143 dbus::FileDescriptor* value) { 144 dbus::MessageReader variant_reader(nullptr); 145 bool ok = details::DescendIntoVariantIfPresent(&reader, &variant_reader) && 146 reader->PopFileDescriptor(value); 147 if (ok) 148 value->CheckValidity(); 149 return ok; 150 } 151 152 namespace { 153 154 // Helper methods for PopValueFromReader(dbus::MessageReader*, Any*) 155 // implementation. Pops a value of particular type from |reader| and assigns 156 // it to |value| of type Any. 157 template<typename T> 158 bool PopTypedValueFromReader(dbus::MessageReader* reader, 159 brillo::Any* value) { 160 T data{}; 161 if (!PopValueFromReader(reader, &data)) 162 return false; 163 *value = std::move(data); 164 return true; 165 } 166 167 // std::vector<T> overload. 168 template<typename T> 169 bool PopTypedArrayFromReader(dbus::MessageReader* reader, 170 brillo::Any* value) { 171 return PopTypedValueFromReader<std::vector<T>>(reader, value); 172 } 173 174 // std::map<KEY, VALUE> overload. 175 template<typename KEY, typename VALUE> 176 bool PopTypedMapFromReader(dbus::MessageReader* reader, brillo::Any* value) { 177 return PopTypedValueFromReader<std::map<KEY, VALUE>>(reader, value); 178 } 179 180 // Helper methods for reading common ARRAY signatures into a Variant. 181 // Note that only common types are supported. If an additional specific 182 // type signature is required, feel free to add support for it. 183 bool PopArrayValueFromReader(dbus::MessageReader* reader, 184 brillo::Any* value) { 185 std::string signature = reader->GetDataSignature(); 186 if (signature == "ab") 187 return PopTypedArrayFromReader<bool>(reader, value); 188 else if (signature == "ay") 189 return PopTypedArrayFromReader<uint8_t>(reader, value); 190 else if (signature == "an") 191 return PopTypedArrayFromReader<int16_t>(reader, value); 192 else if (signature == "aq") 193 return PopTypedArrayFromReader<uint16_t>(reader, value); 194 else if (signature == "ai") 195 return PopTypedArrayFromReader<int32_t>(reader, value); 196 else if (signature == "au") 197 return PopTypedArrayFromReader<uint32_t>(reader, value); 198 else if (signature == "ax") 199 return PopTypedArrayFromReader<int64_t>(reader, value); 200 else if (signature == "at") 201 return PopTypedArrayFromReader<uint64_t>(reader, value); 202 else if (signature == "ad") 203 return PopTypedArrayFromReader<double>(reader, value); 204 else if (signature == "as") 205 return PopTypedArrayFromReader<std::string>(reader, value); 206 else if (signature == "ao") 207 return PopTypedArrayFromReader<dbus::ObjectPath>(reader, value); 208 else if (signature == "av") 209 return PopTypedArrayFromReader<brillo::Any>(reader, value); 210 else if (signature == "a{ss}") 211 return PopTypedMapFromReader<std::string, std::string>(reader, value); 212 else if (signature == "a{sv}") 213 return PopTypedValueFromReader<brillo::VariantDictionary>(reader, value); 214 else if (signature == "aa{ss}") 215 return PopTypedArrayFromReader< 216 std::map<std::string, std::string>>(reader, value); 217 else if (signature == "aa{sv}") 218 return PopTypedArrayFromReader<brillo::VariantDictionary>(reader, value); 219 else if (signature == "a{sa{ss}}") 220 return PopTypedMapFromReader< 221 std::string, std::map<std::string, std::string>>(reader, value); 222 else if (signature == "a{sa{sv}}") 223 return PopTypedMapFromReader< 224 std::string, brillo::VariantDictionary>(reader, value); 225 else if (signature == "a{say}") 226 return PopTypedMapFromReader< 227 std::string, std::vector<uint8_t>>(reader, value); 228 else if (signature == "a{uv}") 229 return PopTypedMapFromReader<uint32_t, brillo::Any>(reader, value); 230 else if (signature == "a(su)") 231 return PopTypedArrayFromReader< 232 std::tuple<std::string, uint32_t>>(reader, value); 233 else if (signature == "a{uu}") 234 return PopTypedMapFromReader<uint32_t, uint32_t>(reader, value); 235 else if (signature == "a(uu)") 236 return PopTypedArrayFromReader< 237 std::tuple<uint32_t, uint32_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. 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 263 // When a use case for particular struct signature is found, feel free 264 // to add handing for it here. 265 LOG(ERROR) << "Variant de-serialization of structs of type '" << signature 266 << "' is not yet supported"; 267 return false; 268 } 269 270 } // anonymous namespace 271 272 bool PopValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { 273 dbus::MessageReader variant_reader(nullptr); 274 if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader)) 275 return false; 276 277 switch (reader->GetDataType()) { 278 case dbus::Message::BYTE: 279 return PopTypedValueFromReader<uint8_t>(reader, value); 280 case dbus::Message::BOOL: 281 return PopTypedValueFromReader<bool>(reader, value); 282 case dbus::Message::INT16: 283 return PopTypedValueFromReader<int16_t>(reader, value); 284 case dbus::Message::UINT16: 285 return PopTypedValueFromReader<uint16_t>(reader, value); 286 case dbus::Message::INT32: 287 return PopTypedValueFromReader<int32_t>(reader, value); 288 case dbus::Message::UINT32: 289 return PopTypedValueFromReader<uint32_t>(reader, value); 290 case dbus::Message::INT64: 291 return PopTypedValueFromReader<int64_t>(reader, value); 292 case dbus::Message::UINT64: 293 return PopTypedValueFromReader<uint64_t>(reader, value); 294 case dbus::Message::DOUBLE: 295 return PopTypedValueFromReader<double>(reader, value); 296 case dbus::Message::STRING: 297 return PopTypedValueFromReader<std::string>(reader, value); 298 case dbus::Message::OBJECT_PATH: 299 return PopTypedValueFromReader<dbus::ObjectPath>(reader, value); 300 case dbus::Message::ARRAY: 301 return PopArrayValueFromReader(reader, value); 302 case dbus::Message::STRUCT: 303 return PopStructValueFromReader(reader, value); 304 case dbus::Message::DICT_ENTRY: 305 LOG(ERROR) << "Variant of DICT_ENTRY is invalid"; 306 return false; 307 case dbus::Message::VARIANT: 308 LOG(ERROR) << "Variant containing a variant is invalid"; 309 return false; 310 case dbus::Message::UNIX_FD: 311 CHECK(dbus::IsDBusTypeUnixFdSupported()) << "UNIX_FD data not supported"; 312 // dbus::FileDescriptor is not a copyable type. Cannot be returned via 313 // brillo::Any. Fail here. 314 LOG(ERROR) << "Cannot return FileDescriptor via Any"; 315 return false; 316 default: 317 LOG(FATAL) << "Unknown D-Bus data type: " << variant_reader.GetDataType(); 318 return false; 319 } 320 return true; 321 } 322 323 } // namespace dbus_utils 324 } // namespace brillo 325