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

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