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

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: fix all.gyp Created 9 years, 4 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/format_macros.h"
9 #include "base/logging.h"
10 #include "base/stringprintf.h"
11
12 namespace dbus {
13
14 Message::Message()
15 : raw_message_(NULL) {
16 }
17
18 Message::~Message() {
19 if (raw_message_)
20 dbus_message_unref(raw_message_);
21 }
22
23 Message::MessageType Message::GetMessageType() {
24 if (!raw_message_)
25 return MESSAGE_INVALID;
26 const int type = dbus_message_get_type(raw_message_);
27 return static_cast<Message::MessageType>(type);
28 }
29
30 void Message::reset_raw_message(DBusMessage* raw_message) {
31 if (raw_message_)
32 dbus_message_unref(raw_message_);
33 raw_message_ = raw_message;
34 }
35
36 std::string Message::ToStringInternal(const std::string& indent,
37 MessageReader* reader) {
38 const char* kBrokenMessage = "[broken message]";
39 std::string output;
40 while (reader->HasMoreData()) {
41 const DataType type = reader->GetDataType();
42 switch (type) {
43 case BYTE: {
44 uint8 value = 0;
45 if (!reader->PopByte(&value))
46 return kBrokenMessage;
47 output += indent + "byte " + base::StringPrintf("%d", value) + "\n";
48 break;
49 }
50 case BOOL: {
51 bool value = false;
52 if (!reader->PopBool(&value))
53 return kBrokenMessage;
54 output += indent + "bool " + (value ? "true" : "false") + "\n";
55 break;
56 }
57 case INT16: {
58 int16 value = 0;
59 if (!reader->PopInt16(&value))
60 return kBrokenMessage;
61 output += indent + "int16 " + base::StringPrintf("%d", value) + "\n";
62 break;
63 }
64 case UINT16: {
65 uint16 value = 0;
66 if (!reader->PopUint16(&value))
67 return kBrokenMessage;
68 output += indent + "uint16 " + base::StringPrintf("%d", value) + "\n";
69 break;
70 }
71 case INT32: {
72 int32 value = 0;
73 if (!reader->PopInt32(&value))
74 return kBrokenMessage;
75 output += indent + "int32 " + base::StringPrintf("%d", value) + "\n";
76 break;
77 }
78 case UINT32: {
79 uint32 value = 0;
80 if (!reader->PopUint32(&value))
81 return kBrokenMessage;
82 output += indent + "uint32 " + base::StringPrintf("%u", value) + "\n";
83 break;
84 }
85 case INT64: {
86 int64 value = 0;
87 if (!reader->PopInt64(&value))
88 return kBrokenMessage;
89 output += (indent + "int64 " +
90 base::StringPrintf("%" PRId64, value) + "\n");
91 break;
92 }
93 case UINT64: {
94 uint64 value = 0;
95 if (!reader->PopUint64(&value))
96 return kBrokenMessage;
97 output += (indent + "uint64 " +
98 base::StringPrintf("%" PRIu64, value) + "\n");
99 break;
100 }
101 case DOUBLE: {
102 double value = 0;
103 if (!reader->PopDouble(&value))
104 return kBrokenMessage;
105 output += indent + "double " + base::StringPrintf("%f", value) + "\n";
106 break;
107 }
108 case STRING: {
109 std::string value;
110 if (!reader->PopString(&value))
111 return kBrokenMessage;
112 output += indent + "string \"" + value + "\"\n";
113 break;
114 }
115 case OBJECT_PATH: {
116 std::string value;
117 if (!reader->PopObjectPath(&value))
118 return kBrokenMessage;
119 output += indent + "object_path \"" + value + "\"\n";
120 break;
121 }
122 case ARRAY: {
123 MessageReader sub_reader(this);
124 if (!reader->PopArray(&sub_reader))
125 return kBrokenMessage;
126 output += indent + "array [\n";
127 output += ToStringInternal(indent + " ", &sub_reader);
128 output += indent + "]\n";
129 break;
130 }
131 case STRUCT: {
132 MessageReader sub_reader(this);
133 if (!reader->PopStruct(&sub_reader))
134 return kBrokenMessage;
135 output += indent + "struct {\n";
136 output += ToStringInternal(indent + " ", &sub_reader);
137 output += indent + "}\n";
138 break;
139 }
140 case DICT_ENTRY: {
141 MessageReader sub_reader(this);
142 if (!reader->PopDictEntry(&sub_reader))
143 return kBrokenMessage;
144 output += indent + "dict entry {\n";
145 output += ToStringInternal(indent + " ", &sub_reader);
146 output += indent + "}\n";
147 break;
148 }
149 case VARIANT: {
150 MessageReader sub_reader(this);
151 if (!reader->PopVariant(&sub_reader))
152 return kBrokenMessage;
153 output += indent + "variant ";
154 output += ToStringInternal(indent + " ", &sub_reader);
155 break;
156 }
157 default:
158 LOG(FATAL) << "Unknown type: " << type;
159 }
160 }
161 return output;
162 }
163
164 // The returned string consists of message headers such as
165 // destination if any, followed by a blank line, and the message
166 // payload. For example, a MethodCall's ToString() will look like:
167 //
168 // destination: com.example.Service
169 // path: /com/example/Object
170 // interface: com.example.Interface
171 // member: SomeMethod
172 //
173 // string \"payload\"
174 // ...
175 std::string Message::ToString() {
176 if (!raw_message_)
177 return "";
178
179 // Generate headers first.
180 std::string headers;
181 const char* destination = dbus_message_get_destination(raw_message_);
182 if (destination)
183 headers += base::StringPrintf("destination: %s\n", destination);
184 const char* path = dbus_message_get_path(raw_message_);
185 if (path)
186 headers += base::StringPrintf("path: %s\n", path);
187 const char* interface = dbus_message_get_interface(raw_message_);
188 if (interface)
189 headers += base::StringPrintf("interface: %s\n", interface);
190 const char* member = dbus_message_get_member(raw_message_);
191 if (member)
192 headers += base::StringPrintf("member: %s\n", member);
193 const char* error_name = dbus_message_get_error_name(raw_message_);
194 if (error_name)
195 headers += base::StringPrintf("error_name: %s\n", error_name);
196 const char* sender = dbus_message_get_sender(raw_message_);
197 if (sender)
198 headers += base::StringPrintf("sender: %s\n", sender);
199 const char* signature = dbus_message_get_signature(raw_message_);
200 if (signature)
201 headers += base::StringPrintf("signature: %s\n", signature);
202
203 // Generate the payload.
204 MessageReader reader(this);
205 return headers + "\n" + ToStringInternal("", &reader);
206 }
207
208 //
209 // MethodCall implementation.
210 //
211
212 MethodCall::MethodCall(const std::string& interface_name,
213 const std::string& method_name)
214 : Message(),
215 interface_name_(interface_name),
216 method_name_(method_name) {
217 reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
218
219 bool success = dbus_message_set_interface(raw_message(),
220 interface_name.c_str());
221 CHECK(success) << "Unable to allocate memory";
222
223 success = dbus_message_set_member(raw_message(), method_name.c_str());
224 CHECK(success) << "Unable to allocate memory";
225 }
226
227 void MethodCall::SetServiceName(const std::string& service_name) {
228 const bool success = dbus_message_set_destination(raw_message(),
229 service_name.c_str());
230 CHECK(success) << "Unable to allocate memory";
231 }
232
233 void MethodCall::SetObjectPath(const std::string& object_path) {
234 const bool success = dbus_message_set_path(raw_message(),
235 object_path.c_str());
236 CHECK(success) << "Unable to allocate memory";
237 }
238
239 //
240 // Response implementation.
241 //
242
243 Response::Response() : Message() {
244 }
245
246 //
247 // MessageWriter implementation.
248 //
249
250 MessageWriter::MessageWriter(Message* message) :
251 message_(message),
252 container_is_open_(false) {
253 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
254 }
255
256 MessageWriter::~MessageWriter() {
257 }
258
259 void MessageWriter::AppendByte(uint8 value) {
260 AppendBasic(DBUS_TYPE_BYTE, &value);
261 }
262
263 void MessageWriter::AppendBool(bool value) {
264 AppendBasic(DBUS_TYPE_BOOLEAN, &value);
265 }
266
267 void MessageWriter::AppendInt16(int16 value) {
268 AppendBasic(DBUS_TYPE_INT16, &value);
269 }
270
271 void MessageWriter::AppendUint16(uint16 value) {
272 AppendBasic(DBUS_TYPE_UINT16, &value);
273 }
274
275 void MessageWriter::AppendInt32(int32 value) {
276 AppendBasic(DBUS_TYPE_INT32, &value);
277 }
278
279 void MessageWriter::AppendUint32(uint32 value) {
280 AppendBasic(DBUS_TYPE_UINT32, &value);
281 }
282
283 void MessageWriter::AppendInt64(int64 value) {
284 AppendBasic(DBUS_TYPE_INT64, &value);
285 }
286
287 void MessageWriter::AppendUint64(uint64 value) {
288 AppendBasic(DBUS_TYPE_UINT64, &value);
289 }
290
291 void MessageWriter::AppendDouble(double value) {
292 AppendBasic(DBUS_TYPE_DOUBLE, &value);
293 }
294
295 void MessageWriter::AppendString(const std::string& value) {
296 const char* pointer = value.c_str();
297 AppendBasic(DBUS_TYPE_STRING, &pointer);
298 // TODO(satorux): It may make sense to return an error here, as the
299 // input string can be large. If needed, we could add something like
300 // bool AppendStringWithErrorChecking().
301 }
302
303 void MessageWriter::AppendObjectPath(const std::string& value) {
304 const char* pointer = value.c_str();
305 AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
306 }
307
308 // Ideally, client shouldn't need to supply the signature string, but
309 // the underlying D-Bus library requires us to supply this before
310 // appending contents to array and variant. It's technically possible
311 // for us to design API that doesn't require the signature but it will
312 // complicate the implementation so we decided to have the signature
313 // parameter. Hopefully, variants are less used in request messages from
314 // client side than response message from server side, so this should
315 // not be a big issue.
316 void MessageWriter::OpenArray(const std::string& signature,
317 MessageWriter* writer) {
318 DCHECK(!container_is_open_);
319
320 const bool success = dbus_message_iter_open_container(
321 &raw_message_iter_,
322 DBUS_TYPE_ARRAY,
323 signature.c_str(),
324 &writer->raw_message_iter_);
325 CHECK(success) << "Unable to allocate memory";
326 container_is_open_ = true;
327 }
328
329 void MessageWriter::OpenVariant(const std::string& signature,
330 MessageWriter* writer) {
331 DCHECK(!container_is_open_);
332
333 const bool success = dbus_message_iter_open_container(
334 &raw_message_iter_,
335 DBUS_TYPE_VARIANT,
336 signature.c_str(),
337 &writer->raw_message_iter_);
338 CHECK(success) << "Unable to allocate memory";
339 container_is_open_ = true;
340 }
341
342 void MessageWriter::OpenStruct(MessageWriter* writer) {
343 DCHECK(!container_is_open_);
344
345 const bool success = dbus_message_iter_open_container(
346 &raw_message_iter_,
347 DBUS_TYPE_STRUCT,
348 NULL, // Signature should be NULL.
349 &writer->raw_message_iter_);
350 CHECK(success) << "Unable to allocate memory";
351 container_is_open_ = true;
352 }
353
354 void MessageWriter::OpenDictEntry(MessageWriter* writer) {
355 DCHECK(!container_is_open_);
356
357 const bool success = dbus_message_iter_open_container(
358 &raw_message_iter_,
359 DBUS_TYPE_DICT_ENTRY,
360 NULL, // Signature should be NULL.
361 &writer->raw_message_iter_);
362 CHECK(success) << "Unable to allocate memory";
363 container_is_open_ = true;
364 }
365
366 void MessageWriter::CloseContainer(MessageWriter* writer) {
367 DCHECK(container_is_open_);
368
369 const bool success = dbus_message_iter_close_container(
370 &raw_message_iter_, &writer->raw_message_iter_);
371 CHECK(success) << "Unable to allocate memory";
372 container_is_open_ = false;
373 }
374
375 void MessageWriter::AppendArrayOfBytes(const uint8* values, size_t length) {
376 DCHECK(!container_is_open_);
377 MessageWriter array_writer(message_);
378 OpenArray("y", &array_writer);
379 const bool success = dbus_message_iter_append_fixed_array(
380 &(array_writer.raw_message_iter_),
381 DBUS_TYPE_BYTE,
382 &values,
383 static_cast<int>(length));
384 CHECK(success) << "Unable to allocate memory";
385 CloseContainer(&array_writer);
386 }
387
388 void MessageWriter::AppendVariantOfByte(uint8 value) {
389 AppendVariantOfBasic(DBUS_TYPE_BYTE, &value);
390 }
391
392 void MessageWriter::AppendVariantOfBool(bool value) {
393 AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &value);
394 }
395
396 void MessageWriter::AppendVariantOfInt16(int16 value) {
397 AppendVariantOfBasic(DBUS_TYPE_INT16, &value);
398 }
399
400 void MessageWriter::AppendVariantOfUint16(uint16 value) {
401 AppendVariantOfBasic(DBUS_TYPE_UINT16, &value);
402 }
403
404 void MessageWriter::AppendVariantOfInt32(int32 value) {
405 AppendVariantOfBasic(DBUS_TYPE_INT32, &value);
406 }
407
408 void MessageWriter::AppendVariantOfUint32(uint32 value) {
409 AppendVariantOfBasic(DBUS_TYPE_UINT32, &value);
410 }
411
412 void MessageWriter::AppendVariantOfInt64(int64 value) {
413 AppendVariantOfBasic(DBUS_TYPE_INT64, &value);
414 }
415
416 void MessageWriter::AppendVariantOfUint64(uint64 value) {
417 AppendVariantOfBasic(DBUS_TYPE_UINT64, &value);
418 }
419
420 void MessageWriter::AppendVariantOfDouble(double value) {
421 AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value);
422 }
423
424 void MessageWriter::AppendVariantOfString(const std::string& value) {
425 const char* pointer = value.c_str();
426 AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer);
427 }
428
429 void MessageWriter::AppendVariantOfObjectPath(const std::string& value) {
430 const char* pointer = value.c_str();
431 AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
432 }
433
434 void MessageWriter::AppendBasic(int dbus_type, const void* value) {
435 DCHECK(!container_is_open_);
436
437 const bool success = dbus_message_iter_append_basic(
438 &raw_message_iter_, dbus_type, value);
439 // dbus_message_iter_append_basic() fails only when there is not enough
440 // memory. We don't return this error as there is nothing we can do when
441 // it fails to allocate memory for a byte etc.
442 CHECK(success) << "Unable to allocate memory";
443 }
444
445 void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) {
446 const std::string signature = base::StringPrintf("%c", dbus_type);
447 MessageWriter variant_writer(message_);
448 OpenVariant(signature, &variant_writer);
449 variant_writer.AppendBasic(dbus_type, value);
450 CloseContainer(&variant_writer);
451 }
452
453 //
454 // MessageReader implementation.
455 //
456
457 MessageReader::MessageReader(Message* message)
458 : message_(message) {
459 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
460 }
461
462
463 MessageReader::~MessageReader() {
464 }
465
466 bool MessageReader::HasMoreData() {
467 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
468 return dbus_type != DBUS_TYPE_INVALID;
469 }
470
471 bool MessageReader::PopByte(uint8* value) {
472 return PopBasic(DBUS_TYPE_BYTE, value);
473 }
474
475 bool MessageReader::PopBool(bool* value) {
476 return PopBasic(DBUS_TYPE_BOOLEAN, value);
477 }
478
479 bool MessageReader::PopInt16(int16* value) {
480 return PopBasic(DBUS_TYPE_INT16, value);
481 }
482
483 bool MessageReader::PopUint16(uint16* value) {
484 return PopBasic(DBUS_TYPE_UINT16, value);
485 }
486
487 bool MessageReader::PopInt32(int32* value) {
488 return PopBasic(DBUS_TYPE_INT32, value);
489 }
490
491 bool MessageReader::PopUint32(uint32* value) {
492 return PopBasic(DBUS_TYPE_UINT32, value);
493 }
494
495 bool MessageReader::PopInt64(int64* value) {
496 return PopBasic(DBUS_TYPE_INT64, value);
497 }
498
499 bool MessageReader::PopUint64(uint64* value) {
500 return PopBasic(DBUS_TYPE_UINT64, value);
501 }
502
503 bool MessageReader::PopDouble(double* value) {
504 return PopBasic(DBUS_TYPE_DOUBLE, value);
505 }
506
507 bool MessageReader::PopString(std::string* value) {
508 char* tmp_value = NULL;
509 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
510 if (success)
511 value->assign(tmp_value);
512 return success;
513 }
514
515 bool MessageReader::PopObjectPath(std::string* value) {
516 char* tmp_value = NULL;
517 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
518 if (success)
519 value->assign(tmp_value);
520 return success;
521 }
522
523 bool MessageReader::PopArray(MessageReader* sub_reader) {
524 return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
525 }
526
527 bool MessageReader::PopStruct(MessageReader* sub_reader) {
528 return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
529 }
530
531 bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
532 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
533 }
534
535 bool MessageReader::PopVariant(MessageReader* sub_reader) {
536 return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
537 }
538
539 bool MessageReader::PopArrayOfBytes(uint8** bytes, size_t* length) {
540 MessageReader array_reader(message_);
541 if (!PopArray(&array_reader))
542 return false;
543 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
544 return false;
545 int int_length = 0;
546 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
547 bytes,
548 &int_length);
549 *length = static_cast<int>(int_length);
550 return bytes != NULL;
551 }
552
553 bool MessageReader::PopArrayOfObjectPaths(
554 std::vector<std::string> *object_paths) {
555 MessageReader array_reader(message_);
556 if (!PopArray(&array_reader))
557 return false;
558 while (array_reader.HasMoreData()) {
559 std::string object_path;
560 if (!array_reader.PopObjectPath(&object_path))
561 return false;
562 object_paths->push_back(object_path);
563 }
564 return true;
565 }
566
567 bool MessageReader::PopVariantOfByte(uint8* value) {
568 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
569 }
570
571 bool MessageReader::PopVariantOfBool(bool* value) {
572 return PopVariantOfBasic(DBUS_TYPE_BOOLEAN, value);
573 }
574
575 bool MessageReader::PopVariantOfInt16(int16* value) {
576 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
577 }
578
579 bool MessageReader::PopVariantOfUint16(uint16* value) {
580 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
581 }
582
583 bool MessageReader::PopVariantOfInt32(int32* value) {
584 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
585 }
586
587 bool MessageReader::PopVariantOfUint32(uint32* value) {
588 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
589 }
590
591 bool MessageReader::PopVariantOfInt64(int64* value) {
592 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
593 }
594
595 bool MessageReader::PopVariantOfUint64(uint64* value) {
596 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
597 }
598
599 bool MessageReader::PopVariantOfDouble(double* value) {
600 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
601 }
602
603 bool MessageReader::PopVariantOfString(std::string* value) {
604 char* tmp_value = NULL;
605 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
606 if (success)
607 value->assign(tmp_value);
608 return success;
609 }
610
611 bool MessageReader::PopVariantOfObjectPath(std::string* value) {
612 char* tmp_value = NULL;
613 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
614 if (success)
615 value->assign(tmp_value);
616 return success;
617 }
618
619 Message::DataType MessageReader::GetDataType() {
620 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
621 return static_cast<Message::DataType>(dbus_type);
622 }
623
624 bool MessageReader::CheckDataType(int dbus_type) {
625 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
626 if (actual_type != dbus_type) {
627 VLOG(1) << "Type " << dbus_type << " is expected but got "
628 << actual_type;
629 return false;
630 }
631 return true;
632 }
633
634 bool MessageReader::PopBasic(int dbus_type, void* value) {
635 if (!CheckDataType(dbus_type))
636 return false;
637 // dbus_message_iter_get_basic() here should always work, as we have
638 // already checked the next item's data type in CheckDataType(). Note
639 // that dbus_message_iter_get_basic() is a void function.
640 dbus_message_iter_get_basic(&raw_message_iter_, value);
641 DCHECK(value);
642 dbus_message_iter_next(&raw_message_iter_);
643 return true;
644 }
645
646 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
647 DCHECK_NE(this, sub_reader);
648
649 if (!CheckDataType(dbus_type))
650 return false;
651 dbus_message_iter_recurse(&raw_message_iter_,
652 &sub_reader->raw_message_iter_);
653 dbus_message_iter_next(&raw_message_iter_);
654 return true;
655 }
656
657 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
658 dbus::MessageReader variant_reader(message_);
659 if (!PopVariant(&variant_reader))
660 return false;
661 return variant_reader.PopBasic(dbus_type, value);
662 }
663
664 } // namespace dbus
OLDNEW
« no previous file with comments | « dbus/message.h ('k') | dbus/message_unittest.cc » ('j') | dbus/message_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698