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