// Copyright 2014 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <brillo/dbus/data_serialization.h> #include <base/logging.h> #include <brillo/any.h> #include <brillo/variant_dictionary.h> namespace brillo { namespace dbus_utils { void AppendValueToWriter(dbus::MessageWriter* writer, bool value) { writer->AppendBool(value); } void AppendValueToWriter(dbus::MessageWriter* writer, uint8_t value) { writer->AppendByte(value); } void AppendValueToWriter(dbus::MessageWriter* writer, int16_t value) { writer->AppendInt16(value); } void AppendValueToWriter(dbus::MessageWriter* writer, uint16_t value) { writer->AppendUint16(value); } void AppendValueToWriter(dbus::MessageWriter* writer, int32_t value) { writer->AppendInt32(value); } void AppendValueToWriter(dbus::MessageWriter* writer, uint32_t value) { writer->AppendUint32(value); } void AppendValueToWriter(dbus::MessageWriter* writer, int64_t value) { writer->AppendInt64(value); } void AppendValueToWriter(dbus::MessageWriter* writer, uint64_t value) { writer->AppendUint64(value); } void AppendValueToWriter(dbus::MessageWriter* writer, double value) { writer->AppendDouble(value); } void AppendValueToWriter(dbus::MessageWriter* writer, const std::string& value) { writer->AppendString(value); } void AppendValueToWriter(dbus::MessageWriter* writer, const char* value) { AppendValueToWriter(writer, std::string(value)); } void AppendValueToWriter(dbus::MessageWriter* writer, const dbus::ObjectPath& value) { writer->AppendObjectPath(value); } void AppendValueToWriter(dbus::MessageWriter* writer, const base::ScopedFD& value) { writer->AppendFileDescriptor(value.get()); } void AppendValueToWriter(dbus::MessageWriter* writer, const brillo::Any& value) { value.AppendToDBusMessageWriter(writer); } /////////////////////////////////////////////////////////////////////////////// bool PopValueFromReader(dbus::MessageReader* reader, bool* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopBool(value); } bool PopValueFromReader(dbus::MessageReader* reader, uint8_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopByte(value); } bool PopValueFromReader(dbus::MessageReader* reader, int16_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopInt16(value); } bool PopValueFromReader(dbus::MessageReader* reader, uint16_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopUint16(value); } bool PopValueFromReader(dbus::MessageReader* reader, int32_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopInt32(value); } bool PopValueFromReader(dbus::MessageReader* reader, uint32_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopUint32(value); } bool PopValueFromReader(dbus::MessageReader* reader, int64_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopInt64(value); } bool PopValueFromReader(dbus::MessageReader* reader, uint64_t* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopUint64(value); } bool PopValueFromReader(dbus::MessageReader* reader, double* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopDouble(value); } bool PopValueFromReader(dbus::MessageReader* reader, std::string* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopString(value); } bool PopValueFromReader(dbus::MessageReader* reader, dbus::ObjectPath* value) { dbus::MessageReader variant_reader(nullptr); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopObjectPath(value); } bool PopValueFromReader(dbus::MessageReader* reader, base::ScopedFD* value) { dbus::MessageReader variant_reader(nullptr); bool ok = details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopFileDescriptor(value); return ok; } namespace { // Helper methods for PopValueFromReader(dbus::MessageReader*, Any*) // implementation. Pops a value of particular type from |reader| and assigns // it to |value| of type Any. template<typename T> bool PopTypedValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { T data{}; if (!PopValueFromReader(reader, &data)) return false; *value = std::move(data); return true; } // std::vector<T> overload. template<typename T> bool PopTypedArrayFromReader(dbus::MessageReader* reader, brillo::Any* value) { return PopTypedValueFromReader<std::vector<T>>(reader, value); } // std::map<KEY, VALUE> overload. template<typename KEY, typename VALUE> bool PopTypedMapFromReader(dbus::MessageReader* reader, brillo::Any* value) { return PopTypedValueFromReader<std::map<KEY, VALUE>>(reader, value); } // Helper methods for reading common ARRAY signatures into a Variant. // Note that only common types are supported. If an additional specific // type signature is required, feel free to add support for it. bool PopArrayValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { std::string signature = reader->GetDataSignature(); if (signature == "ab") return PopTypedArrayFromReader<bool>(reader, value); else if (signature == "ay") return PopTypedArrayFromReader<uint8_t>(reader, value); else if (signature == "an") return PopTypedArrayFromReader<int16_t>(reader, value); else if (signature == "aq") return PopTypedArrayFromReader<uint16_t>(reader, value); else if (signature == "ai") return PopTypedArrayFromReader<int32_t>(reader, value); else if (signature == "au") return PopTypedArrayFromReader<uint32_t>(reader, value); else if (signature == "ax") return PopTypedArrayFromReader<int64_t>(reader, value); else if (signature == "at") return PopTypedArrayFromReader<uint64_t>(reader, value); else if (signature == "ad") return PopTypedArrayFromReader<double>(reader, value); else if (signature == "as") return PopTypedArrayFromReader<std::string>(reader, value); else if (signature == "ao") return PopTypedArrayFromReader<dbus::ObjectPath>(reader, value); else if (signature == "av") return PopTypedArrayFromReader<brillo::Any>(reader, value); else if (signature == "a{ss}") return PopTypedMapFromReader<std::string, std::string>(reader, value); else if (signature == "a{sv}") return PopTypedValueFromReader<brillo::VariantDictionary>(reader, value); else if (signature == "aa{ss}") return PopTypedArrayFromReader< std::map<std::string, std::string>>(reader, value); else if (signature == "aa{sv}") return PopTypedArrayFromReader<brillo::VariantDictionary>(reader, value); else if (signature == "a{sa{ss}}") return PopTypedMapFromReader< std::string, std::map<std::string, std::string>>(reader, value); else if (signature == "a{sa{sv}}") return PopTypedMapFromReader< std::string, brillo::VariantDictionary>(reader, value); else if (signature == "a{say}") return PopTypedMapFromReader< std::string, std::vector<uint8_t>>(reader, value); else if (signature == "a{uv}") return PopTypedMapFromReader<uint32_t, brillo::Any>(reader, value); else if (signature == "a(su)") return PopTypedArrayFromReader< std::tuple<std::string, uint32_t>>(reader, value); else if (signature == "a{uu}") return PopTypedMapFromReader<uint32_t, uint32_t>(reader, value); else if (signature == "a(uu)") return PopTypedArrayFromReader< std::tuple<uint32_t, uint32_t>>(reader, value); // When a use case for particular array signature is found, feel free // to add handing for it here. LOG(ERROR) << "Variant de-serialization of array containing data of " << "type '" << signature << "' is not yet supported"; return false; } // Helper methods for reading common STRUCT signatures into a Variant. // Note that only common types are supported. If an additional specific // type signature is required, feel free to add support for it. bool PopStructValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { std::string signature = reader->GetDataSignature(); if (signature == "(ii)") return PopTypedValueFromReader<std::tuple<int, int>>(reader, value); else if (signature == "(ss)") return PopTypedValueFromReader<std::tuple<std::string, std::string>>(reader, value); else if (signature == "(ub)") return PopTypedValueFromReader<std::tuple<uint32_t, bool>>(reader, value); else if (signature == "(uu)") return PopTypedValueFromReader<std::tuple<uint32_t, uint32_t>>(reader, value); // When a use case for particular struct signature is found, feel free // to add handing for it here. LOG(ERROR) << "Variant de-serialization of structs of type '" << signature << "' is not yet supported"; return false; } } // anonymous namespace bool PopValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { dbus::MessageReader variant_reader(nullptr); if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader)) return false; switch (reader->GetDataType()) { case dbus::Message::BYTE: return PopTypedValueFromReader<uint8_t>(reader, value); case dbus::Message::BOOL: return PopTypedValueFromReader<bool>(reader, value); case dbus::Message::INT16: return PopTypedValueFromReader<int16_t>(reader, value); case dbus::Message::UINT16: return PopTypedValueFromReader<uint16_t>(reader, value); case dbus::Message::INT32: return PopTypedValueFromReader<int32_t>(reader, value); case dbus::Message::UINT32: return PopTypedValueFromReader<uint32_t>(reader, value); case dbus::Message::INT64: return PopTypedValueFromReader<int64_t>(reader, value); case dbus::Message::UINT64: return PopTypedValueFromReader<uint64_t>(reader, value); case dbus::Message::DOUBLE: return PopTypedValueFromReader<double>(reader, value); case dbus::Message::STRING: return PopTypedValueFromReader<std::string>(reader, value); case dbus::Message::OBJECT_PATH: return PopTypedValueFromReader<dbus::ObjectPath>(reader, value); case dbus::Message::ARRAY: return PopArrayValueFromReader(reader, value); case dbus::Message::STRUCT: return PopStructValueFromReader(reader, value); case dbus::Message::DICT_ENTRY: LOG(ERROR) << "Variant of DICT_ENTRY is invalid"; return false; case dbus::Message::VARIANT: LOG(ERROR) << "Variant containing a variant is invalid"; return false; case dbus::Message::UNIX_FD: CHECK(dbus::IsDBusTypeUnixFdSupported()) << "UNIX_FD data not supported"; // base::ScopedFD is not a copyable type. Cannot be returned via // brillo::Any. Fail here. LOG(ERROR) << "Cannot return FileDescriptor via Any"; return false; default: LOG(FATAL) << "Unknown D-Bus data type: " << variant_reader.GetDataType(); return false; } return true; } } // namespace dbus_utils } // namespace brillo