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 11namespace brillo { 12namespace dbus_utils { 13 14void AppendValueToWriter(dbus::MessageWriter* writer, bool value) { 15 writer->AppendBool(value); 16} 17 18void AppendValueToWriter(dbus::MessageWriter* writer, uint8_t value) { 19 writer->AppendByte(value); 20} 21 22void AppendValueToWriter(dbus::MessageWriter* writer, int16_t value) { 23 writer->AppendInt16(value); 24} 25 26void AppendValueToWriter(dbus::MessageWriter* writer, uint16_t value) { 27 writer->AppendUint16(value); 28} 29 30void AppendValueToWriter(dbus::MessageWriter* writer, int32_t value) { 31 writer->AppendInt32(value); 32} 33 34void AppendValueToWriter(dbus::MessageWriter* writer, uint32_t value) { 35 writer->AppendUint32(value); 36} 37 38void AppendValueToWriter(dbus::MessageWriter* writer, int64_t value) { 39 writer->AppendInt64(value); 40} 41 42void AppendValueToWriter(dbus::MessageWriter* writer, uint64_t value) { 43 writer->AppendUint64(value); 44} 45 46void AppendValueToWriter(dbus::MessageWriter* writer, double value) { 47 writer->AppendDouble(value); 48} 49 50void AppendValueToWriter(dbus::MessageWriter* writer, 51 const std::string& value) { 52 writer->AppendString(value); 53} 54 55void AppendValueToWriter(dbus::MessageWriter* writer, const char* value) { 56 AppendValueToWriter(writer, std::string(value)); 57} 58 59void AppendValueToWriter(dbus::MessageWriter* writer, 60 const dbus::ObjectPath& value) { 61 writer->AppendObjectPath(value); 62} 63 64void AppendValueToWriter(dbus::MessageWriter* writer, 65 const dbus::FileDescriptor& value) { 66 writer->AppendFileDescriptor(value); 67} 68 69void AppendValueToWriter(dbus::MessageWriter* writer, 70 const brillo::Any& value) { 71 value.AppendToDBusMessageWriter(writer); 72} 73 74/////////////////////////////////////////////////////////////////////////////// 75 76bool 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 82bool 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 88bool 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 94bool 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 100bool 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 106bool 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 112bool 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 118bool 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 124bool 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 130bool 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 136bool 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 142bool 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 152namespace { 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. 157template<typename T> 158bool 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. 168template<typename T> 169bool PopTypedArrayFromReader(dbus::MessageReader* reader, 170 brillo::Any* value) { 171 return PopTypedValueFromReader<std::vector<T>>(reader, value); 172} 173 174// std::map<KEY, VALUE> overload. 175template<typename KEY, typename VALUE> 176bool 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. 183bool 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. 246bool 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 269bool 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