blob: 3f0cac480d2c079b4f7314f5a8bca1bebaa72fc7 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001/*
2 *
3 * D-Bus++ - C++ bindings for D-Bus
4 *
5 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <dbus-c++/message.h>
29
30#include <dbus/dbus.h>
31#include <cstdlib>
32
33#include "internalerror.h"
34#include "message_p.h"
35
36using namespace DBus;
37
38/*
39*/
40
41int MessageIter::type()
42{
43 return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter);
44}
45
46bool MessageIter::at_end()
47{
48 return type() == DBUS_TYPE_INVALID;
49}
50
51bool MessageIter::has_next()
52{
53 return dbus_message_iter_has_next((DBusMessageIter *)&_iter);
54}
55
56MessageIter &MessageIter::operator ++()
57{
58 dbus_message_iter_next((DBusMessageIter *)&_iter);
59 return (*this);
60}
61
62MessageIter MessageIter::operator ++(int)
63{
64 MessageIter copy(*this);
65 ++(*this);
66 return copy;
67}
68
69bool MessageIter::append_basic(int type_id, void *value)
70{
71 return dbus_message_iter_append_basic((DBusMessageIter *)&_iter, type_id, value);
72}
73
74void MessageIter::get_basic(int type_id, void *ptr)
75{
76 if (type() != type_id)
77 throw ErrorInvalidArgs("type mismatch");
78
79 dbus_message_iter_get_basic((DBusMessageIter *)_iter, ptr);
80}
81
82bool MessageIter::append_byte(unsigned char b)
83{
84 return append_basic(DBUS_TYPE_BYTE, &b);
85}
86
87unsigned char MessageIter::get_byte()
88{
89 unsigned char b;
90 get_basic(DBUS_TYPE_BYTE, &b);
91 return b;
92}
93
94bool MessageIter::append_bool(bool b)
95{
96 dbus_bool_t db = b;
97 return append_basic(DBUS_TYPE_BOOLEAN, &db);
98}
99
100bool MessageIter::get_bool()
101{
102 dbus_bool_t db;
103 get_basic(DBUS_TYPE_BOOLEAN, &db);
104 return (bool)db;
105}
106
107bool MessageIter::append_int16(signed short i)
108{
109 return append_basic(DBUS_TYPE_INT16, &i);
110}
111
112signed short MessageIter::get_int16()
113{
114 signed short i;
115 get_basic(DBUS_TYPE_INT16, &i);
116 return i;
117}
118
119bool MessageIter::append_uint16(unsigned short u)
120{
121 return append_basic(DBUS_TYPE_UINT16, &u);
122}
123
124unsigned short MessageIter::get_uint16()
125{
126 unsigned short u;
127 get_basic(DBUS_TYPE_UINT16, &u);
128 return u;
129}
130
131bool MessageIter::append_int32(signed int i)
132{
133 return append_basic(DBUS_TYPE_INT32, &i);
134}
135
136signed int MessageIter::get_int32()
137{
138 signed int i;
139 get_basic(DBUS_TYPE_INT32, &i);
140 return i;
141}
142
143bool MessageIter::append_uint32(unsigned int u)
144{
145 return append_basic(DBUS_TYPE_UINT32, &u);
146}
147
148unsigned int MessageIter::get_uint32()
149{
150 unsigned int u;
151 get_basic(DBUS_TYPE_UINT32, &u);
152 return u;
153}
154
155signed long long MessageIter::get_int64()
156{
157 signed long long i;
158 get_basic(DBUS_TYPE_INT64, &i);
159 return i;
160}
161
162bool MessageIter::append_int64(signed long long i)
163{
164 return append_basic(DBUS_TYPE_INT64, &i);
165}
166
167unsigned long long MessageIter::get_uint64()
168{
169 unsigned long long u;
170 get_basic(DBUS_TYPE_UINT64, &u);
171 return u;
172}
173
174bool MessageIter::append_uint64(unsigned long long u)
175{
176 return append_basic(DBUS_TYPE_UINT64, &u);
177}
178
179double MessageIter::get_double()
180{
181 double d;
182 get_basic(DBUS_TYPE_DOUBLE, &d);
183 return d;
184}
185
186bool MessageIter::append_double(double d)
187{
188 return append_basic(DBUS_TYPE_DOUBLE, &d);
189}
190
191bool MessageIter::append_string(const char *chars)
192{
193 return append_basic(DBUS_TYPE_STRING, &chars);
194}
195
196const char *MessageIter::get_string()
197{
198 char *chars;
199 get_basic(DBUS_TYPE_STRING, &chars);
200 return chars;
201}
202
203bool MessageIter::append_path(const char *chars)
204{
205 return append_basic(DBUS_TYPE_OBJECT_PATH, &chars);
206}
207
208const char *MessageIter::get_path()
209{
210 char *chars;
211 get_basic(DBUS_TYPE_OBJECT_PATH, &chars);
212 return chars;
213}
214
215bool MessageIter::append_signature(const char *chars)
216{
217 return append_basic(DBUS_TYPE_SIGNATURE, &chars);
218}
219
220const char *MessageIter::get_signature()
221{
222 char *chars;
223 get_basic(DBUS_TYPE_SIGNATURE, &chars);
224 return chars;
225}
226
227MessageIter MessageIter::recurse()
228{
229 MessageIter iter(msg());
230 dbus_message_iter_recurse((DBusMessageIter *)&_iter, (DBusMessageIter *) & (iter._iter));
231 return iter;
232}
233
234char *MessageIter::signature() const
235{
236 return dbus_message_iter_get_signature((DBusMessageIter *)&_iter);
237}
238
239bool MessageIter::append_array(char type, const void *ptr, size_t length)
240{
241 return dbus_message_iter_append_fixed_array((DBusMessageIter *)&_iter, type, &ptr, length);
242}
243
244int MessageIter::array_type()
245{
246 return dbus_message_iter_get_element_type((DBusMessageIter *)&_iter);
247}
248
249int MessageIter::get_array(void *ptr)
250{
251 int length;
252 dbus_message_iter_get_fixed_array((DBusMessageIter *)&_iter, ptr, &length);
253 return length;
254}
255
256bool MessageIter::is_array()
257{
258 return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter) == DBUS_TYPE_ARRAY;
259}
260
261bool MessageIter::is_dict()
262{
263 return is_array() && dbus_message_iter_get_element_type((DBusMessageIter *)_iter) == DBUS_TYPE_DICT_ENTRY;
264}
265
266MessageIter MessageIter::new_array(const char *sig)
267{
268 MessageIter arr(msg());
269 dbus_message_iter_open_container(
270 (DBusMessageIter *)&_iter, DBUS_TYPE_ARRAY, sig, (DBusMessageIter *) & (arr._iter)
271 );
272 return arr;
273}
274
275MessageIter MessageIter::new_variant(const char *sig)
276{
277 MessageIter var(msg());
278 dbus_message_iter_open_container(
279 (DBusMessageIter *)_iter, DBUS_TYPE_VARIANT, sig, (DBusMessageIter *) & (var._iter)
280 );
281 return var;
282}
283
284MessageIter MessageIter::new_struct()
285{
286 MessageIter stu(msg());
287 dbus_message_iter_open_container(
288 (DBusMessageIter *)_iter, DBUS_TYPE_STRUCT, NULL, (DBusMessageIter *) & (stu._iter)
289 );
290 return stu;
291}
292
293MessageIter MessageIter::new_dict_entry()
294{
295 MessageIter ent(msg());
296 dbus_message_iter_open_container(
297 (DBusMessageIter *)_iter, DBUS_TYPE_DICT_ENTRY, NULL, (DBusMessageIter *) & (ent._iter)
298 );
299 return ent;
300}
301
302void MessageIter::close_container(MessageIter &container)
303{
304 dbus_message_iter_close_container((DBusMessageIter *)&_iter, (DBusMessageIter *) & (container._iter));
305}
306
307static bool is_basic_type(int typecode)
308{
309 switch (typecode)
310 {
311 case 'y':
312 case 'b':
313 case 'n':
314 case 'q':
315 case 'i':
316 case 'u':
317 case 'x':
318 case 't':
319 case 'd':
320 case 's':
321 case 'o':
322 case 'g':
323 return true;
324 default:
325 return false;
326 }
327}
328
329void MessageIter::copy_data(MessageIter &to)
330{
331 for (MessageIter &from = *this; !from.at_end(); ++from)
332 {
333 if (is_basic_type(from.type()))
334 {
335 debug_log("copying basic type: %c", from.type());
336
337 unsigned char value[8];
338 from.get_basic(from.type(), &value);
339 to.append_basic(from.type(), &value);
340 }
341 else
342 {
343 MessageIter from_container = from.recurse();
344 char *sig = from_container.signature();
345
346 debug_log("copying compound type: %c[%s]", from.type(), sig);
347
348 MessageIter to_container(to.msg());
349 dbus_message_iter_open_container
350 (
351 (DBusMessageIter *) & (to._iter),
352 from.type(),
353 from.type() == DBUS_TYPE_VARIANT ? NULL : sig,
354 (DBusMessageIter *) & (to_container._iter)
355 );
356
357 from_container.copy_data(to_container);
358 to.close_container(to_container);
359 free(sig);
360 }
361 }
362}
363
364/*
365*/
366
367Message::Message()
368 : _pvt(new Private)
369{
370}
371
372Message::Message(Message::Private *p, bool incref)
373 : _pvt(p)
374{
375 if (_pvt->msg && incref) dbus_message_ref(_pvt->msg);
376}
377
378Message::Message(const Message &m)
379 : _pvt(m._pvt)
380{
381 dbus_message_ref(_pvt->msg);
382}
383
384Message::~Message()
385{
386 dbus_message_unref(_pvt->msg);
387}
388
389Message &Message::operator = (const Message &m)
390{
391 if (&m != this)
392 {
393 dbus_message_unref(_pvt->msg);
394 _pvt = m._pvt;
395 dbus_message_ref(_pvt->msg);
396 }
397 return *this;
398}
399
400Message Message::copy()
401{
402 Private *pvt = new Private(dbus_message_copy(_pvt->msg));
403 return Message(pvt);
404}
405
406bool Message::append(int first_type, ...)
407{
408 va_list vl;
409 va_start(vl, first_type);
410
411 bool b = dbus_message_append_args_valist(_pvt->msg, first_type, vl);
412
413 va_end(vl);
414 return b;
415}
416
417void Message::terminate()
418{
419 dbus_message_append_args(_pvt->msg, DBUS_TYPE_INVALID);
420}
421
422int Message::type() const
423{
424 return dbus_message_get_type(_pvt->msg);
425}
426
427int Message::serial() const
428{
429 return dbus_message_get_serial(_pvt->msg);
430}
431
432int Message::reply_serial() const
433{
434 return dbus_message_get_reply_serial(_pvt->msg);
435}
436
437bool Message::reply_serial(int s)
438{
439 return dbus_message_set_reply_serial(_pvt->msg, s);
440}
441
442const char *Message::sender() const
443{
444 return dbus_message_get_sender(_pvt->msg);
445}
446
447bool Message::sender(const char *s)
448{
449 return dbus_message_set_sender(_pvt->msg, s);
450}
451
452const char *Message::destination() const
453{
454 return dbus_message_get_destination(_pvt->msg);
455}
456
457bool Message::destination(const char *s)
458{
459 return dbus_message_set_destination(_pvt->msg, s);
460}
461
462bool Message::is_error() const
463{
464 return type() == DBUS_MESSAGE_TYPE_ERROR;
465}
466
467bool Message::is_signal(const char *interface, const char *member) const
468{
469 return dbus_message_is_signal(_pvt->msg, interface, member);
470}
471
472MessageIter Message::writer()
473{
474 MessageIter iter(*this);
475 dbus_message_iter_init_append(_pvt->msg, (DBusMessageIter *) & (iter._iter));
476 return iter;
477}
478
479MessageIter Message::reader() const
480{
481 MessageIter iter(const_cast<Message &>(*this));
482 dbus_message_iter_init(_pvt->msg, (DBusMessageIter *) & (iter._iter));
483 return iter;
484}
485
486/*
487*/
488
489ErrorMessage::ErrorMessage()
490{
491 _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
492}
493
494ErrorMessage::ErrorMessage(const Message &to_reply, const char *name, const char *message)
495{
496 _pvt->msg = dbus_message_new_error(to_reply._pvt->msg, name, message);
497}
498
499bool ErrorMessage::operator == (const ErrorMessage &m) const
500{
501 return dbus_message_is_error(_pvt->msg, m.name());
502}
503
504const char *ErrorMessage::name() const
505{
506 return dbus_message_get_error_name(_pvt->msg);
507}
508
509bool ErrorMessage::name(const char *n)
510{
511 return dbus_message_set_error_name(_pvt->msg, n);
512}
513
514/*
515*/
516
517SignalMessage::SignalMessage(const char *name)
518{
519 _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
520 member(name);
521}
522
523SignalMessage::SignalMessage(const char *path, const char *interface, const char *name)
524{
525 _pvt->msg = dbus_message_new_signal(path, interface, name);
526}
527
528bool SignalMessage::operator == (const SignalMessage &m) const
529{
530 return dbus_message_is_signal(_pvt->msg, m.interface(), m.member());
531}
532
533const char *SignalMessage::interface() const
534{
535 return dbus_message_get_interface(_pvt->msg);
536}
537
538bool SignalMessage::interface(const char *i)
539{
540 return dbus_message_set_interface(_pvt->msg, i);
541}
542
543const char *SignalMessage::member() const
544{
545 return dbus_message_get_member(_pvt->msg);
546}
547
548bool SignalMessage::member(const char *m)
549{
550 return dbus_message_set_member(_pvt->msg, m);
551}
552
553const char *SignalMessage::path() const
554{
555 return dbus_message_get_path(_pvt->msg);
556}
557
558char **SignalMessage::path_split() const
559{
560 char **p;
561 dbus_message_get_path_decomposed(_pvt->msg, &p); //todo: return as a std::vector ?
562 return p;
563}
564
565bool SignalMessage::path(const char *p)
566{
567 return dbus_message_set_path(_pvt->msg, p);
568}
569
570/*
571*/
572
573CallMessage::CallMessage()
574{
575 _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
576}
577
578CallMessage::CallMessage(const char *dest, const char *path, const char *iface, const char *method)
579{
580 _pvt->msg = dbus_message_new_method_call(dest, path, iface, method);
581}
582
583bool CallMessage::operator == (const CallMessage &m) const
584{
585 return dbus_message_is_method_call(_pvt->msg, m.interface(), m.member());
586}
587
588const char *CallMessage::interface() const
589{
590 return dbus_message_get_interface(_pvt->msg);
591}
592
593bool CallMessage::interface(const char *i)
594{
595 return dbus_message_set_interface(_pvt->msg, i);
596}
597
598const char *CallMessage::member() const
599{
600 return dbus_message_get_member(_pvt->msg);
601}
602
603bool CallMessage::member(const char *m)
604{
605 return dbus_message_set_member(_pvt->msg, m);
606}
607
608const char *CallMessage::path() const
609{
610 return dbus_message_get_path(_pvt->msg);
611}
612
613char **CallMessage::path_split() const
614{
615 char **p;
616 dbus_message_get_path_decomposed(_pvt->msg, &p);
617 return p;
618}
619
620bool CallMessage::path(const char *p)
621{
622 return dbus_message_set_path(_pvt->msg, p);
623}
624
625const char *CallMessage::signature() const
626{
627 return dbus_message_get_signature(_pvt->msg);
628}
629
630/*
631*/
632
633ReturnMessage::ReturnMessage(const CallMessage &callee)
634{
635 _pvt = new Private(dbus_message_new_method_return(callee._pvt->msg));
636}
637
638const char *ReturnMessage::signature() const
639{
640 return dbus_message_get_signature(_pvt->msg);
641}
642