// 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 #include #include #include 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 FileDescriptor& 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); return details::DescendIntoVariantIfPresent(&reader, &variant_reader) && reader->PopFileDescriptor(value); } 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 bool PopTypedValueFromReader(dbus::MessageReader* reader, brillo::Any* value) { T data{}; if (!PopValueFromReader(reader, &data)) return false; *value = std::move(data); return true; } // std::vector overload. template bool PopTypedArrayFromReader(dbus::MessageReader* reader, brillo::Any* value) { return PopTypedValueFromReader>(reader, value); } // std::map overload. template bool PopTypedMapFromReader(dbus::MessageReader* reader, brillo::Any* value) { return PopTypedValueFromReader>(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(reader, value); else if (signature == "ay") return PopTypedArrayFromReader(reader, value); else if (signature == "an") return PopTypedArrayFromReader(reader, value); else if (signature == "aq") return PopTypedArrayFromReader(reader, value); else if (signature == "ai") return PopTypedArrayFromReader(reader, value); else if (signature == "au") return PopTypedArrayFromReader(reader, value); else if (signature == "ax") return PopTypedArrayFromReader(reader, value); else if (signature == "at") return PopTypedArrayFromReader(reader, value); else if (signature == "ad") return PopTypedArrayFromReader(reader, value); else if (signature == "as") return PopTypedArrayFromReader(reader, value); else if (signature == "ao") return PopTypedArrayFromReader(reader, value); else if (signature == "av") return PopTypedArrayFromReader(reader, value); else if (signature == "a{ss}") return PopTypedMapFromReader(reader, value); else if (signature == "a{sv}") return PopTypedValueFromReader(reader, value); else if (signature == "aa{ss}") return PopTypedArrayFromReader< std::map>(reader, value); else if (signature == "aa{sv}") return PopTypedArrayFromReader(reader, value); else if (signature == "a{sa{ss}}") return PopTypedMapFromReader< std::string, std::map>(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>(reader, value); else if (signature == "a{uv}") return PopTypedMapFromReader(reader, value); else if (signature == "a(su)") return PopTypedArrayFromReader< std::tuple>(reader, value); else if (signature == "a{uu}") return PopTypedMapFromReader(reader, value); else if (signature == "a(uu)") return PopTypedArrayFromReader< std::tuple>(reader, value); else if (signature == "a(ubay)") return PopTypedArrayFromReader< std::tuple>>(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>(reader, value); else if (signature == "(ss)") return PopTypedValueFromReader>(reader, value); else if (signature == "(ub)") return PopTypedValueFromReader>(reader, value); else if (signature == "(uu)") return PopTypedValueFromReader>(reader, value); else if (signature == "(ua{sv})") return PopTypedValueFromReader< std::tuple>(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(reader, value); case dbus::Message::BOOL: return PopTypedValueFromReader(reader, value); case dbus::Message::INT16: return PopTypedValueFromReader(reader, value); case dbus::Message::UINT16: return PopTypedValueFromReader(reader, value); case dbus::Message::INT32: return PopTypedValueFromReader(reader, value); case dbus::Message::UINT32: return PopTypedValueFromReader(reader, value); case dbus::Message::INT64: return PopTypedValueFromReader(reader, value); case dbus::Message::UINT64: return PopTypedValueFromReader(reader, value); case dbus::Message::DOUBLE: return PopTypedValueFromReader(reader, value); case dbus::Message::STRING: return PopTypedValueFromReader(reader, value); case dbus::Message::OBJECT_PATH: return PopTypedValueFromReader(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"; // File descriptors don't use copyable types. 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; } } } // namespace dbus_utils } // namespace brillo