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{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.
    246 bool 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 
    269 bool 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