blob: a971eab2003a63b6e741582a4f5f5e37e7985d08 [file] [log] [blame]
keybuk@chromium.orge34b29e2012-02-08 08:48:35 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
satorux@chromium.orgb684e272011-07-31 04:13:31 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "dbus/message.h"
6
rharrison@chromium.org3d530352012-02-10 03:14:08 +09007#include <string>
8
satorux@chromium.orgb684e272011-07-31 04:13:31 +09009#include "base/format_macros.h"
10#include "base/logging.h"
ricea1bd48b92015-09-19 07:26:10 +090011#include "base/numerics/safe_conversions.h"
ricea6d265ec2015-07-02 00:56:50 +090012#include "base/strings/string_number_conversions.h"
avi@chromium.orgffcdb952013-06-11 16:27:01 +090013#include "base/strings/string_util.h"
14#include "base/strings/stringprintf.h"
keybuk@google.combf4649a2012-02-15 06:29:06 +090015#include "dbus/object_path.h"
rharrison@chromium.org3d530352012-02-10 03:14:08 +090016#include "third_party/protobuf/src/google/protobuf/message_lite.h"
satorux@chromium.orgb684e272011-07-31 04:13:31 +090017
satorux@chromium.org8facb242011-08-11 07:34:02 +090018namespace {
19
20// Appends the header name and the value to |output|, if the value is
21// not empty.
davemoore@chromium.orgb8ebdc62012-07-26 04:29:57 +090022void AppendStringHeader(const std::string& header_name,
23 const std::string& header_value,
24 std::string* output) {
satorux@chromium.org8facb242011-08-11 07:34:02 +090025 if (!header_value.empty()) {
26 *output += header_name + ": " + header_value + "\n";
27 }
28}
29
30// Appends the header name and the value to |output|, if the value is
31// nonzero.
davemoore@chromium.orgb8ebdc62012-07-26 04:29:57 +090032void AppendUint32Header(const std::string& header_name,
avi0ad0ce02015-12-23 03:12:45 +090033 uint32_t header_value,
davemoore@chromium.orgb8ebdc62012-07-26 04:29:57 +090034 std::string* output) {
satorux@chromium.org8facb242011-08-11 07:34:02 +090035 if (header_value != 0) {
ricea1bd48b92015-09-19 07:26:10 +090036 *output += (header_name + ": " + base::UintToString(header_value) + "\n");
satorux@chromium.org8facb242011-08-11 07:34:02 +090037 }
38}
39
40} // namespace
41
satorux@chromium.orgb684e272011-07-31 04:13:31 +090042namespace dbus {
43
davemoore@chromium.orgb8ebdc62012-07-26 04:29:57 +090044bool IsDBusTypeUnixFdSupported() {
45 int major = 0, minor = 0, micro = 0;
46 dbus_get_version(&major, &minor, &micro);
47 return major >= 1 && minor >= 4;
48}
49
Hidehiko Abe1f025e62017-09-12 12:55:06 +090050Message::Message() : raw_message_(nullptr) {}
satorux@chromium.orgb684e272011-07-31 04:13:31 +090051
52Message::~Message() {
53 if (raw_message_)
54 dbus_message_unref(raw_message_);
55}
56
satorux@chromium.orgffa83a92011-08-24 12:32:06 +090057void Message::Init(DBusMessage* raw_message) {
58 DCHECK(!raw_message_);
59 raw_message_ = raw_message;
60}
61
satorux@chromium.orgb684e272011-07-31 04:13:31 +090062Message::MessageType Message::GetMessageType() {
63 if (!raw_message_)
64 return MESSAGE_INVALID;
65 const int type = dbus_message_get_type(raw_message_);
66 return static_cast<Message::MessageType>(type);
67}
68
satorux@chromium.orgffa83a92011-08-24 12:32:06 +090069std::string Message::GetMessageTypeAsString() {
70 switch (GetMessageType()) {
71 case MESSAGE_INVALID:
72 return "MESSAGE_INVALID";
73 case MESSAGE_METHOD_CALL:
74 return "MESSAGE_METHOD_CALL";
75 case MESSAGE_METHOD_RETURN:
76 return "MESSAGE_METHOD_RETURN";
77 case MESSAGE_SIGNAL:
78 return "MESSAGE_SIGNAL";
79 case MESSAGE_ERROR:
80 return "MESSAGE_ERROR";
81 }
82 NOTREACHED();
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +090083 return std::string();
satorux@chromium.orgb684e272011-07-31 04:13:31 +090084}
85
86std::string Message::ToStringInternal(const std::string& indent,
87 MessageReader* reader) {
88 const char* kBrokenMessage = "[broken message]";
89 std::string output;
90 while (reader->HasMoreData()) {
91 const DataType type = reader->GetDataType();
92 switch (type) {
93 case BYTE: {
avi0ad0ce02015-12-23 03:12:45 +090094 uint8_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +090095 if (!reader->PopByte(&value))
96 return kBrokenMessage;
ricea1bd48b92015-09-19 07:26:10 +090097 output += indent + "byte " + base::UintToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +090098 break;
99 }
100 case BOOL: {
101 bool value = false;
102 if (!reader->PopBool(&value))
103 return kBrokenMessage;
104 output += indent + "bool " + (value ? "true" : "false") + "\n";
105 break;
106 }
107 case INT16: {
avi0ad0ce02015-12-23 03:12:45 +0900108 int16_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900109 if (!reader->PopInt16(&value))
110 return kBrokenMessage;
avi0ad0ce02015-12-23 03:12:45 +0900111 output += indent + "int16_t " + base::IntToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900112 break;
113 }
114 case UINT16: {
avi0ad0ce02015-12-23 03:12:45 +0900115 uint16_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900116 if (!reader->PopUint16(&value))
117 return kBrokenMessage;
avi0ad0ce02015-12-23 03:12:45 +0900118 output += indent + "uint16_t " + base::UintToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900119 break;
120 }
121 case INT32: {
avi0ad0ce02015-12-23 03:12:45 +0900122 int32_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900123 if (!reader->PopInt32(&value))
124 return kBrokenMessage;
avi0ad0ce02015-12-23 03:12:45 +0900125 output += indent + "int32_t " + base::IntToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900126 break;
127 }
128 case UINT32: {
avi0ad0ce02015-12-23 03:12:45 +0900129 uint32_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900130 if (!reader->PopUint32(&value))
131 return kBrokenMessage;
avi0ad0ce02015-12-23 03:12:45 +0900132 output += indent + "uint32_t " + base::UintToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900133 break;
134 }
135 case INT64: {
avi0ad0ce02015-12-23 03:12:45 +0900136 int64_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900137 if (!reader->PopInt64(&value))
138 return kBrokenMessage;
avi0ad0ce02015-12-23 03:12:45 +0900139 output += (indent + "int64_t " + base::Int64ToString(value) + "\n");
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900140 break;
141 }
142 case UINT64: {
avi0ad0ce02015-12-23 03:12:45 +0900143 uint64_t value = 0;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900144 if (!reader->PopUint64(&value))
145 return kBrokenMessage;
Daniel Cheng9b8647c2017-12-12 12:51:09 +0900146 output += (indent + "uint64_t " + base::NumberToString(value) + "\n");
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900147 break;
148 }
149 case DOUBLE: {
150 double value = 0;
151 if (!reader->PopDouble(&value))
152 return kBrokenMessage;
Brett Wilsonbd836f12017-12-01 10:25:11 +0900153 output += indent + "double " + base::NumberToString(value) + "\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900154 break;
155 }
156 case STRING: {
157 std::string value;
158 if (!reader->PopString(&value))
159 return kBrokenMessage;
satorux@chromium.org6a7aa372012-06-08 01:41:26 +0900160 // Truncate if the string is longer than the limit.
161 const size_t kTruncateLength = 100;
162 if (value.size() < kTruncateLength) {
163 output += indent + "string \"" + value + "\"\n";
164 } else {
165 std::string truncated;
brettw@chromium.org1f044f32013-12-04 07:05:28 +0900166 base::TruncateUTF8ToByteSize(value, kTruncateLength, &truncated);
thakis@chromium.orgf3b469a2013-07-31 11:29:01 +0900167 base::StringAppendF(&truncated, "... (%" PRIuS " bytes in total)",
satorux@chromium.org6a7aa372012-06-08 01:41:26 +0900168 value.size());
169 output += indent + "string \"" + truncated + "\"\n";
170 }
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900171 break;
172 }
173 case OBJECT_PATH: {
keybuk@google.combf4649a2012-02-15 06:29:06 +0900174 ObjectPath value;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900175 if (!reader->PopObjectPath(&value))
176 return kBrokenMessage;
keybuk@google.combf4649a2012-02-15 06:29:06 +0900177 output += indent + "object_path \"" + value.value() + "\"\n";
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900178 break;
179 }
180 case ARRAY: {
181 MessageReader sub_reader(this);
182 if (!reader->PopArray(&sub_reader))
183 return kBrokenMessage;
184 output += indent + "array [\n";
185 output += ToStringInternal(indent + " ", &sub_reader);
186 output += indent + "]\n";
187 break;
188 }
189 case STRUCT: {
190 MessageReader sub_reader(this);
191 if (!reader->PopStruct(&sub_reader))
192 return kBrokenMessage;
193 output += indent + "struct {\n";
194 output += ToStringInternal(indent + " ", &sub_reader);
195 output += indent + "}\n";
196 break;
197 }
198 case DICT_ENTRY: {
199 MessageReader sub_reader(this);
200 if (!reader->PopDictEntry(&sub_reader))
201 return kBrokenMessage;
202 output += indent + "dict entry {\n";
203 output += ToStringInternal(indent + " ", &sub_reader);
204 output += indent + "}\n";
205 break;
206 }
207 case VARIANT: {
208 MessageReader sub_reader(this);
209 if (!reader->PopVariant(&sub_reader))
210 return kBrokenMessage;
211 output += indent + "variant ";
212 output += ToStringInternal(indent + " ", &sub_reader);
213 break;
214 }
sleffler@chromium.org22fab402012-03-30 15:46:20 +0900215 case UNIX_FD: {
davemoore@chromium.orgb8ebdc62012-07-26 04:29:57 +0900216 CHECK(IsDBusTypeUnixFdSupported());
sleffler@chromium.org22fab402012-03-30 15:46:20 +0900217
hashimoto6550fcf2016-09-14 13:05:02 +0900218 base::ScopedFD file_descriptor;
sleffler@chromium.org22fab402012-03-30 15:46:20 +0900219 if (!reader->PopFileDescriptor(&file_descriptor))
220 return kBrokenMessage;
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900221 output +=
222 indent + "fd#" + base::IntToString(file_descriptor.get()) + "\n";
sleffler@chromium.org22fab402012-03-30 15:46:20 +0900223 break;
224 }
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900225 default:
226 LOG(FATAL) << "Unknown type: " << type;
227 }
228 }
229 return output;
230}
231
232// The returned string consists of message headers such as
233// destination if any, followed by a blank line, and the message
234// payload. For example, a MethodCall's ToString() will look like:
235//
236// destination: com.example.Service
237// path: /com/example/Object
238// interface: com.example.Interface
239// member: SomeMethod
240//
241// string \"payload\"
242// ...
243std::string Message::ToString() {
244 if (!raw_message_)
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900245 return std::string();
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900246
247 // Generate headers first.
248 std::string headers;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900249 AppendStringHeader("message_type", GetMessageTypeAsString(), &headers);
satorux@chromium.org8facb242011-08-11 07:34:02 +0900250 AppendStringHeader("destination", GetDestination(), &headers);
keybuk@google.combf4649a2012-02-15 06:29:06 +0900251 AppendStringHeader("path", GetPath().value(), &headers);
satorux@chromium.org8facb242011-08-11 07:34:02 +0900252 AppendStringHeader("interface", GetInterface(), &headers);
253 AppendStringHeader("member", GetMember(), &headers);
254 AppendStringHeader("error_name", GetErrorName(), &headers);
255 AppendStringHeader("sender", GetSender(), &headers);
benchanbefafc82014-08-25 20:16:56 +0900256 AppendStringHeader("signature", GetSignature(), &headers);
satorux@chromium.org8facb242011-08-11 07:34:02 +0900257 AppendUint32Header("serial", GetSerial(), &headers);
258 AppendUint32Header("reply_serial", GetReplySerial(), &headers);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900259
260 // Generate the payload.
261 MessageReader reader(this);
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900262 return headers + "\n" + ToStringInternal(std::string(), &reader);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900263}
264
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900265bool Message::SetDestination(const std::string& destination) {
266 return dbus_message_set_destination(raw_message_, destination.c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900267}
268
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900269bool Message::SetPath(const ObjectPath& path) {
270 return dbus_message_set_path(raw_message_, path.value().c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900271}
272
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900273bool Message::SetInterface(const std::string& interface) {
274 return dbus_message_set_interface(raw_message_, interface.c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900275}
276
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900277bool Message::SetMember(const std::string& member) {
278 return dbus_message_set_member(raw_message_, member.c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900279}
280
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900281bool Message::SetErrorName(const std::string& error_name) {
282 return dbus_message_set_error_name(raw_message_, error_name.c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900283}
284
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900285bool Message::SetSender(const std::string& sender) {
286 return dbus_message_set_sender(raw_message_, sender.c_str());
satorux@chromium.org8facb242011-08-11 07:34:02 +0900287}
288
avi0ad0ce02015-12-23 03:12:45 +0900289void Message::SetSerial(uint32_t serial) {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900290 dbus_message_set_serial(raw_message_, serial);
291}
292
avi0ad0ce02015-12-23 03:12:45 +0900293void Message::SetReplySerial(uint32_t reply_serial) {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900294 dbus_message_set_reply_serial(raw_message_, reply_serial);
295}
296
297std::string Message::GetDestination() {
298 const char* destination = dbus_message_get_destination(raw_message_);
299 return destination ? destination : "";
300}
301
keybuk@google.combf4649a2012-02-15 06:29:06 +0900302ObjectPath Message::GetPath() {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900303 const char* path = dbus_message_get_path(raw_message_);
keybuk@google.combf4649a2012-02-15 06:29:06 +0900304 return ObjectPath(path ? path : "");
satorux@chromium.org8facb242011-08-11 07:34:02 +0900305}
306
307std::string Message::GetInterface() {
308 const char* interface = dbus_message_get_interface(raw_message_);
309 return interface ? interface : "";
310}
311
312std::string Message::GetMember() {
313 const char* member = dbus_message_get_member(raw_message_);
314 return member ? member : "";
315}
316
317std::string Message::GetErrorName() {
318 const char* error_name = dbus_message_get_error_name(raw_message_);
319 return error_name ? error_name : "";
320}
321
322std::string Message::GetSender() {
323 const char* sender = dbus_message_get_sender(raw_message_);
324 return sender ? sender : "";
325}
326
benchanbefafc82014-08-25 20:16:56 +0900327std::string Message::GetSignature() {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900328 const char* signature = dbus_message_get_signature(raw_message_);
329 return signature ? signature : "";
330}
331
avi0ad0ce02015-12-23 03:12:45 +0900332uint32_t Message::GetSerial() {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900333 return dbus_message_get_serial(raw_message_);
334}
335
avi0ad0ce02015-12-23 03:12:45 +0900336uint32_t Message::GetReplySerial() {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900337 return dbus_message_get_reply_serial(raw_message_);
338}
339
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900340//
341// MethodCall implementation.
342//
343
344MethodCall::MethodCall(const std::string& interface_name,
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900345 const std::string& method_name) {
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900346 Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900347
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900348 CHECK(SetInterface(interface_name));
349 CHECK(SetMember(method_name));
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900350}
351
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900352MethodCall::MethodCall() = default;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900353
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900354std::unique_ptr<MethodCall> MethodCall::FromRawMessage(
355 DBusMessage* raw_message) {
satorux@chromium.org8facb242011-08-11 07:34:02 +0900356 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_CALL, dbus_message_get_type(raw_message));
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900357
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900358 std::unique_ptr<MethodCall> method_call(new MethodCall());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900359 method_call->Init(raw_message);
satorux@chromium.org8facb242011-08-11 07:34:02 +0900360 return method_call;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900361}
362
363//
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900364// Signal implementation.
365//
366Signal::Signal(const std::string& interface_name,
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900367 const std::string& method_name) {
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900368 Init(dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL));
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900369
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900370 CHECK(SetInterface(interface_name));
371 CHECK(SetMember(method_name));
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900372}
373
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900374Signal::Signal() = default;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900375
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900376std::unique_ptr<Signal> Signal::FromRawMessage(DBusMessage* raw_message) {
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900377 DCHECK_EQ(DBUS_MESSAGE_TYPE_SIGNAL, dbus_message_get_type(raw_message));
378
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900379 std::unique_ptr<Signal> signal(new Signal());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900380 signal->Init(raw_message);
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900381 return signal;
382}
383
384//
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900385// Response implementation.
386//
387
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900388Response::Response() = default;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900389
dcheng30c5a172016-04-09 07:55:04 +0900390std::unique_ptr<Response> Response::FromRawMessage(DBusMessage* raw_message) {
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900391 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_RETURN,
392 dbus_message_get_type(raw_message));
393
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900394 std::unique_ptr<Response> response(new Response());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900395 response->Init(raw_message);
dcheng6c1ffcf2015-12-28 11:24:50 +0900396 return response;
satorux@chromium.org8facb242011-08-11 07:34:02 +0900397}
398
dcheng30c5a172016-04-09 07:55:04 +0900399std::unique_ptr<Response> Response::FromMethodCall(MethodCall* method_call) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900400 std::unique_ptr<Response> response(new Response());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900401 response->Init(dbus_message_new_method_return(method_call->raw_message()));
dcheng6c1ffcf2015-12-28 11:24:50 +0900402 return response;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900403}
404
dcheng30c5a172016-04-09 07:55:04 +0900405std::unique_ptr<Response> Response::CreateEmpty() {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900406 std::unique_ptr<Response> response(new Response());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900407 response->Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN));
dcheng6c1ffcf2015-12-28 11:24:50 +0900408 return response;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900409}
yuki@chromium.orgd4eedf82013-02-07 18:46:24 +0900410
satorux@chromium.org8facb242011-08-11 07:34:02 +0900411//
412// ErrorResponse implementation.
413//
414
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900415ErrorResponse::ErrorResponse() = default;
satorux@chromium.org8facb242011-08-11 07:34:02 +0900416
dcheng30c5a172016-04-09 07:55:04 +0900417std::unique_ptr<ErrorResponse> ErrorResponse::FromRawMessage(
yuki@chromium.orgd4eedf82013-02-07 18:46:24 +0900418 DBusMessage* raw_message) {
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900419 DCHECK_EQ(DBUS_MESSAGE_TYPE_ERROR, dbus_message_get_type(raw_message));
420
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900421 std::unique_ptr<ErrorResponse> response(new ErrorResponse());
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900422 response->Init(raw_message);
dcheng6c1ffcf2015-12-28 11:24:50 +0900423 return response;
satorux@chromium.orgffa83a92011-08-24 12:32:06 +0900424}
425
dcheng30c5a172016-04-09 07:55:04 +0900426std::unique_ptr<ErrorResponse> ErrorResponse::FromMethodCall(
satorux@chromium.org8facb242011-08-11 07:34:02 +0900427 MethodCall* method_call,
428 const std::string& error_name,
429 const std::string& error_message) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900430 std::unique_ptr<ErrorResponse> response(new ErrorResponse());
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900431 response->Init(dbus_message_new_error(
432 method_call->raw_message(), error_name.c_str(), error_message.c_str()));
dcheng6c1ffcf2015-12-28 11:24:50 +0900433 return response;
satorux@chromium.org8facb242011-08-11 07:34:02 +0900434}
435
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900436//
437// MessageWriter implementation.
438//
439
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900440MessageWriter::MessageWriter(Message* message)
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900441 : message_(message), container_is_open_(false) {
jhawkins@chromium.org69bde422012-02-13 13:12:40 +0900442 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
keybuk@chromium.orge34b29e2012-02-08 08:48:35 +0900443 if (message)
444 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900445}
446
Chris Watkins635e8902017-11-29 16:44:11 +0900447MessageWriter::~MessageWriter() = default;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900448
avi0ad0ce02015-12-23 03:12:45 +0900449void MessageWriter::AppendByte(uint8_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900450 AppendBasic(DBUS_TYPE_BYTE, &value);
451}
452
453void MessageWriter::AppendBool(bool value) {
satorux@chromium.orga566a2c2011-08-05 06:57:21 +0900454 // The size of dbus_bool_t and the size of bool are different. The
455 // former is always 4 per dbus-types.h, whereas the latter is usually 1.
456 // dbus_message_iter_append_basic() used in AppendBasic() expects four
457 // bytes for DBUS_TYPE_BOOLEAN, so we must pass a dbus_bool_t, instead
458 // of a bool, to AppendBasic().
Ryo Hashimoto30ac2372017-09-25 16:06:14 +0900459 dbus_bool_t dbus_value = value ? 1 : 0;
satorux@chromium.orga566a2c2011-08-05 06:57:21 +0900460 AppendBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900461}
462
avi0ad0ce02015-12-23 03:12:45 +0900463void MessageWriter::AppendInt16(int16_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900464 AppendBasic(DBUS_TYPE_INT16, &value);
465}
466
avi0ad0ce02015-12-23 03:12:45 +0900467void MessageWriter::AppendUint16(uint16_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900468 AppendBasic(DBUS_TYPE_UINT16, &value);
469}
470
avi0ad0ce02015-12-23 03:12:45 +0900471void MessageWriter::AppendInt32(int32_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900472 AppendBasic(DBUS_TYPE_INT32, &value);
473}
474
avi0ad0ce02015-12-23 03:12:45 +0900475void MessageWriter::AppendUint32(uint32_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900476 AppendBasic(DBUS_TYPE_UINT32, &value);
477}
478
avi0ad0ce02015-12-23 03:12:45 +0900479void MessageWriter::AppendInt64(int64_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900480 AppendBasic(DBUS_TYPE_INT64, &value);
481}
482
avi0ad0ce02015-12-23 03:12:45 +0900483void MessageWriter::AppendUint64(uint64_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900484 AppendBasic(DBUS_TYPE_UINT64, &value);
485}
486
487void MessageWriter::AppendDouble(double value) {
488 AppendBasic(DBUS_TYPE_DOUBLE, &value);
489}
490
491void MessageWriter::AppendString(const std::string& value) {
hashimoto@chromium.org5fdbcf72012-06-05 13:15:50 +0900492 // D-Bus Specification (0.19) says a string "must be valid UTF-8".
brettw@chromium.org89f697b2014-05-07 23:38:26 +0900493 CHECK(base::IsStringUTF8(value));
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900494 const char* pointer = value.c_str();
495 AppendBasic(DBUS_TYPE_STRING, &pointer);
496 // TODO(satorux): It may make sense to return an error here, as the
497 // input string can be large. If needed, we could add something like
498 // bool AppendStringWithErrorChecking().
499}
500
keybuk@google.combf4649a2012-02-15 06:29:06 +0900501void MessageWriter::AppendObjectPath(const ObjectPath& value) {
hashimoto@chromium.org5fdbcf72012-06-05 13:15:50 +0900502 CHECK(value.IsValid());
keybuk@google.combf4649a2012-02-15 06:29:06 +0900503 const char* pointer = value.value().c_str();
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900504 AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
505}
506
507// Ideally, client shouldn't need to supply the signature string, but
508// the underlying D-Bus library requires us to supply this before
509// appending contents to array and variant. It's technically possible
510// for us to design API that doesn't require the signature but it will
511// complicate the implementation so we decided to have the signature
512// parameter. Hopefully, variants are less used in request messages from
513// client side than response message from server side, so this should
514// not be a big issue.
515void MessageWriter::OpenArray(const std::string& signature,
516 MessageWriter* writer) {
517 DCHECK(!container_is_open_);
518
519 const bool success = dbus_message_iter_open_container(
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900520 &raw_message_iter_, DBUS_TYPE_ARRAY, signature.c_str(),
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900521 &writer->raw_message_iter_);
522 CHECK(success) << "Unable to allocate memory";
523 container_is_open_ = true;
524}
525
526void MessageWriter::OpenVariant(const std::string& signature,
527 MessageWriter* writer) {
528 DCHECK(!container_is_open_);
529
530 const bool success = dbus_message_iter_open_container(
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900531 &raw_message_iter_, DBUS_TYPE_VARIANT, signature.c_str(),
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900532 &writer->raw_message_iter_);
533 CHECK(success) << "Unable to allocate memory";
534 container_is_open_ = true;
535}
536
537void MessageWriter::OpenStruct(MessageWriter* writer) {
538 DCHECK(!container_is_open_);
539
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900540 const bool success =
541 dbus_message_iter_open_container(&raw_message_iter_, DBUS_TYPE_STRUCT,
542 nullptr, // Signature should be nullptr.
543 &writer->raw_message_iter_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900544 CHECK(success) << "Unable to allocate memory";
545 container_is_open_ = true;
546}
547
548void MessageWriter::OpenDictEntry(MessageWriter* writer) {
549 DCHECK(!container_is_open_);
550
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900551 const bool success =
552 dbus_message_iter_open_container(&raw_message_iter_, DBUS_TYPE_DICT_ENTRY,
553 nullptr, // Signature should be nullptr.
554 &writer->raw_message_iter_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900555 CHECK(success) << "Unable to allocate memory";
556 container_is_open_ = true;
557}
558
559void MessageWriter::CloseContainer(MessageWriter* writer) {
560 DCHECK(container_is_open_);
561
562 const bool success = dbus_message_iter_close_container(
563 &raw_message_iter_, &writer->raw_message_iter_);
564 CHECK(success) << "Unable to allocate memory";
565 container_is_open_ = false;
566}
567
avi0ad0ce02015-12-23 03:12:45 +0900568void MessageWriter::AppendArrayOfBytes(const uint8_t* values, size_t length) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900569 DCHECK(!container_is_open_);
570 MessageWriter array_writer(message_);
571 OpenArray("y", &array_writer);
572 const bool success = dbus_message_iter_append_fixed_array(
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900573 &(array_writer.raw_message_iter_), DBUS_TYPE_BYTE, &values,
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900574 static_cast<int>(length));
575 CHECK(success) << "Unable to allocate memory";
576 CloseContainer(&array_writer);
577}
578
warxef0f8372016-03-31 06:27:41 +0900579void MessageWriter::AppendArrayOfDoubles(const double* values, size_t length) {
580 DCHECK(!container_is_open_);
581 MessageWriter array_writer(message_);
582 OpenArray("d", &array_writer);
583 const bool success = dbus_message_iter_append_fixed_array(
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900584 &(array_writer.raw_message_iter_), DBUS_TYPE_DOUBLE, &values,
warxef0f8372016-03-31 06:27:41 +0900585 static_cast<int>(length));
586 CHECK(success) << "Unable to allocate memory";
587 CloseContainer(&array_writer);
588}
589
mdm@chromium.org3d2baf02011-09-20 03:22:14 +0900590void MessageWriter::AppendArrayOfStrings(
591 const std::vector<std::string>& strings) {
592 DCHECK(!container_is_open_);
593 MessageWriter array_writer(message_);
594 OpenArray("s", &array_writer);
595 for (size_t i = 0; i < strings.size(); ++i) {
596 array_writer.AppendString(strings[i]);
597 }
598 CloseContainer(&array_writer);
599}
600
satorux@chromium.orgf0ceb482011-08-23 03:28:42 +0900601void MessageWriter::AppendArrayOfObjectPaths(
keybuk@google.combf4649a2012-02-15 06:29:06 +0900602 const std::vector<ObjectPath>& object_paths) {
satorux@chromium.orgf0ceb482011-08-23 03:28:42 +0900603 DCHECK(!container_is_open_);
604 MessageWriter array_writer(message_);
605 OpenArray("o", &array_writer);
606 for (size_t i = 0; i < object_paths.size(); ++i) {
607 array_writer.AppendObjectPath(object_paths[i]);
608 }
609 CloseContainer(&array_writer);
610}
611
rharrison@chromium.org3d530352012-02-10 03:14:08 +0900612bool MessageWriter::AppendProtoAsArrayOfBytes(
613 const google::protobuf::MessageLite& protobuf) {
614 std::string serialized_proto;
615 if (!protobuf.SerializeToString(&serialized_proto)) {
616 LOG(ERROR) << "Unable to serialize supplied protocol buffer";
617 return false;
618 }
avi0ad0ce02015-12-23 03:12:45 +0900619 AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(serialized_proto.data()),
rharrison@chromium.org3d530352012-02-10 03:14:08 +0900620 serialized_proto.size());
621 return true;
622}
623
avi0ad0ce02015-12-23 03:12:45 +0900624void MessageWriter::AppendVariantOfByte(uint8_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900625 AppendVariantOfBasic(DBUS_TYPE_BYTE, &value);
626}
627
628void MessageWriter::AppendVariantOfBool(bool value) {
satorux@chromium.orga566a2c2011-08-05 06:57:21 +0900629 // See the comment at MessageWriter::AppendBool().
630 dbus_bool_t dbus_value = value;
631 AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900632}
633
avi0ad0ce02015-12-23 03:12:45 +0900634void MessageWriter::AppendVariantOfInt16(int16_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900635 AppendVariantOfBasic(DBUS_TYPE_INT16, &value);
636}
637
avi0ad0ce02015-12-23 03:12:45 +0900638void MessageWriter::AppendVariantOfUint16(uint16_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900639 AppendVariantOfBasic(DBUS_TYPE_UINT16, &value);
640}
641
avi0ad0ce02015-12-23 03:12:45 +0900642void MessageWriter::AppendVariantOfInt32(int32_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900643 AppendVariantOfBasic(DBUS_TYPE_INT32, &value);
644}
645
avi0ad0ce02015-12-23 03:12:45 +0900646void MessageWriter::AppendVariantOfUint32(uint32_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900647 AppendVariantOfBasic(DBUS_TYPE_UINT32, &value);
648}
649
avi0ad0ce02015-12-23 03:12:45 +0900650void MessageWriter::AppendVariantOfInt64(int64_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900651 AppendVariantOfBasic(DBUS_TYPE_INT64, &value);
652}
653
avi0ad0ce02015-12-23 03:12:45 +0900654void MessageWriter::AppendVariantOfUint64(uint64_t value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900655 AppendVariantOfBasic(DBUS_TYPE_UINT64, &value);
656}
657
658void MessageWriter::AppendVariantOfDouble(double value) {
659 AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value);
660}
661
662void MessageWriter::AppendVariantOfString(const std::string& value) {
663 const char* pointer = value.c_str();
664 AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer);
665}
666
keybuk@google.combf4649a2012-02-15 06:29:06 +0900667void MessageWriter::AppendVariantOfObjectPath(const ObjectPath& value) {
668 const char* pointer = value.value().c_str();
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900669 AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
670}
671
672void MessageWriter::AppendBasic(int dbus_type, const void* value) {
673 DCHECK(!container_is_open_);
674
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900675 const bool success =
676 dbus_message_iter_append_basic(&raw_message_iter_, dbus_type, value);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900677 // dbus_message_iter_append_basic() fails only when there is not enough
678 // memory. We don't return this error as there is nothing we can do when
679 // it fails to allocate memory for a byte etc.
680 CHECK(success) << "Unable to allocate memory";
681}
682
683void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) {
ricea1bd48b92015-09-19 07:26:10 +0900684 const std::string signature(1u, // length
685 base::checked_cast<char>(dbus_type));
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900686 MessageWriter variant_writer(message_);
687 OpenVariant(signature, &variant_writer);
688 variant_writer.AppendBasic(dbus_type, value);
689 CloseContainer(&variant_writer);
690}
691
hashimotodac22fb2016-08-25 01:51:38 +0900692void MessageWriter::AppendFileDescriptor(int value) {
693 CHECK(IsDBusTypeUnixFdSupported());
694 AppendBasic(DBUS_TYPE_UNIX_FD, &value); // This duplicates the FD.
695}
696
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900697//
698// MessageReader implementation.
699//
700
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900701MessageReader::MessageReader(Message* message) : message_(message) {
jhawkins@chromium.org69bde422012-02-13 13:12:40 +0900702 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
keybuk@chromium.orge34b29e2012-02-08 08:48:35 +0900703 if (message)
704 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900705}
706
Chris Watkins635e8902017-11-29 16:44:11 +0900707MessageReader::~MessageReader() = default;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900708
709bool MessageReader::HasMoreData() {
710 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
711 return dbus_type != DBUS_TYPE_INVALID;
712}
713
avi0ad0ce02015-12-23 03:12:45 +0900714bool MessageReader::PopByte(uint8_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900715 return PopBasic(DBUS_TYPE_BYTE, value);
716}
717
718bool MessageReader::PopBool(bool* value) {
satorux@chromium.orga566a2c2011-08-05 06:57:21 +0900719 // Like MessageWriter::AppendBool(), we should copy |value| to
720 // dbus_bool_t, as dbus_message_iter_get_basic() used in PopBasic()
721 // expects four bytes for DBUS_TYPE_BOOLEAN.
722 dbus_bool_t dbus_value = FALSE;
723 const bool success = PopBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
724 *value = static_cast<bool>(dbus_value);
725 return success;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900726}
727
avi0ad0ce02015-12-23 03:12:45 +0900728bool MessageReader::PopInt16(int16_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900729 return PopBasic(DBUS_TYPE_INT16, value);
730}
731
avi0ad0ce02015-12-23 03:12:45 +0900732bool MessageReader::PopUint16(uint16_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900733 return PopBasic(DBUS_TYPE_UINT16, value);
734}
735
avi0ad0ce02015-12-23 03:12:45 +0900736bool MessageReader::PopInt32(int32_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900737 return PopBasic(DBUS_TYPE_INT32, value);
738}
739
avi0ad0ce02015-12-23 03:12:45 +0900740bool MessageReader::PopUint32(uint32_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900741 return PopBasic(DBUS_TYPE_UINT32, value);
742}
743
avi0ad0ce02015-12-23 03:12:45 +0900744bool MessageReader::PopInt64(int64_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900745 return PopBasic(DBUS_TYPE_INT64, value);
746}
747
avi0ad0ce02015-12-23 03:12:45 +0900748bool MessageReader::PopUint64(uint64_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900749 return PopBasic(DBUS_TYPE_UINT64, value);
750}
751
752bool MessageReader::PopDouble(double* value) {
753 return PopBasic(DBUS_TYPE_DOUBLE, value);
754}
755
756bool MessageReader::PopString(std::string* value) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900757 char* tmp_value = nullptr;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900758 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
759 if (success)
760 value->assign(tmp_value);
761 return success;
762}
763
keybuk@google.combf4649a2012-02-15 06:29:06 +0900764bool MessageReader::PopObjectPath(ObjectPath* value) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900765 char* tmp_value = nullptr;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900766 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
767 if (success)
keybuk@google.combf4649a2012-02-15 06:29:06 +0900768 *value = ObjectPath(tmp_value);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900769 return success;
770}
771
772bool MessageReader::PopArray(MessageReader* sub_reader) {
773 return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
774}
775
776bool MessageReader::PopStruct(MessageReader* sub_reader) {
777 return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
778}
779
780bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
781 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
782}
783
784bool MessageReader::PopVariant(MessageReader* sub_reader) {
785 return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
786}
787
avi0ad0ce02015-12-23 03:12:45 +0900788bool MessageReader::PopArrayOfBytes(const uint8_t** bytes, size_t* length) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900789 MessageReader array_reader(message_);
790 if (!PopArray(&array_reader))
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900791 return false;
satorux@chromium.org39a0d9b2011-11-11 11:13:56 +0900792 // An empty array is allowed.
793 if (!array_reader.HasMoreData()) {
794 *length = 0;
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900795 *bytes = nullptr;
satorux@chromium.org39a0d9b2011-11-11 11:13:56 +0900796 return true;
797 }
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900798 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
799 return false;
800 int int_length = 0;
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900801 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, bytes,
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900802 &int_length);
warxef0f8372016-03-31 06:27:41 +0900803 *length = static_cast<size_t>(int_length);
804 return true;
805}
806
807bool MessageReader::PopArrayOfDoubles(const double** doubles, size_t* length) {
808 MessageReader array_reader(message_);
809 if (!PopArray(&array_reader))
810 return false;
811 if (!array_reader.HasMoreData()) {
812 *length = 0;
813 *doubles = nullptr;
814 return true;
815 }
816 if (!array_reader.CheckDataType(DBUS_TYPE_DOUBLE))
817 return false;
818 int int_length = 0;
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900819 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, doubles,
warxef0f8372016-03-31 06:27:41 +0900820 &int_length);
821 *length = static_cast<size_t>(int_length);
satorux@chromium.org39a0d9b2011-11-11 11:13:56 +0900822 return true;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900823}
824
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900825bool MessageReader::PopArrayOfStrings(std::vector<std::string>* strings) {
derat@chromium.org2bf9e5c2014-02-25 00:59:40 +0900826 strings->clear();
mdm@chromium.org3d2baf02011-09-20 03:22:14 +0900827 MessageReader array_reader(message_);
828 if (!PopArray(&array_reader))
derat@chromium.org2bf9e5c2014-02-25 00:59:40 +0900829 return false;
mdm@chromium.org3d2baf02011-09-20 03:22:14 +0900830 while (array_reader.HasMoreData()) {
831 std::string string;
832 if (!array_reader.PopString(&string))
833 return false;
834 strings->push_back(string);
835 }
836 return true;
837}
838
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900839bool MessageReader::PopArrayOfObjectPaths(
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900840 std::vector<ObjectPath>* object_paths) {
derat@chromium.org2bf9e5c2014-02-25 00:59:40 +0900841 object_paths->clear();
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900842 MessageReader array_reader(message_);
843 if (!PopArray(&array_reader))
derat@chromium.org2bf9e5c2014-02-25 00:59:40 +0900844 return false;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900845 while (array_reader.HasMoreData()) {
keybuk@google.combf4649a2012-02-15 06:29:06 +0900846 ObjectPath object_path;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900847 if (!array_reader.PopObjectPath(&object_path))
848 return false;
849 object_paths->push_back(object_path);
850 }
851 return true;
852}
853
rharrison@chromium.org3d530352012-02-10 03:14:08 +0900854bool MessageReader::PopArrayOfBytesAsProto(
855 google::protobuf::MessageLite* protobuf) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900856 DCHECK(protobuf);
857 const char* serialized_buf = nullptr;
rharrison@chromium.org3d530352012-02-10 03:14:08 +0900858 size_t buf_size = 0;
avi0ad0ce02015-12-23 03:12:45 +0900859 if (!PopArrayOfBytes(reinterpret_cast<const uint8_t**>(&serialized_buf),
860 &buf_size)) {
rharrison@chromium.org3d530352012-02-10 03:14:08 +0900861 LOG(ERROR) << "Error reading array of bytes";
862 return false;
863 }
864 if (!protobuf->ParseFromArray(serialized_buf, buf_size)) {
865 LOG(ERROR) << "Failed to parse protocol buffer from array";
866 return false;
867 }
868 return true;
869}
870
avi0ad0ce02015-12-23 03:12:45 +0900871bool MessageReader::PopVariantOfByte(uint8_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900872 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
873}
874
875bool MessageReader::PopVariantOfBool(bool* value) {
satorux@chromium.orga566a2c2011-08-05 06:57:21 +0900876 // See the comment at MessageReader::PopBool().
877 dbus_bool_t dbus_value = FALSE;
878 const bool success = PopVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
879 *value = static_cast<bool>(dbus_value);
880 return success;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900881}
882
avi0ad0ce02015-12-23 03:12:45 +0900883bool MessageReader::PopVariantOfInt16(int16_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900884 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
885}
886
avi0ad0ce02015-12-23 03:12:45 +0900887bool MessageReader::PopVariantOfUint16(uint16_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900888 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
889}
890
avi0ad0ce02015-12-23 03:12:45 +0900891bool MessageReader::PopVariantOfInt32(int32_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900892 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
893}
894
avi0ad0ce02015-12-23 03:12:45 +0900895bool MessageReader::PopVariantOfUint32(uint32_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900896 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
897}
898
avi0ad0ce02015-12-23 03:12:45 +0900899bool MessageReader::PopVariantOfInt64(int64_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900900 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
901}
902
avi0ad0ce02015-12-23 03:12:45 +0900903bool MessageReader::PopVariantOfUint64(uint64_t* value) {
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900904 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
905}
906
907bool MessageReader::PopVariantOfDouble(double* value) {
908 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
909}
910
911bool MessageReader::PopVariantOfString(std::string* value) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900912 char* tmp_value = nullptr;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900913 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
914 if (success)
915 value->assign(tmp_value);
916 return success;
917}
918
keybuk@google.combf4649a2012-02-15 06:29:06 +0900919bool MessageReader::PopVariantOfObjectPath(ObjectPath* value) {
Hidehiko Abe1f025e62017-09-12 12:55:06 +0900920 char* tmp_value = nullptr;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900921 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
922 if (success)
keybuk@google.combf4649a2012-02-15 06:29:06 +0900923 *value = ObjectPath(tmp_value);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900924 return success;
925}
926
927Message::DataType MessageReader::GetDataType() {
928 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
929 return static_cast<Message::DataType>(dbus_type);
930}
931
benchan464afff2014-08-25 15:50:29 +0900932std::string MessageReader::GetDataSignature() {
933 std::string signature;
934 char* raw_signature = dbus_message_iter_get_signature(&raw_message_iter_);
935 if (raw_signature) {
936 signature = raw_signature;
937 dbus_free(raw_signature);
938 }
939 return signature;
940}
941
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900942bool MessageReader::CheckDataType(int dbus_type) {
943 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
944 if (actual_type != dbus_type) {
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900945 VLOG(1) << "Type " << dbus_type << " is expected but got " << actual_type;
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900946 return false;
947 }
948 return true;
949}
950
951bool MessageReader::PopBasic(int dbus_type, void* value) {
952 if (!CheckDataType(dbus_type))
953 return false;
954 // dbus_message_iter_get_basic() here should always work, as we have
955 // already checked the next item's data type in CheckDataType(). Note
956 // that dbus_message_iter_get_basic() is a void function.
957 dbus_message_iter_get_basic(&raw_message_iter_, value);
958 DCHECK(value);
959 dbus_message_iter_next(&raw_message_iter_);
960 return true;
961}
962
963bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
964 DCHECK_NE(this, sub_reader);
965
966 if (!CheckDataType(dbus_type))
967 return false;
Abhishek Bhardwaj76f36522018-05-23 16:22:19 +0900968 dbus_message_iter_recurse(&raw_message_iter_, &sub_reader->raw_message_iter_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900969 dbus_message_iter_next(&raw_message_iter_);
970 return true;
971}
972
973bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900974 MessageReader variant_reader(message_);
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900975 if (!PopVariant(&variant_reader))
976 return false;
977 return variant_reader.PopBasic(dbus_type, value);
978}
979
hashimotodac22fb2016-08-25 01:51:38 +0900980bool MessageReader::PopFileDescriptor(base::ScopedFD* value) {
981 CHECK(IsDBusTypeUnixFdSupported());
982
983 int fd = -1;
984 const bool success = PopBasic(DBUS_TYPE_UNIX_FD, &fd);
985 if (!success)
986 return false;
987
988 *value = base::ScopedFD(fd);
989 return true;
990}
991
satorux@chromium.orgb684e272011-07-31 04:13:31 +0900992} // namespace dbus