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{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 236 // When a use case for particular array signature is found, feel free 237 // to add handing for it here. 238 LOG(ERROR) << "Variant de-serialization of array containing data of " 239 << "type '" << signature << "' is not yet supported"; 240 return false; 241 } 242 243 // Helper methods for reading common STRUCT signatures into a Variant. 244 // Note that only common types are supported. If an additional specific 245 // type signature is required, feel free to add support for it. 246 bool PopStructValueFromReader(dbus::MessageReader* reader, 247 brillo::Any* value) { 248 std::string signature = reader->GetDataSignature(); 249 if (signature == "(ii)") 250 return PopTypedValueFromReader<std::tuple<int, int>>(reader, value); 251 else if (signature == "(ss)") 252 return PopTypedValueFromReader<std::tuple<std::string, std::string>>(reader, 253 value); 254 else if (signature == "(ub)") 255 return PopTypedValueFromReader<std::tuple<uint32_t, bool>>(reader, value); 256 else if (signature == "(uu)") 257 return PopTypedValueFromReader<std::tuple<uint32_t, uint32_t>>(reader, 258 value); 259 260 // When a use case for particular struct signature is found, feel free 261 // to add handing for it here. 262 LOG(ERROR) << "Variant de-serialization of structs of type '" << signature 263 << "' is not yet supported"; 264 return false; 265 } 266 267 } // anonymous namespace 268 269 bool PopValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { 270 dbus::MessageReader variant_reader(nullptr); 271 if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader)) 272 return false; 273 274 switch (reader->GetDataType()) { 275 case dbus::Message::BYTE: 276 return PopTypedValueFromReader<uint8_t>(reader, value); 277 case dbus::Message::BOOL: 278 return PopTypedValueFromReader<bool>(reader, value); 279 case dbus::Message::INT16: 280 return PopTypedValueFromReader<int16_t>(reader, value); 281 case dbus::Message::UINT16: 282 return PopTypedValueFromReader<uint16_t>(reader, value); 283 case dbus::Message::INT32: 284 return PopTypedValueFromReader<int32_t>(reader, value); 285 case dbus::Message::UINT32: 286 return PopTypedValueFromReader<uint32_t>(reader, value); 287 case dbus::Message::INT64: 288 return PopTypedValueFromReader<int64_t>(reader, value); 289 case dbus::Message::UINT64: 290 return PopTypedValueFromReader<uint64_t>(reader, value); 291 case dbus::Message::DOUBLE: 292 return PopTypedValueFromReader<double>(reader, value); 293 case dbus::Message::STRING: 294 return PopTypedValueFromReader<std::string>(reader, value); 295 case dbus::Message::OBJECT_PATH: 296 return PopTypedValueFromReader<dbus::ObjectPath>(reader, value); 297 case dbus::Message::ARRAY: 298 return PopArrayValueFromReader(reader, value); 299 case dbus::Message::STRUCT: 300 return PopStructValueFromReader(reader, value); 301 case dbus::Message::DICT_ENTRY: 302 LOG(ERROR) << "Variant of DICT_ENTRY is invalid"; 303 return false; 304 case dbus::Message::VARIANT: 305 LOG(ERROR) << "Variant containing a variant is invalid"; 306 return false; 307 case dbus::Message::UNIX_FD: 308 CHECK(dbus::IsDBusTypeUnixFdSupported()) << "UNIX_FD data not supported"; 309 // dbus::FileDescriptor is not a copyable type. Cannot be returned via 310 // brillo::Any. Fail here. 311 LOG(ERROR) << "Cannot return FileDescriptor via Any"; 312 return false; 313 default: 314 LOG(FATAL) << "Unknown D-Bus data type: " << variant_reader.GetDataType(); 315 return false; 316 } 317 return true; 318 } 319 320 } // namespace dbus_utils 321 } // namespace brillo 322