Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: dbus/message.cc

Issue 7492029: Implement classes used for manipulating D-Bus messages. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium 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 "dbus/message.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/stringprintf.h"
10
11 namespace dbus {
12
13 Message::Message()
14 : raw_message_(NULL) {
15 }
16
17 Message::~Message() {
18 if (raw_message_)
19 dbus_message_unref(raw_message_);
20 }
21
22 Message::MessageType Message::GetMessageType() {
23 if (!raw_message_)
24 return MESSAGE_INVALID;
25 const int type = dbus_message_get_type(raw_message_);
26 return static_cast<Message::MessageType>(type);
27 }
28
29 void Message::reset_raw_message(DBusMessage* raw_message) {
30 if (raw_message_)
31 dbus_message_unref(raw_message_);
32 raw_message_ = raw_message;
33 }
34
35 std::string Message::ToStringInternal(const std::string& indent,
36 MessageReader* reader) {
37 std::string output;
38 while (reader->HasMore()) {
39 const DataType type = reader->GetDataType();
40 switch (type) {
41 case BYTE: {
42 uint8 value = 0;
43 CHECK(reader->PopByte(&value)) << "Broken message";
44 output += indent + "byte " + base::StringPrintf("%d", value) + "\n";
45 break;
46 }
47 case BOOL: {
48 bool value = false;
49 CHECK(reader->PopBool(&value)) << "Broken message";
50 output += indent + "bool " + (value ? "true" : "false") + "\n";
51 break;
52 }
53 case INT16: {
54 int16 value = 0;
55 CHECK(reader->PopInt16(&value)) << "Broken message";
56 output += indent + "int16 " + base::StringPrintf("%d", value) + "\n";
57 break;
58 }
59 case UINT16: {
60 uint16 value = 0;
61 CHECK(reader->PopUint16(&value)) << "Broken message";
62 output += indent + "uint16 " + base::StringPrintf("%d", value) + "\n";
63 break;
64 }
65 case INT32: {
66 int32 value = 0;
67 CHECK(reader->PopInt32(&value)) << "Broken message";
68 output += indent + "int32 " + base::StringPrintf("%d", value) + "\n";
69 break;
70 }
71 case UINT32: {
72 uint32 value = 0;
73 CHECK(reader->PopUint32(&value)) << "Broken message";
74 output += indent + "uint32 " + base::StringPrintf("%u", value) + "\n";
75 break;
76 }
77 case INT64: {
78 int64 value = 0;
79 CHECK(reader->PopInt64(&value)) << "Broken message";
80 output += indent + "int64 " + base::StringPrintf("%ld", value) + "\n";
81 break;
82 }
83 case UINT64: {
84 uint64 value = 0;
85 CHECK(reader->PopUint64(&value)) << "Broken message";
86 output += indent + "uint64 " + base::StringPrintf("%lu", value) + "\n";
87 break;
88 }
89 case DOUBLE: {
90 double value = 0;
91 CHECK(reader->PopDouble(&value)) << "Broken message";
92 output += indent + "double " + base::StringPrintf("%f", value) + "\n";
93 break;
94 }
95 case STRING: {
96 std::string value;
97 CHECK(reader->PopString(&value)) << "Broken message";
98 output += indent + "string \"" + value + "\"\n";
99 break;
100 }
101 case OBJECT_PATH: {
102 std::string value;
103 CHECK(reader->PopObjectPath(&value)) << "Broken message";
104 output += indent + "object_path \"" + value + "\"\n";
105 break;
106 }
107 case ARRAY: {
108 MessageReader sub_reader(this);
109 CHECK(reader->PopArray(&sub_reader)) << "Broken message";
110 output += indent + "array [\n";
111 output += ToStringInternal(indent + " ", &sub_reader);
112 output += indent + "]\n";
113 break;
114 }
115 case STRUCT: {
116 MessageReader sub_reader(this);
117 CHECK(reader->PopStruct(&sub_reader)) << "Broken message";
118 output += indent + "struct {\n";
119 output += ToStringInternal(indent + " ", &sub_reader);
120 output += indent + "}\n";
121 break;
122 }
123 case DICT_ENTRY: {
124 MessageReader sub_reader(this);
125 CHECK(reader->PopDictEntry(&sub_reader)) << "Broken message";
126 output += indent + "dict entry {\n";
127 output += ToStringInternal(indent + " ", &sub_reader);
128 output += indent + "}\n";
129 break;
130 }
131 case VARIANT: {
132 MessageReader sub_reader(this);
133 CHECK(reader->PopVariant(&sub_reader)) << "Broken message";
134 output += indent + "variant ";
135 output += ToStringInternal(indent + " ", &sub_reader);
136 break;
137 }
138 default:
139 LOG(FATAL) << "Unknown type: " << type;
140 }
141 }
142 return output;
143 }
144
145 std::string Message::ToString() {
146 std::string output;
147 MessageReader reader(this);
148 return ToStringInternal("", &reader);
149 }
150
151 //
152 // MethodCall implementation.
153 //
154
155 MethodCall::MethodCall(const std::string& interface_name,
156 const std::string& method_name)
157 : Message(),
158 interface_name_(interface_name),
159 method_name_(method_name) {
160 reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
161
162 bool success = false;
163 success = dbus_message_set_interface(raw_message(), interface_name.c_str());
164 DCHECK(success) << "Unable to allocate memory";
165
166 success = dbus_message_set_member(raw_message(), method_name.c_str());
167 DCHECK(success) << "Unable to allocate memory";
168 }
169
170 void MethodCall::SetServiceName(const std::string& service_name) {
171 const bool success = dbus_message_set_destination(raw_message(),
172 service_name.c_str());
173 DCHECK(success) << "Unable to allocate memory";
174 }
175
176 void MethodCall::SetObjectPath(const std::string& object_path) {
177 const bool success = dbus_message_set_path(raw_message(),
178 object_path.c_str());
179 DCHECK(success) << "Unable to allocate memory";
180 }
181
182 //
183 // Response implementation.
184 //
185
186 Response::Response() : Message() {
187 }
188
189 //
190 // MessageWriter implementation.
191 //
192
193 MessageWriter::MessageWriter(Message* message) :
194 message_(message),
195 container_is_open_(false) {
196 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
197 }
198
199 MessageWriter::~MessageWriter() {
200 }
201
202 void MessageWriter::AppendByte(uint8 value) {
203 DCHECK(!container_is_open_);
204
205 const bool success = dbus_message_iter_append_basic(
206 &raw_message_iter_, DBUS_TYPE_BYTE, &value);
207 // dbus_message_iter_append_basic() fails only when there is not enough
208 // memory. We don't return this error as there is nothing we can do when
209 // it fails to allocate memory for a byte.
210 DCHECK(success) << "Unable to allocate memory";
211 }
212
213 void MessageWriter::AppendBool(bool value) {
214 DCHECK(!container_is_open_);
215
216 const bool success = dbus_message_iter_append_basic(
217 &raw_message_iter_, DBUS_TYPE_BOOLEAN, &value);
218 DCHECK(success) << "Unable to allocate memory";
219 }
220
221 void MessageWriter::AppendInt16(int16 value) {
222 DCHECK(!container_is_open_);
223
224 const bool success = dbus_message_iter_append_basic(
225 &raw_message_iter_, DBUS_TYPE_INT16, &value);
226 DCHECK(success) << "Unable to allocate memory";
227 }
228
229 void MessageWriter::AppendUint16(uint16 value) {
230 DCHECK(!container_is_open_);
231
232 const bool success = dbus_message_iter_append_basic(
233 &raw_message_iter_, DBUS_TYPE_UINT16, &value);
234 DCHECK(success) << "Unable to allocate memory";
235 }
236
237 void MessageWriter::AppendInt32(int32 value) {
238 DCHECK(!container_is_open_);
239
240 const bool success = dbus_message_iter_append_basic(
241 &raw_message_iter_, DBUS_TYPE_INT32, &value);
242 DCHECK(success) << "Unable to allocate memory";
243 }
244
245 void MessageWriter::AppendUint32(uint32 value) {
246 DCHECK(!container_is_open_);
247
248 const bool success = dbus_message_iter_append_basic(
249 &raw_message_iter_, DBUS_TYPE_UINT32, &value);
250 DCHECK(success) << "Unable to allocate memory";
251 }
252
253 void MessageWriter::AppendInt64(int64 value) {
254 DCHECK(!container_is_open_);
255
256 const bool success = dbus_message_iter_append_basic(
257 &raw_message_iter_, DBUS_TYPE_INT64, &value);
258 DCHECK(success) << "Unable to allocate memory";
259 }
260
261 void MessageWriter::AppendUint64(uint64 value) {
262 DCHECK(!container_is_open_);
263
264 const bool success = dbus_message_iter_append_basic(
265 &raw_message_iter_, DBUS_TYPE_UINT64, &value);
266 DCHECK(success) << "Unable to allocate memory";
267 }
268
269 void MessageWriter::AppendDouble(double value) {
270 DCHECK(!container_is_open_);
271
272 const bool success = dbus_message_iter_append_basic(
273 &raw_message_iter_, DBUS_TYPE_DOUBLE, &value);
274 DCHECK(success) << "Unable to allocate memory";
275 }
276
277 void MessageWriter::AppendString(const std::string& value) {
278 DCHECK(!container_is_open_);
279
280 const char* pointer = value.c_str();
281 const bool success = dbus_message_iter_append_basic(
282 &raw_message_iter_, DBUS_TYPE_STRING, &pointer);
283 // It may make sense to return an error here, as the input string can be
284 // large. If needed, we could add something like
285 // bool AppendStringWithErrorChecking().
286 DCHECK(success) << "Unable to allocate memory";
287 }
288
289 void MessageWriter::AppendObjectPath(const std::string& value) {
290 DCHECK(!container_is_open_);
291
292 const char* pointer = value.c_str();
293 const bool success = dbus_message_iter_append_basic(
294 &raw_message_iter_, DBUS_TYPE_OBJECT_PATH, &pointer);
295 DCHECK(success) << "Unable to allocate memory";
296 }
297
298 void MessageWriter::OpenArray(const std::string& signature,
299 MessageWriter* writer) {
300 DCHECK(!container_is_open_);
301
302 const bool success = dbus_message_iter_open_container(
303 &raw_message_iter_,
304 DBUS_TYPE_ARRAY,
305 signature.c_str(),
306 &writer->raw_message_iter_);
307 DCHECK(success) << "Unable to allocate memory";
308 container_is_open_ = true;
309 }
310
311 void MessageWriter::OpenVariant(const std::string& signature,
312 MessageWriter* writer) {
313 DCHECK(!container_is_open_);
314
315 const bool success = dbus_message_iter_open_container(
316 &raw_message_iter_,
317 DBUS_TYPE_VARIANT,
318 signature.c_str(),
319 &writer->raw_message_iter_);
320 DCHECK(success) << "Unable to allocate memory";
321 container_is_open_ = true;
322 }
323
324 void MessageWriter::OpenStruct(MessageWriter* writer) {
325 DCHECK(!container_is_open_);
326
327 const bool success = dbus_message_iter_open_container(
328 &raw_message_iter_,
329 DBUS_TYPE_STRUCT,
330 NULL, // Signature should be NULL.
331 &writer->raw_message_iter_);
332 DCHECK(success) << "Unable to allocate memory";
333 container_is_open_ = true;
334 }
335
336 void MessageWriter::OpenDictEntry(MessageWriter* writer) {
337 DCHECK(!container_is_open_);
338
339 const bool success = dbus_message_iter_open_container(
340 &raw_message_iter_,
341 DBUS_TYPE_DICT_ENTRY,
342 NULL, // Signature should be NULL.
343 &writer->raw_message_iter_);
344 DCHECK(success) << "Unable to allocate memory";
345 container_is_open_ = true;
346 }
347
348 void MessageWriter::CloseContainer(MessageWriter* writer) {
349 DCHECK(container_is_open_);
350
351 const bool success = dbus_message_iter_close_container(
352 &raw_message_iter_, &writer->raw_message_iter_);
353 DCHECK(success) << "Unable to allocate memory";
354 container_is_open_ = false;
355 }
356
357 //
358 // MessageReader implementation.
359 //
360
361 MessageReader::MessageReader(Message* message)
362 : message_(message) {
363 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
364 }
365
366
367 MessageReader::~MessageReader() {
368 }
369
370 bool MessageReader::HasMore() {
371 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
372 return dbus_type != DBUS_TYPE_INVALID;
373 }
374
375 bool MessageReader::PopByte(uint8* value) {
376 return PopBasic(DBUS_TYPE_BYTE, value);
377 }
378
379 bool MessageReader::PopBool(bool* value) {
380 return PopBasic(DBUS_TYPE_BOOLEAN, value);
381 }
382
383 bool MessageReader::PopInt16(int16* value) {
384 return PopBasic(DBUS_TYPE_INT16, value);
385 }
386
387 bool MessageReader::PopUint16(uint16* value) {
388 return PopBasic(DBUS_TYPE_UINT16, value);
389 }
390
391 bool MessageReader::PopInt32(int32* value) {
392 return PopBasic(DBUS_TYPE_INT32, value);
393 }
394
395 bool MessageReader::PopUint32(uint32* value) {
396 return PopBasic(DBUS_TYPE_UINT32, value);
397 }
398
399 bool MessageReader::PopInt64(int64* value) {
400 return PopBasic(DBUS_TYPE_INT64, value);
401 }
402
403 bool MessageReader::PopUint64(uint64* value) {
404 return PopBasic(DBUS_TYPE_UINT64, value);
405 }
406
407 bool MessageReader::PopDouble(double* value) {
408 return PopBasic(DBUS_TYPE_DOUBLE, value);
409 }
410
411 bool MessageReader::PopString(std::string* value) {
412 char* tmp_value = NULL;
413 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
414 if (success)
415 *value = tmp_value; // Copy the string.
416 return success;
417 }
418
419 bool MessageReader::PopObjectPath(std::string* value) {
420 char* tmp_value = NULL;
421 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
422 if (success)
423 *value = tmp_value; // Copy the string.
424 return success;
425 }
426
427 bool MessageReader::PopArray(MessageReader* sub_reader) {
428 return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
429 }
430
431 bool MessageReader::PopStruct(MessageReader* sub_reader) {
432 return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
433 }
434
435 bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
436 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
437 }
438
439 bool MessageReader::PopVariant(MessageReader* sub_reader) {
440 return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
441 }
442
443 bool MessageReader::PopArrayOfBytes(
444 std::vector<uint8>* bytes) {
445 MessageReader array_reader(message_);
446 if (!PopArray(&array_reader))
447 return false;
448 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
449 return false;
450 char* values = NULL;
451 int num_values = 0;
452 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
453 &values, &num_values);
454 if (!values)
455 return false;
456
457 bytes->assign(values, values + num_values); // Copy the data.
458 return true;
459 }
460
461 bool MessageReader::PopArrayOfObjectPaths(
462 std::vector<std::string> *object_paths) {
463 MessageReader array_reader(message_);
464 if (!PopArray(&array_reader))
465 return false;
466 while (array_reader.HasMore()) {
467 std::string object_path;
468 if (!array_reader.PopObjectPath(&object_path))
469 return false;
470 object_paths->push_back(object_path);
471 }
472 return true;
473 }
474
475 bool MessageReader::PopVariantOfByte(uint8* value) {
476 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
477 }
478
479 bool MessageReader::PopVariantOfBool(bool* value) {
480 return PopVariantOfBasic(DBUS_TYPE_BOOLEAN, value);
481 }
482
483 bool MessageReader::PopVariantOfInt16(int16* value) {
484 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
485 }
486
487 bool MessageReader::PopVariantOfUint16(uint16* value) {
488 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
489 }
490
491 bool MessageReader::PopVariantOfInt32(int32* value) {
492 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
493 }
494
495 bool MessageReader::PopVariantOfUint32(uint32* value) {
496 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
497 }
498
499 bool MessageReader::PopVariantOfInt64(int64* value) {
500 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
501 }
502
503 bool MessageReader::PopVariantOfUint64(uint64* value) {
504 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
505 }
506
507 bool MessageReader::PopVariantOfDouble(double* value) {
508 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
509 }
510
511 bool MessageReader::PopVariantOfString(std::string* value) {
512 char* tmp_value = NULL;
513 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
514 if (success)
515 *value = tmp_value; // Copy the string.
516 return success;
517 }
518
519 bool MessageReader::PopVariantOfObjectPath(std::string* value) {
520 char* tmp_value = NULL;
521 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
522 if (success)
523 *value = tmp_value; // Copy the string.
524 return success;
525 }
526
527 Message::DataType MessageReader::GetDataType() {
528 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
529 return static_cast<Message::DataType>(dbus_type);
530 }
531
532 bool MessageReader::CheckDataType(int dbus_type) {
533 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
534 if (actual_type != dbus_type) {
535 VLOG(1) << "Type " << dbus_type << " is expected but got "
536 << actual_type;
537 return false;
538 }
539 return true;
540 }
541
542 bool MessageReader::PopBasic(int dbus_type, void* value) {
543 if (!CheckDataType(dbus_type))
544 return false;
545 dbus_message_iter_get_basic(&raw_message_iter_, value);
546 dbus_message_iter_next(&raw_message_iter_);
547 return true;
548 }
549
550 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
551 DCHECK_NE(this, sub_reader);
552
553 if (!CheckDataType(dbus_type))
554 return false;
555 dbus_message_iter_recurse(&raw_message_iter_,
556 &sub_reader->raw_message_iter_);
557 dbus_message_iter_next(&raw_message_iter_);
558 return true;
559 }
560
561 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
562 dbus::MessageReader variant_reader(message_);
563 if (!PopVariant(&variant_reader))
564 return false;
565 return variant_reader.PopBasic(dbus_type, value);
566 }
567
568 } // namespace dbus
OLDNEW
« no previous file with comments | « dbus/message.h ('k') | dbus/message_unittest.cc » ('j') | dbus/run_all_unittests.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698