You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
12 KiB
327 lines
12 KiB
// 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 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<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);
|
|
else if (signature == "a(ubay)")
|
|
return PopTypedArrayFromReader<
|
|
std::tuple<uint32_t, bool, std::vector<uint8_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);
|
|
else if (signature == "(ua{sv})")
|
|
return PopTypedValueFromReader<
|
|
std::tuple<uint32_t, brillo::VariantDictionary>>(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";
|
|
// 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
|