2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004-2006 Net Integration Technologies, Inc.
6 * Copyright (C) 2007, Carillon Information Security Inc.
8 * This library is licensed under the LGPL, please read LICENSE for details.
11 #include "wvdbusmsg.h"
12 #include "wvdbusconn.h"
13 #include "wvstrutils.h"
14 #undef interface // windows
15 #include <dbus/dbus.h>
18 class WvDBusReplyMsg
: public WvDBusMsg
22 * Constructs a new reply message (a message intended to be a reply to
23 * an existing D-Bus message).
25 * Don't call this directly. Use WvDBusMsg::reply() instead.
27 WvDBusReplyMsg(DBusMessage
*_msg
);
29 virtual ~WvDBusReplyMsg() {}
34 WvDBusMsg::Iter::Iter(const WvDBusMsg
&_msg
)
35 : first(new DBusMessageIter
), it(new DBusMessageIter
)
37 dbus_message_iter_init(_msg
, first
);
42 WvDBusMsg::Iter::Iter(const WvDBusMsg::Iter
&_it
)
43 : first(new DBusMessageIter
), it(new DBusMessageIter
)
50 WvDBusMsg::Iter::Iter(const DBusMessageIter
&_first
)
51 : first(new DBusMessageIter
), it(new DBusMessageIter
)
58 WvDBusMsg::Iter::~Iter()
65 void WvDBusMsg::Iter::rewind()
71 bool WvDBusMsg::Iter::next()
75 else if (type() != DBUS_TYPE_INVALID
)
76 dbus_message_iter_next(it
);
78 return type() != DBUS_TYPE_INVALID
;
82 int WvDBusMsg::Iter::type() const
84 return dbus_message_iter_get_arg_type(it
);
88 WvDBusMsg::Iter
WvDBusMsg::Iter::open() const
91 dbus_message_iter_recurse(it
, &sub
);
96 bool WvDBusMsg::Iter::cur() const
98 return !rewound
&& type() != DBUS_TYPE_INVALID
;
102 void WvDBusMsg::Iter::get_all(WvStringList
&list
)
105 for (rewind(); next() && items
< 20; items
++)
106 list
.append(get_str());
112 WvString
WvDBusMsg::Iter::get_all()
116 return list
.join(",");
120 WvString
WvDBusMsg::Iter::get_str() const
128 return WvString("y%s", get_int());
129 case DBUS_TYPE_BOOLEAN
:
130 return WvString("b%s", get_int());
131 case DBUS_TYPE_INT16
:
132 case DBUS_TYPE_INT32
:
133 case DBUS_TYPE_INT64
:
135 case DBUS_TYPE_UINT16
:
136 case DBUS_TYPE_UINT32
:
137 case DBUS_TYPE_UINT64
:
139 case DBUS_TYPE_DOUBLE
:
140 dbus_message_iter_get_basic(it
, &d
);
142 case DBUS_TYPE_STRING
:
143 dbus_message_iter_get_basic(it
, &s
);
145 case DBUS_TYPE_VARIANT
:
146 return WvString("{%s}", open().getnext().get_str());
147 case DBUS_TYPE_STRUCT
:
148 case DBUS_TYPE_ARRAY
:
149 return WvString("[%s]", open().get_all());
150 case DBUS_TYPE_INVALID
:
153 return WvString("UNKNOWN_TYPE(%c)", type());
158 int64_t WvDBusMsg::Iter::get_int() const
170 dbus_message_iter_get_basic(it
, &c
);
173 case DBUS_TYPE_BOOLEAN
:
174 dbus_message_iter_get_basic(it
, &b
);
177 case DBUS_TYPE_INT16
:
178 case DBUS_TYPE_UINT16
:
179 dbus_message_iter_get_basic(it
, &s
);
182 case DBUS_TYPE_INT32
:
183 case DBUS_TYPE_UINT32
:
184 dbus_message_iter_get_basic(it
, &i
);
187 case DBUS_TYPE_INT64
:
188 case DBUS_TYPE_UINT64
:
189 dbus_message_iter_get_basic(it
, &l
);
192 case DBUS_TYPE_STRING
:
193 dbus_message_iter_get_basic(it
, &str
);
194 return WvString(str
).num();
196 case DBUS_TYPE_VARIANT
:
197 return open().getnext().get_int();
205 uint64_t WvDBusMsg::Iter::get_uint() const
217 dbus_message_iter_get_basic(it
, &c
);
220 case DBUS_TYPE_BOOLEAN
:
221 dbus_message_iter_get_basic(it
, &b
);
224 case DBUS_TYPE_INT16
:
225 case DBUS_TYPE_UINT16
:
226 dbus_message_iter_get_basic(it
, &s
);
229 case DBUS_TYPE_INT32
:
230 case DBUS_TYPE_UINT32
:
231 dbus_message_iter_get_basic(it
, &i
);
234 case DBUS_TYPE_INT64
:
235 case DBUS_TYPE_UINT64
:
236 dbus_message_iter_get_basic(it
, &l
);
239 case DBUS_TYPE_STRING
:
240 dbus_message_iter_get_basic(it
, &str
);
241 return WvString(str
).num();
243 case DBUS_TYPE_VARIANT
:
244 return open().getnext().get_uint();
252 double WvDBusMsg::Iter::get_double() const
264 case DBUS_TYPE_DOUBLE
:
265 dbus_message_iter_get_basic(it
, &d
);
269 dbus_message_iter_get_basic(it
, &c
);
272 case DBUS_TYPE_BOOLEAN
:
273 dbus_message_iter_get_basic(it
, &b
);
276 case DBUS_TYPE_INT16
:
277 case DBUS_TYPE_UINT16
:
278 dbus_message_iter_get_basic(it
, &s
);
281 case DBUS_TYPE_INT32
:
282 case DBUS_TYPE_UINT32
:
283 dbus_message_iter_get_basic(it
, &i
);
286 case DBUS_TYPE_INT64
:
287 case DBUS_TYPE_UINT64
:
288 dbus_message_iter_get_basic(it
, &l
);
291 case DBUS_TYPE_STRING
:
292 dbus_message_iter_get_basic(it
, &str
);
295 case DBUS_TYPE_VARIANT
:
296 return open().getnext().get_double();
304 WvString
*WvDBusMsg::Iter::ptr() const
313 static DBusMessageIter
*new_append_iter(WvDBusMsg
&msg
)
315 DBusMessageIter
*it
= new DBusMessageIter
;
316 dbus_message_iter_init_append(msg
, it
);
321 WvDBusMsg::WvDBusMsg(WvStringParm busname
, WvStringParm objectname
,
322 WvStringParm interface
, WvStringParm method
)
324 msg
= dbus_message_new_method_call(busname
, objectname
, interface
, method
);
325 itlist
.prepend(new_append_iter(*this), true);
329 WvDBusMsg::WvDBusMsg(WvDBusMsg
&_msg
)
332 dbus_message_ref(msg
);
333 itlist
.prepend(new_append_iter(*this), true);
337 WvDBusMsg::WvDBusMsg(DBusMessage
*_msg
)
340 dbus_message_ref(msg
);
341 itlist
.prepend(new_append_iter(*this), true);
345 WvDBusMsg::~WvDBusMsg()
347 dbus_message_unref(msg
);
351 WvDBusMsg::operator DBusMessage
* () const
357 WvString
WvDBusMsg::get_sender() const
359 return dbus_message_get_sender(msg
);
363 WvString
WvDBusMsg::get_dest() const
365 return dbus_message_get_destination(msg
);
369 WvString
WvDBusMsg::get_path() const
371 return dbus_message_get_path(msg
);
375 WvString
WvDBusMsg::get_interface() const
377 return dbus_message_get_interface(msg
);
381 WvString
WvDBusMsg::get_member() const
383 return dbus_message_get_member(msg
);
387 WvString
WvDBusMsg::get_error() const
390 return dbus_message_get_error_name(msg
);
392 return WvString::null
;
395 bool WvDBusMsg::is_reply() const
397 // This used to have a hack to deal with replies to message #0.
398 // But it turns out the first message is #1, so that's not an actual
400 return get_replyserial() != 0;
404 uint32_t WvDBusMsg::get_serial() const
406 return dbus_message_get_serial(msg
);
410 uint32_t WvDBusMsg::get_replyserial() const
412 return dbus_message_get_reply_serial(msg
);
416 void WvDBusMsg::get_arglist(WvStringList
&list
) const
418 Iter(*this).get_all(list
);
422 WvString
WvDBusMsg::get_argstr() const
424 return Iter(*this).get_all();
428 WvDBusMsg::operator WvString() const
433 return WvString("ERR#%s(%s)", get_replyserial(), get_argstr());
435 return WvString("REPLY#%s(%s)", get_replyserial(), get_argstr());
439 WvString
dest(get_dest());
443 dest
= WvString("%s:", dest
);
444 WvString
s("%s%s/%s.%s(%s)#%s",
446 get_path(), get_interface(), get_member(),
447 get_argstr(), get_serial());
448 s
= strreplace(s
, "org.freedesktop.DBus", "o.f.D");
449 s
= strreplace(s
, "org/freedesktop/DBus", "o/f/D");
455 WvDBusMsg
&WvDBusMsg::append(const char *s
)
459 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_STRING
, &s
);
464 WvDBusMsg
&WvDBusMsg::append(bool b
)
468 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_BOOLEAN
, &bb
);
473 WvDBusMsg
&WvDBusMsg::append(signed char c
)
476 dbus_unichar_t cc
= c
;
477 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_BYTE
, &cc
);
482 WvDBusMsg
&WvDBusMsg::append(unsigned char c
)
485 dbus_unichar_t cc
= c
;
486 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_BYTE
, &cc
);
491 WvDBusMsg
&WvDBusMsg::append(int16_t i
)
494 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_INT16
, &i
);
499 WvDBusMsg
&WvDBusMsg::append(uint16_t i
)
502 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_UINT16
, &i
);
507 WvDBusMsg
&WvDBusMsg::append(int32_t i
)
510 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_INT32
, &i
);
515 WvDBusMsg
&WvDBusMsg::append(uint32_t i
)
518 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_UINT32
, &i
);
523 WvDBusMsg
&WvDBusMsg::append(int64_t i
)
526 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_INT64
, &i
);
531 WvDBusMsg
&WvDBusMsg::append(uint64_t i
)
534 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_UINT64
, &i
);
539 WvDBusMsg
&WvDBusMsg::append(double d
)
542 dbus_message_iter_append_basic(itlist
.first(), DBUS_TYPE_DOUBLE
, &d
);
547 WvDBusMsg
&WvDBusMsg::variant_start(WvStringParm element_type
)
549 DBusMessageIter
*parent
= itlist
.first();
550 DBusMessageIter
*sub
= new DBusMessageIter
;
551 dbus_message_iter_open_container(parent
,
552 DBUS_TYPE_VARIANT
, element_type
, sub
);
553 itlist
.prepend(sub
, true);
558 WvDBusMsg
&WvDBusMsg::variant_end()
560 assert(itlist
.count() >= 2);
562 WvList
<DBusMessageIter
>::Iter
i(itlist
);
563 i
.rewind(); i
.next();
564 DBusMessageIter
*sub
= i
.ptr();
566 DBusMessageIter
*parent
= i
.ptr();
568 dbus_message_iter_close_container(parent
, sub
);
569 itlist
.unlink_first();
574 WvDBusMsg
&WvDBusMsg::struct_start(WvStringParm element_type
)
576 DBusMessageIter
*parent
= itlist
.first();
577 DBusMessageIter
*sub
= new DBusMessageIter
;
578 dbus_message_iter_open_container(parent
,
579 DBUS_TYPE_STRUCT
, 0, sub
);
580 itlist
.prepend(sub
, true);
585 WvDBusMsg
&WvDBusMsg::struct_end()
587 return array_end(); // same thing
591 WvDBusMsg
&WvDBusMsg::array_start(WvStringParm element_type
)
593 DBusMessageIter
*parent
= itlist
.first();
594 DBusMessageIter
*sub
= new DBusMessageIter
;
595 dbus_message_iter_open_container(parent
,
596 DBUS_TYPE_ARRAY
, element_type
, sub
);
597 itlist
.prepend(sub
, true);
602 WvDBusMsg
&WvDBusMsg::array_end()
604 return variant_end(); // same thing
608 WvDBusMsg
&WvDBusMsg::varray_start(WvStringParm element_type
)
610 variant_start(WvString("a%s", element_type
));
611 return array_start(element_type
);
615 WvDBusMsg
&WvDBusMsg::varray_end()
617 assert(itlist
.count() >= 3);
619 return variant_end();
623 WvDBusMsg
WvDBusMsg::reply()
625 return WvDBusReplyMsg(*this);
629 bool WvDBusMsg::iserror() const
631 return dbus_message_get_type(msg
) == DBUS_MESSAGE_TYPE_ERROR
;
635 void WvDBusMsg::send(WvDBusConn
&conn
)
641 WvDBusReplyMsg::WvDBusReplyMsg(DBusMessage
*_msg
)
642 : WvDBusMsg(dbus_message_new_method_return(_msg
))
644 dbus_message_unref(msg
);
648 WvDBusSignal::WvDBusSignal(WvStringParm objectname
, WvStringParm interface
,
650 : WvDBusMsg(dbus_message_new_signal(objectname
, interface
, name
))
652 dbus_message_unref(msg
);
656 DBusMessage
*WvDBusError::setup1(WvDBusMsg
&in_reply_to
,
657 WvStringParm errname
, WvStringParm message
)
659 return dbus_message_new_error(in_reply_to
, errname
, message
);
662 void WvDBusError::setup2()
664 dbus_message_unref(msg
);