WvStreams
wvdbusmsg.cc
1/* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004-2006 Net Integration Technologies, Inc.
4 *
5 * Pathfinder Software:
6 * Copyright (C) 2007, Carillon Information Security Inc.
7 *
8 * This library is licensed under the LGPL, please read LICENSE for details.
9 *
10 */
11#include "wvdbusmsg.h"
12#include "wvdbusconn.h"
13#include "wvstrutils.h"
14#undef interface // windows
15#include <dbus/dbus.h>
16
17
19{
20public:
27 WvDBusReplyMsg(DBusMessage *_msg);
28
29 virtual ~WvDBusReplyMsg() {}
30};
31
32
33
34WvDBusMsg::Iter::Iter(const WvDBusMsg &_msg)
35 : first(new DBusMessageIter), it(new DBusMessageIter)
36{
37 dbus_message_iter_init(_msg, first);
38 rewind();
39}
40
41
42WvDBusMsg::Iter::Iter(const WvDBusMsg::Iter &_it)
43 : first(new DBusMessageIter), it(new DBusMessageIter)
44{
45 *first = *_it.first;
46 rewind();
47}
48
49
50WvDBusMsg::Iter::Iter(const DBusMessageIter &_first)
51 : first(new DBusMessageIter), it(new DBusMessageIter)
52{
53 *first = _first;
54 rewind();
55}
56
57
58WvDBusMsg::Iter::~Iter()
59{
60 delete first;
61 delete it;
62}
63
64
66{
67 rewound = true;
68}
69
70
72{
73 if (rewound)
74 *it = *first;
75 else if (type() != DBUS_TYPE_INVALID)
76 dbus_message_iter_next(it);
77 rewound = false;
78 return type() != DBUS_TYPE_INVALID;
79}
80
81
83{
84 return dbus_message_iter_get_arg_type(it);
85}
86
87
89{
90 DBusMessageIter sub;
91 dbus_message_iter_recurse(it, &sub);
92 return Iter(sub);
93}
94
95
97{
98 return !rewound && type() != DBUS_TYPE_INVALID;
99}
100
101
103{
104 int items = 0;
105 for (rewind(); next() && items < 20; items++)
106 list.append(get_str());
107 if (items == 20)
108 list.append("...");
109}
110
111
113{
114 WvStringList list;
115 get_all(list);
116 return list.join(",");
117}
118
119
121{
122 char *s;
123 double d;
124
125 switch (type())
126 {
127 case DBUS_TYPE_BYTE:
128 // Don't do this: things like vxodbc expect to be able to atoi()
129 // the resulting string!
130 //return WvString("y%s", get_int());
131 case DBUS_TYPE_BOOLEAN:
132 //return WvString("b%s", get_int());
133 case DBUS_TYPE_INT16:
134 case DBUS_TYPE_INT32:
135 case DBUS_TYPE_INT64:
136 return get_int();
137 case DBUS_TYPE_UINT16:
138 case DBUS_TYPE_UINT32:
139 case DBUS_TYPE_UINT64:
140 return get_uint();
141 case DBUS_TYPE_DOUBLE:
142 dbus_message_iter_get_basic(it, &d);
143 return d;
144 case DBUS_TYPE_STRING:
145 dbus_message_iter_get_basic(it, &s);
146 return s;
147 case DBUS_TYPE_VARIANT:
148 return WvString("{%s}", open().getnext().get_str());
149 case DBUS_TYPE_STRUCT:
150 case DBUS_TYPE_ARRAY:
151 return WvString("[%s]", open().get_all());
152 case DBUS_TYPE_INVALID:
153 return WvString();
154 default:
155 return WvString("UNKNOWN_TYPE(%c)", type());
156 }
157}
158
159
161{
162 dbus_bool_t b;
163 unsigned char c;
164 dbus_int16_t s;
165 dbus_int32_t i;
166 dbus_int64_t l;
167 char *str;
168
169 switch (type())
170 {
171 case DBUS_TYPE_BYTE:
172 dbus_message_iter_get_basic(it, &c);
173 return c;
174
175 case DBUS_TYPE_BOOLEAN:
176 dbus_message_iter_get_basic(it, &b);
177 return b;
178
179 case DBUS_TYPE_INT16:
180 case DBUS_TYPE_UINT16:
181 dbus_message_iter_get_basic(it, &s);
182 return s;
183
184 case DBUS_TYPE_INT32:
185 case DBUS_TYPE_UINT32:
186 dbus_message_iter_get_basic(it, &i);
187 return i;
188
189 case DBUS_TYPE_INT64:
190 case DBUS_TYPE_UINT64:
191 dbus_message_iter_get_basic(it, &l);
192 return l;
193
194 case DBUS_TYPE_STRING:
195 dbus_message_iter_get_basic(it, &str);
196 return WvString(str).num();
197
198 case DBUS_TYPE_VARIANT:
199 return open().getnext().get_int();
200
201 default:
202 return 0;
203 }
204}
205
206
208{
209 dbus_bool_t b;
210 unsigned char c;
211 dbus_uint16_t s;
212 dbus_uint32_t i;
213 dbus_uint64_t l;
214 char *str;
215
216 switch (type())
217 {
218 case DBUS_TYPE_BYTE:
219 dbus_message_iter_get_basic(it, &c);
220 return c;
221
222 case DBUS_TYPE_BOOLEAN:
223 dbus_message_iter_get_basic(it, &b);
224 return b;
225
226 case DBUS_TYPE_INT16:
227 case DBUS_TYPE_UINT16:
228 dbus_message_iter_get_basic(it, &s);
229 return s;
230
231 case DBUS_TYPE_INT32:
232 case DBUS_TYPE_UINT32:
233 dbus_message_iter_get_basic(it, &i);
234 return i;
235
236 case DBUS_TYPE_INT64:
237 case DBUS_TYPE_UINT64:
238 dbus_message_iter_get_basic(it, &l);
239 return l;
240
241 case DBUS_TYPE_STRING:
242 dbus_message_iter_get_basic(it, &str);
243 return WvString(str).num();
244
245 case DBUS_TYPE_VARIANT:
246 return open().getnext().get_uint();
247
248 default:
249 return 0;
250 }
251}
252
253
255{
256 dbus_bool_t b;
257 unsigned char c;
258 dbus_uint16_t s;
259 dbus_uint32_t i;
260 dbus_uint64_t l;
261 char *str;
262 double d;
263
264 switch (type())
265 {
266 case DBUS_TYPE_DOUBLE:
267 dbus_message_iter_get_basic(it, &d);
268 return d;
269
270 case DBUS_TYPE_BYTE:
271 dbus_message_iter_get_basic(it, &c);
272 return c;
273
274 case DBUS_TYPE_BOOLEAN:
275 dbus_message_iter_get_basic(it, &b);
276 return b;
277
278 case DBUS_TYPE_INT16:
279 case DBUS_TYPE_UINT16:
280 dbus_message_iter_get_basic(it, &s);
281 return s;
282
283 case DBUS_TYPE_INT32:
284 case DBUS_TYPE_UINT32:
285 dbus_message_iter_get_basic(it, &i);
286 return i;
287
288 case DBUS_TYPE_INT64:
289 case DBUS_TYPE_UINT64:
290 dbus_message_iter_get_basic(it, &l);
291 return l;
292
293 case DBUS_TYPE_STRING:
294 dbus_message_iter_get_basic(it, &str);
295 return atof(str);
296
297 case DBUS_TYPE_VARIANT:
298 return open().getnext().get_double();
299
300 default:
301 return 0;
302 }
303}
304
305
307{
308 s = get_str();
309 return &s;
310}
311
312
313
314
315static DBusMessageIter *new_append_iter(WvDBusMsg &msg)
316{
317 DBusMessageIter *it = new DBusMessageIter;
318 dbus_message_iter_init_append(msg, it);
319 return it;
320}
321
322
324 WvStringParm interface, WvStringParm method)
325{
326 msg = dbus_message_new_method_call(busname, objectname, interface, method);
327 itlist.prepend(new_append_iter(*this), true);
328}
329
330
332{
333 msg = _msg.msg;
334 dbus_message_ref(msg);
335 itlist.prepend(new_append_iter(*this), true);
336}
337
338
339WvDBusMsg::WvDBusMsg(DBusMessage *_msg)
340{
341 msg = _msg;
342 dbus_message_ref(msg);
343 itlist.prepend(new_append_iter(*this), true);
344}
345
346
347WvDBusMsg::~WvDBusMsg()
348{
349 dbus_message_unref(msg);
350}
351
352
353WvDBusMsg::operator DBusMessage* () const
354{
355 return msg;
356}
357
358
359WvString WvDBusMsg::get_sender() const
360{
361 return dbus_message_get_sender(msg);
362}
363
364
365WvString WvDBusMsg::get_dest() const
366{
367 return dbus_message_get_destination(msg);
368}
369
370
371WvString WvDBusMsg::get_path() const
372{
373 return dbus_message_get_path(msg);
374}
375
376
377WvString WvDBusMsg::get_interface() const
378{
379 return dbus_message_get_interface(msg);
380}
381
382
383WvString WvDBusMsg::get_member() const
384{
385 return dbus_message_get_member(msg);
386}
387
388
389WvString WvDBusMsg::get_error() const
390{
391 if (iserror())
392 return dbus_message_get_error_name(msg);
393
394 return WvString::null;
395}
396
397bool WvDBusMsg::is_reply() const
398{
399 // This used to have a hack to deal with replies to message #0.
400 // But it turns out the first message is #1, so that's not an actual
401 // problem.
402 return get_replyserial() != 0;
403}
404
405
406uint32_t WvDBusMsg::get_serial() const
407{
408 return dbus_message_get_serial(msg);
409}
410
411
412uint32_t WvDBusMsg::get_replyserial() const
413{
414 return dbus_message_get_reply_serial(msg);
415}
416
417
418void WvDBusMsg::get_arglist(WvStringList &list) const
419{
420 Iter(*this).get_all(list);
421}
422
423
424WvString WvDBusMsg::get_argstr() const
425{
426 return Iter(*this).get_all();
427}
428
429
430WvDBusMsg::operator WvString() const
431{
432 WvString dest(get_dest());
433 if (!dest)
434 dest = "";
435 else
436 dest = WvString("%s:", dest);
437 if (is_reply())
438 {
439 if (iserror())
440 return WvString("ERR#%s->%s#%s(%s)",
441 get_serial(), dest, get_replyserial(),
442 get_argstr());
443 else
444 return WvString("REPLY#%s->%s#%s(%s)",
445 get_serial(), dest, get_replyserial(),
446 get_argstr());
447 }
448 else
449 {
450 WvString s("%s%s/%s.%s(%s)#%s",
451 dest,
452 get_path(), get_interface(), get_member(),
453 get_argstr(), get_serial());
454 s = strreplace(s, "org.freedesktop.DBus", "o.f.D");
455 s = strreplace(s, "org/freedesktop/DBus", "o/f/D");
456 return s;
457 }
458}
459
460
462{
463 assert(msg);
464 assert(s);
465 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_STRING, &s);
466 return *this;
467}
468
469
471{
472 assert(msg);
473 dbus_bool_t bb = b;
474 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BOOLEAN, &bb);
475 return *this;
476}
477
478
479WvDBusMsg &WvDBusMsg::append(signed char c)
480{
481 assert(msg);
482 dbus_unichar_t cc = c;
483 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
484 return *this;
485}
486
487
488WvDBusMsg &WvDBusMsg::append(unsigned char c)
489{
490 assert(msg);
491 dbus_unichar_t cc = c;
492 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc);
493 return *this;
494}
495
496
498{
499 assert(msg);
500 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT16, &i);
501 return *this;
502}
503
504
505WvDBusMsg &WvDBusMsg::append(uint16_t i)
506{
507 assert(msg);
508 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT16, &i);
509 return *this;
510}
511
512
514{
515 assert(msg);
516 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT32, &i);
517 return *this;
518}
519
520
521WvDBusMsg &WvDBusMsg::append(uint32_t i)
522{
523 assert(msg);
524 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT32, &i);
525 return *this;
526}
527
528
530{
531 assert(msg);
532 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT64, &i);
533 return *this;
534}
535
536
537WvDBusMsg &WvDBusMsg::append(uint64_t i)
538{
539 assert(msg);
540 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT64, &i);
541 return *this;
542}
543
544
546{
547 assert(msg);
548 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_DOUBLE, &d);
549 return *this;
550}
551
552
554{
555 DBusMessageIter *parent = itlist.first();
556 DBusMessageIter *sub = new DBusMessageIter;
557 dbus_message_iter_open_container(parent,
558 DBUS_TYPE_VARIANT, element_type, sub);
559 itlist.prepend(sub, true);
560 return *this;
561}
562
563
565{
566 assert(itlist.count() >= 2);
567
569 i.rewind(); i.next();
570 DBusMessageIter *sub = i.ptr();
571 i.next();
572 DBusMessageIter *parent = i.ptr();
573
574 dbus_message_iter_close_container(parent, sub);
575 itlist.unlink_first();
576 return *this;
577}
578
579
581{
582 DBusMessageIter *parent = itlist.first();
583 DBusMessageIter *sub = new DBusMessageIter;
584 dbus_message_iter_open_container(parent,
585 DBUS_TYPE_STRUCT, 0, sub);
586 itlist.prepend(sub, true);
587 return *this;
588}
589
590
592{
593 return array_end(); // same thing
594}
595
596
598{
599 DBusMessageIter *parent = itlist.first();
600 DBusMessageIter *sub = new DBusMessageIter;
601 dbus_message_iter_open_container(parent,
602 DBUS_TYPE_ARRAY, element_type, sub);
603 itlist.prepend(sub, true);
604 return *this;
605}
606
607
609{
610 return variant_end(); // same thing
611}
612
613
615{
616 variant_start(WvString("a%s", element_type));
617 return array_start(element_type);
618}
619
620
622{
623 assert(itlist.count() >= 3);
624 array_end();
625 return variant_end();
626}
627
628
630{
631 return WvDBusReplyMsg(*this);
632}
633
634
636{
637 return dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR;
638}
639
640
642{
643 conn.send(*this);
644}
645
646
648 : WvDBusMsg(dbus_message_new_method_return(_msg))
649{
650 dbus_message_unref(msg);
651}
652
653
654WvDBusSignal::WvDBusSignal(WvStringParm objectname, WvStringParm interface,
655 WvStringParm name)
656 : WvDBusMsg(dbus_message_new_signal(objectname, interface, name))
657{
658 dbus_message_unref(msg);
659}
660
661
662DBusMessage *WvDBusError::setup1(WvDBusMsg &in_reply_to,
663 WvStringParm errname, WvStringParm message)
664{
665 return dbus_message_new_error(in_reply_to, errname, message);
666}
667
668void WvDBusError::setup2()
669{
670 dbus_message_unref(msg);
671}
uint32_t send(WvDBusMsg msg)
Send a message on the bus, not expecting any reply.
uint64_t get_uint() const
Get the current element as a uint64_t (possible for all integer types)
Definition wvdbusmsg.cc:207
Iter open() const
Returns a sub-iterator for walking through recursive types, such as arrays, structs,...
Definition wvdbusmsg.cc:88
bool next()
Moves the iterator along the list to point to the next element.
Definition wvdbusmsg.cc:71
bool cur() const
Returns: true if the current link is valid.
Definition wvdbusmsg.cc:96
int type() const
Returns the data type of the current element.
Definition wvdbusmsg.cc:82
double get_double() const
Get the current element as a double (possible for all integer and floating point types)
Definition wvdbusmsg.cc:254
WvString get_all()
Return a WvString representation of all elements in a single string.
Definition wvdbusmsg.cc:112
WvString get_str() const
Get the current element as a string (possible for all types).
Definition wvdbusmsg.cc:120
WvString * ptr() const
Returns a pointer to the WvString at the iterator's current location.
Definition wvdbusmsg.cc:306
void rewind()
Rewinds the iterator to make it point to an imaginary element preceeding the first element of the lis...
Definition wvdbusmsg.cc:65
int64_t get_int() const
Get the current element as an int64_t (possible for all integer types)
Definition wvdbusmsg.cc:160
WvDBusMsg reply()
Generate a message that will be a reply to this one.
Definition wvdbusmsg.cc:629
void send(WvDBusConn &conn)
A shortcut for sending this message on the given connection.
Definition wvdbusmsg.cc:641
WvDBusMsg & struct_start(WvStringParm element_type)
Start a struct.
Definition wvdbusmsg.cc:580
WvDBusMsg & append(const char *s)
The following methods are designed to allow appending various arguments to the message.
Definition wvdbusmsg.cc:461
WvDBusMsg(WvStringParm busname, WvStringParm objectname, WvStringParm ifc, WvStringParm method)
Constructs a new WvDBus message.
Definition wvdbusmsg.cc:323
WvDBusMsg & varray_start(WvStringParm element_type)
Start a variant-array.
Definition wvdbusmsg.cc:614
WvDBusMsg & variant_end()
End a variant.
Definition wvdbusmsg.cc:564
WvDBusMsg & struct_end()
End a struct started with struct_start().
Definition wvdbusmsg.cc:591
WvDBusMsg & variant_start(WvStringParm element_type)
Start a variant.
Definition wvdbusmsg.cc:553
bool iserror() const
Return true if this message is an error response.
Definition wvdbusmsg.cc:635
WvDBusMsg & array_start(WvStringParm element_type)
Start an array.
Definition wvdbusmsg.cc:597
WvDBusMsg & varray_end()
End an array started with array_start().
Definition wvdbusmsg.cc:621
WvDBusMsg & array_end()
End an array started with array_start().
Definition wvdbusmsg.cc:608
WvDBusReplyMsg(DBusMessage *_msg)
Constructs a new reply message (a message intended to be a reply to an existing D-Bus message).
Definition wvdbusmsg.cc:647
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
int num() const
Return a stdc++ string with the contents of this string.
void rewind()
Rewinds the iterator to make it point to an imaginary element preceeding the first element of the lis...
WvLink * next()
Moves the iterator along the list to point to the next element.
size_t count() const
Returns the number of elements in the list.
Definition wvlinklist.cc:24
T * ptr() const
Returns a pointer to the current element.
void unlink_first()
Unlinks the first element from the list.
void prepend(T *data, bool autofree, const char *id=NULL)
Prepends the element to the beginning of the list.
T * first() const
Returns a pointer to the first element in the linked list.
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString join(const char *joinchars=" ") const
concatenates all elements of the list seperating on joinchars
WvString is an implementation of a simple and efficient printable-string class.
WvString strreplace(WvStringParm s, WvStringParm a, WvStringParm b)
Replace any instances of "a" with "b" in "s".
Definition strutils.cc:797