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

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: Add more headers 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 std::string Message::ToString() {
165 if (!raw_message_)
166 return "";
167
168 // Generate headers first.
169 std::string headers;
170 const char* destination = dbus_message_get_destination(raw_message_);
171 if (destination)
172 headers += base::StringPrintf("destination: %s\n", destination);
173 const char* path = dbus_message_get_path(raw_message_);
174 if (path)
175 headers += base::StringPrintf("path: %s\n", path);
176 const char* interface = dbus_message_get_interface(raw_message_);
177 if (interface)
178 headers += base::StringPrintf("interface: %s\n", interface);
179 const char* member = dbus_message_get_member(raw_message_);
180 if (member)
181 headers += base::StringPrintf("member: %s\n", member);
182 const char* error_name = dbus_message_get_error_name(raw_message_);
183 if (error_name)
184 headers += base::StringPrintf("error_name: %s\n", error_name);
185 const char* sender = dbus_message_get_sender(raw_message_);
186 if (sender)
187 headers += base::StringPrintf("sender: %s\n", sender);
188 const char* signature = dbus_message_get_signature(raw_message_);
189 if (signature)
190 headers += base::StringPrintf("signature: %s\n", signature);
191
192 // Generate the payload.
193 MessageReader reader(this);
194 return headers + "\n" + ToStringInternal("", &reader);
195 }
196
197 //
198 // MethodCall implementation.
199 //
200
201 MethodCall::MethodCall(const std::string& interface_name,
202 const std::string& method_name)
203 : Message(),
204 interface_name_(interface_name),
205 method_name_(method_name) {
206 reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
207
208 bool success = dbus_message_set_interface(raw_message(),
209 interface_name.c_str());
210 CHECK(success) << "Unable to allocate memory";
211
212 success = dbus_message_set_member(raw_message(), method_name.c_str());
213 CHECK(success) << "Unable to allocate memory";
214 }
215
216 void MethodCall::SetServiceName(const std::string& service_name) {
217 const bool success = dbus_message_set_destination(raw_message(),
218 service_name.c_str());
219 CHECK(success) << "Unable to allocate memory";
220 }
221
222 void MethodCall::SetObjectPath(const std::string& object_path) {
223 const bool success = dbus_message_set_path(raw_message(),
224 object_path.c_str());
225 CHECK(success) << "Unable to allocate memory";
226 }
227
228 //
229 // Response implementation.
230 //
231
232 Response::Response() : Message() {
233 }
234
235 //
236 // MessageWriter implementation.
237 //
238
239 MessageWriter::MessageWriter(Message* message) :
240 message_(message),
241 container_is_open_(false) {
242 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
243 }
244
245 MessageWriter::~MessageWriter() {
246 }
247
248 void MessageWriter::AppendByte(uint8 value) {
249 AppendBasic(DBUS_TYPE_BYTE, &value);
250 }
251
252 void MessageWriter::AppendBool(bool value) {
253 AppendBasic(DBUS_TYPE_BOOLEAN, &value);
254 }
255
256 void MessageWriter::AppendInt16(int16 value) {
257 AppendBasic(DBUS_TYPE_INT16, &value);
258 }
259
260 void MessageWriter::AppendUint16(uint16 value) {
261 AppendBasic(DBUS_TYPE_UINT16, &value);
262 }
263
264 void MessageWriter::AppendInt32(int32 value) {
265 AppendBasic(DBUS_TYPE_INT32, &value);
266 }
267
268 void MessageWriter::AppendUint32(uint32 value) {
269 AppendBasic(DBUS_TYPE_UINT32, &value);
270 }
271
272 void MessageWriter::AppendInt64(int64 value) {
273 AppendBasic(DBUS_TYPE_INT64, &value);
274 }
275
276 void MessageWriter::AppendUint64(uint64 value) {
277 AppendBasic(DBUS_TYPE_UINT64, &value);
278 }
279
280 void MessageWriter::AppendDouble(double value) {
281 AppendBasic(DBUS_TYPE_DOUBLE, &value);
282 }
283
284 void MessageWriter::AppendString(const std::string& value) {
285 const char* pointer = value.c_str();
286 AppendBasic(DBUS_TYPE_STRING, &pointer);
287 // It may make sense to return an error here, as the input string can be
stevenjb 2011/07/29 20:27:12 Add TODO(satorux)
satorux1 2011/07/29 22:08:20 Done.
288 // large. If needed, we could add something like
289 // bool AppendStringWithErrorChecking().
290 }
291
292 void MessageWriter::AppendObjectPath(const std::string& value) {
293 const char* pointer = value.c_str();
294 AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
295 }
296
297 // Ideally, client shouldn't need to supply the signature string, but
298 // the underlying D-Bus library requires us to supply this before
299 // appending contents to array and variant. It's technically possible
300 // for us to design API that doesn't require the signature but it will
301 // complicate the implementation so we decided to have the signature
302 // parameter. Hopefully, variants are less used in request messages from
303 // client side than response message from server side, so this should
304 // not be a big issue.
305 void MessageWriter::OpenArray(const std::string& signature,
306 MessageWriter* writer) {
307 DCHECK(!container_is_open_);
308
309 const bool success = dbus_message_iter_open_container(
310 &raw_message_iter_,
311 DBUS_TYPE_ARRAY,
312 signature.c_str(),
313 &writer->raw_message_iter_);
314 CHECK(success) << "Unable to allocate memory";
315 container_is_open_ = true;
316 }
317
318 void MessageWriter::OpenVariant(const std::string& signature,
319 MessageWriter* writer) {
320 DCHECK(!container_is_open_);
321
322 const bool success = dbus_message_iter_open_container(
323 &raw_message_iter_,
324 DBUS_TYPE_VARIANT,
325 signature.c_str(),
326 &writer->raw_message_iter_);
327 CHECK(success) << "Unable to allocate memory";
328 container_is_open_ = true;
329 }
330
331 void MessageWriter::OpenStruct(MessageWriter* writer) {
332 DCHECK(!container_is_open_);
333
334 const bool success = dbus_message_iter_open_container(
335 &raw_message_iter_,
336 DBUS_TYPE_STRUCT,
337 NULL, // Signature should be NULL.
338 &writer->raw_message_iter_);
339 CHECK(success) << "Unable to allocate memory";
340 container_is_open_ = true;
341 }
342
343 void MessageWriter::OpenDictEntry(MessageWriter* writer) {
344 DCHECK(!container_is_open_);
345
346 const bool success = dbus_message_iter_open_container(
347 &raw_message_iter_,
348 DBUS_TYPE_DICT_ENTRY,
349 NULL, // Signature should be NULL.
350 &writer->raw_message_iter_);
351 CHECK(success) << "Unable to allocate memory";
352 container_is_open_ = true;
353 }
354
355 void MessageWriter::CloseContainer(MessageWriter* writer) {
356 DCHECK(container_is_open_);
357
358 const bool success = dbus_message_iter_close_container(
359 &raw_message_iter_, &writer->raw_message_iter_);
360 CHECK(success) << "Unable to allocate memory";
361 container_is_open_ = false;
362 }
363
364 void MessageWriter::AppendArrayOfBytes(const uint8* values, size_t length) {
365 DCHECK(!container_is_open_);
366 MessageWriter array_writer(message_);
367 OpenArray("y", &array_writer);
368 const bool success = dbus_message_iter_append_fixed_array(
369 &(array_writer.raw_message_iter_),
370 DBUS_TYPE_BYTE,
371 &values,
372 static_cast<int>(length));
373 CHECK(success) << "Unable to allocate memory";
374 CloseContainer(&array_writer);
375 }
376
377 void MessageWriter::AppendVariantOfByte(uint8 value) {
378 AppendVariantOfBasic(DBUS_TYPE_BYTE, &value);
379 }
380
381 void MessageWriter::AppendVariantOfBool(bool value) {
382 AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &value);
383 }
384
385 void MessageWriter::AppendVariantOfInt16(int16 value) {
386 AppendVariantOfBasic(DBUS_TYPE_INT16, &value);
387 }
388
389 void MessageWriter::AppendVariantOfUint16(uint16 value) {
390 AppendVariantOfBasic(DBUS_TYPE_UINT16, &value);
391 }
392
393 void MessageWriter::AppendVariantOfInt32(int32 value) {
394 AppendVariantOfBasic(DBUS_TYPE_INT32, &value);
395 }
396
397 void MessageWriter::AppendVariantOfUint32(uint32 value) {
398 AppendVariantOfBasic(DBUS_TYPE_UINT32, &value);
399 }
400
401 void MessageWriter::AppendVariantOfInt64(int64 value) {
402 AppendVariantOfBasic(DBUS_TYPE_INT64, &value);
403 }
404
405 void MessageWriter::AppendVariantOfUint64(uint64 value) {
406 AppendVariantOfBasic(DBUS_TYPE_UINT64, &value);
407 }
408
409 void MessageWriter::AppendVariantOfDouble(double value) {
410 AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value);
411 }
412
413 void MessageWriter::AppendVariantOfString(const std::string& value) {
414 const char* pointer = value.c_str();
415 AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer);
416 }
417
418 void MessageWriter::AppendVariantOfObjectPath(const std::string& value) {
419 const char* pointer = value.c_str();
420 AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
421 }
422
423 void MessageWriter::AppendBasic(int dbus_type, const void* value) {
424 DCHECK(!container_is_open_);
425
426 const bool success = dbus_message_iter_append_basic(
427 &raw_message_iter_, dbus_type, value);
428 // dbus_message_iter_append_basic() fails only when there is not enough
429 // memory. We don't return this error as there is nothing we can do when
430 // it fails to allocate memory for a byte etc.
431 CHECK(success) << "Unable to allocate memory";
432 }
433
434 void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) {
435 const std::string signature = base::StringPrintf("%c", dbus_type);
436 MessageWriter variant_writer(message_);
437 OpenVariant(signature, &variant_writer);
438 variant_writer.AppendBasic(dbus_type, value);
439 CloseContainer(&variant_writer);
440 }
441
442 //
443 // MessageReader implementation.
444 //
445
446 MessageReader::MessageReader(Message* message)
447 : message_(message) {
448 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
449 }
450
451
452 MessageReader::~MessageReader() {
453 }
454
455 bool MessageReader::HasMoreData() {
456 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
457 return dbus_type != DBUS_TYPE_INVALID;
458 }
459
460 bool MessageReader::PopByte(uint8* value) {
461 return PopBasic(DBUS_TYPE_BYTE, value);
462 }
463
464 bool MessageReader::PopBool(bool* value) {
465 return PopBasic(DBUS_TYPE_BOOLEAN, value);
466 }
467
468 bool MessageReader::PopInt16(int16* value) {
469 return PopBasic(DBUS_TYPE_INT16, value);
470 }
471
472 bool MessageReader::PopUint16(uint16* value) {
473 return PopBasic(DBUS_TYPE_UINT16, value);
474 }
475
476 bool MessageReader::PopInt32(int32* value) {
477 return PopBasic(DBUS_TYPE_INT32, value);
478 }
479
480 bool MessageReader::PopUint32(uint32* value) {
481 return PopBasic(DBUS_TYPE_UINT32, value);
482 }
483
484 bool MessageReader::PopInt64(int64* value) {
485 return PopBasic(DBUS_TYPE_INT64, value);
486 }
487
488 bool MessageReader::PopUint64(uint64* value) {
489 return PopBasic(DBUS_TYPE_UINT64, value);
490 }
491
492 bool MessageReader::PopDouble(double* value) {
493 return PopBasic(DBUS_TYPE_DOUBLE, value);
494 }
495
496 bool MessageReader::PopString(std::string* value) {
497 char* tmp_value = NULL;
498 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
499 if (success)
500 value->assign(tmp_value);
501 return success;
502 }
503
504 bool MessageReader::PopObjectPath(std::string* value) {
505 char* tmp_value = NULL;
506 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
507 if (success)
508 value->assign(tmp_value);
509 return success;
510 }
511
512 bool MessageReader::PopArray(MessageReader* sub_reader) {
513 return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
514 }
515
516 bool MessageReader::PopStruct(MessageReader* sub_reader) {
517 return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
518 }
519
520 bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
521 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
522 }
523
524 bool MessageReader::PopVariant(MessageReader* sub_reader) {
525 return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
526 }
527
528 bool MessageReader::PopArrayOfBytes(uint8** bytes, size_t* length) {
529 MessageReader array_reader(message_);
530 if (!PopArray(&array_reader))
531 return false;
532 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
533 return false;
534 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
535 bytes,
536 reinterpret_cast<int*>(length));
stevenjb 2011/07/29 20:27:12 reinterpret_cast should be avoided. It would be be
satorux1 2011/07/29 22:08:20 Done.
537 if (!bytes)
538 return false;
539 return true;
stevenjb 2011/07/29 20:27:12 nit: return (bytes != NULL);
satorux1 2011/07/29 22:08:20 Done.
540 }
541
542 bool MessageReader::PopArrayOfObjectPaths(
543 std::vector<std::string> *object_paths) {
544 MessageReader array_reader(message_);
545 if (!PopArray(&array_reader))
546 return false;
547 while (array_reader.HasMoreData()) {
548 std::string object_path;
549 if (!array_reader.PopObjectPath(&object_path))
550 return false;
551 object_paths->push_back(object_path);
552 }
553 return true;
554 }
555
556 bool MessageReader::PopVariantOfByte(uint8* value) {
557 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
558 }
559
560 bool MessageReader::PopVariantOfBool(bool* value) {
561 return PopVariantOfBasic(DBUS_TYPE_BOOLEAN, value);
562 }
563
564 bool MessageReader::PopVariantOfInt16(int16* value) {
565 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
566 }
567
568 bool MessageReader::PopVariantOfUint16(uint16* value) {
569 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
570 }
571
572 bool MessageReader::PopVariantOfInt32(int32* value) {
573 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
574 }
575
576 bool MessageReader::PopVariantOfUint32(uint32* value) {
577 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
578 }
579
580 bool MessageReader::PopVariantOfInt64(int64* value) {
581 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
582 }
583
584 bool MessageReader::PopVariantOfUint64(uint64* value) {
585 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
586 }
587
588 bool MessageReader::PopVariantOfDouble(double* value) {
589 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
590 }
591
592 bool MessageReader::PopVariantOfString(std::string* value) {
593 char* tmp_value = NULL;
594 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
595 if (success)
596 value->assign(tmp_value);
597 return success;
598 }
599
600 bool MessageReader::PopVariantOfObjectPath(std::string* value) {
601 char* tmp_value = NULL;
602 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
603 if (success)
604 value->assign(tmp_value);
605 return success;
606 }
607
608 Message::DataType MessageReader::GetDataType() {
609 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
610 return static_cast<Message::DataType>(dbus_type);
611 }
612
613 bool MessageReader::CheckDataType(int dbus_type) {
614 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
615 if (actual_type != dbus_type) {
616 VLOG(1) << "Type " << dbus_type << " is expected but got "
617 << actual_type;
618 return false;
619 }
620 return true;
621 }
622
623 bool MessageReader::PopBasic(int dbus_type, void* value) {
624 if (!CheckDataType(dbus_type))
625 return false;
626 // dbus_message_iter_get_basic() here should always work, as we have
627 // already checked the next item's data type in CheckDataType(). Note
628 // that dbus_message_iter_get_basic() is a void function.
629 dbus_message_iter_get_basic(&raw_message_iter_, value);
630 DCHECK(value);
631 dbus_message_iter_next(&raw_message_iter_);
632 return true;
633 }
634
635 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
636 DCHECK_NE(this, sub_reader);
637
638 if (!CheckDataType(dbus_type))
639 return false;
640 dbus_message_iter_recurse(&raw_message_iter_,
641 &sub_reader->raw_message_iter_);
642 dbus_message_iter_next(&raw_message_iter_);
643 return true;
644 }
645
646 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
647 dbus::MessageReader variant_reader(message_);
648 if (!PopVariant(&variant_reader))
649 return false;
650 return variant_reader.PopBasic(dbus_type, value);
651 }
652
653 } // namespace dbus
OLDNEW
« dbus/message.h ('K') | « dbus/message.h ('k') | dbus/message_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698