WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2004-2006 Net Integration Technologies, Inc. 00004 * 00005 * Pathfinder Software: 00006 * Copyright (C) 2007, Carillon Information Security Inc. 00007 * 00008 * This library is licensed under the LGPL, please read LICENSE for details. 00009 * 00010 */ 00011 #include "wvdbusmsg.h" 00012 #include "wvdbusconn.h" 00013 #include "wvstrutils.h" 00014 #undef interface // windows 00015 #include <dbus/dbus.h> 00016 00017 00018 class WvDBusReplyMsg : public WvDBusMsg 00019 { 00020 public: 00027 WvDBusReplyMsg(DBusMessage *_msg); 00028 00029 virtual ~WvDBusReplyMsg() {} 00030 }; 00031 00032 00033 00034 WvDBusMsg::Iter::Iter(const WvDBusMsg &_msg) 00035 : first(new DBusMessageIter), it(new DBusMessageIter) 00036 { 00037 dbus_message_iter_init(_msg, first); 00038 rewind(); 00039 } 00040 00041 00042 WvDBusMsg::Iter::Iter(const WvDBusMsg::Iter &_it) 00043 : first(new DBusMessageIter), it(new DBusMessageIter) 00044 { 00045 *first = *_it.first; 00046 rewind(); 00047 } 00048 00049 00050 WvDBusMsg::Iter::Iter(const DBusMessageIter &_first) 00051 : first(new DBusMessageIter), it(new DBusMessageIter) 00052 { 00053 *first = _first; 00054 rewind(); 00055 } 00056 00057 00058 WvDBusMsg::Iter::~Iter() 00059 { 00060 delete first; 00061 delete it; 00062 } 00063 00064 00065 void WvDBusMsg::Iter::rewind() 00066 { 00067 rewound = true; 00068 } 00069 00070 00071 bool WvDBusMsg::Iter::next() 00072 { 00073 if (rewound) 00074 *it = *first; 00075 else if (type() != DBUS_TYPE_INVALID) 00076 dbus_message_iter_next(it); 00077 rewound = false; 00078 return type() != DBUS_TYPE_INVALID; 00079 } 00080 00081 00082 int WvDBusMsg::Iter::type() const 00083 { 00084 return dbus_message_iter_get_arg_type(it); 00085 } 00086 00087 00088 WvDBusMsg::Iter WvDBusMsg::Iter::open() const 00089 { 00090 DBusMessageIter sub; 00091 dbus_message_iter_recurse(it, &sub); 00092 return Iter(sub); 00093 } 00094 00095 00096 bool WvDBusMsg::Iter::cur() const 00097 { 00098 return !rewound && type() != DBUS_TYPE_INVALID; 00099 } 00100 00101 00102 void WvDBusMsg::Iter::get_all(WvStringList &list) 00103 { 00104 int items = 0; 00105 for (rewind(); next() && items < 20; items++) 00106 list.append(get_str()); 00107 if (items == 20) 00108 list.append("..."); 00109 } 00110 00111 00112 WvString WvDBusMsg::Iter::get_all() 00113 { 00114 WvStringList list; 00115 get_all(list); 00116 return list.join(","); 00117 } 00118 00119 00120 WvString WvDBusMsg::Iter::get_str() const 00121 { 00122 char *s; 00123 double d; 00124 00125 switch (type()) 00126 { 00127 case DBUS_TYPE_BYTE: 00128 // Don't do this: things like vxodbc expect to be able to atoi() 00129 // the resulting string! 00130 //return WvString("y%s", get_int()); 00131 case DBUS_TYPE_BOOLEAN: 00132 //return WvString("b%s", get_int()); 00133 case DBUS_TYPE_INT16: 00134 case DBUS_TYPE_INT32: 00135 case DBUS_TYPE_INT64: 00136 return get_int(); 00137 case DBUS_TYPE_UINT16: 00138 case DBUS_TYPE_UINT32: 00139 case DBUS_TYPE_UINT64: 00140 return get_uint(); 00141 case DBUS_TYPE_DOUBLE: 00142 dbus_message_iter_get_basic(it, &d); 00143 return d; 00144 case DBUS_TYPE_STRING: 00145 dbus_message_iter_get_basic(it, &s); 00146 return s; 00147 case DBUS_TYPE_VARIANT: 00148 return WvString("{%s}", open().getnext().get_str()); 00149 case DBUS_TYPE_STRUCT: 00150 case DBUS_TYPE_ARRAY: 00151 return WvString("[%s]", open().get_all()); 00152 case DBUS_TYPE_INVALID: 00153 return WvString(); 00154 default: 00155 return WvString("UNKNOWN_TYPE(%c)", type()); 00156 } 00157 } 00158 00159 00160 int64_t WvDBusMsg::Iter::get_int() const 00161 { 00162 dbus_bool_t b; 00163 unsigned char c; 00164 dbus_int16_t s; 00165 dbus_int32_t i; 00166 dbus_int64_t l; 00167 char *str; 00168 00169 switch (type()) 00170 { 00171 case DBUS_TYPE_BYTE: 00172 dbus_message_iter_get_basic(it, &c); 00173 return c; 00174 00175 case DBUS_TYPE_BOOLEAN: 00176 dbus_message_iter_get_basic(it, &b); 00177 return b; 00178 00179 case DBUS_TYPE_INT16: 00180 case DBUS_TYPE_UINT16: 00181 dbus_message_iter_get_basic(it, &s); 00182 return s; 00183 00184 case DBUS_TYPE_INT32: 00185 case DBUS_TYPE_UINT32: 00186 dbus_message_iter_get_basic(it, &i); 00187 return i; 00188 00189 case DBUS_TYPE_INT64: 00190 case DBUS_TYPE_UINT64: 00191 dbus_message_iter_get_basic(it, &l); 00192 return l; 00193 00194 case DBUS_TYPE_STRING: 00195 dbus_message_iter_get_basic(it, &str); 00196 return WvString(str).num(); 00197 00198 case DBUS_TYPE_VARIANT: 00199 return open().getnext().get_int(); 00200 00201 default: 00202 return 0; 00203 } 00204 } 00205 00206 00207 uint64_t WvDBusMsg::Iter::get_uint() const 00208 { 00209 dbus_bool_t b; 00210 unsigned char c; 00211 dbus_uint16_t s; 00212 dbus_uint32_t i; 00213 dbus_uint64_t l; 00214 char *str; 00215 00216 switch (type()) 00217 { 00218 case DBUS_TYPE_BYTE: 00219 dbus_message_iter_get_basic(it, &c); 00220 return c; 00221 00222 case DBUS_TYPE_BOOLEAN: 00223 dbus_message_iter_get_basic(it, &b); 00224 return b; 00225 00226 case DBUS_TYPE_INT16: 00227 case DBUS_TYPE_UINT16: 00228 dbus_message_iter_get_basic(it, &s); 00229 return s; 00230 00231 case DBUS_TYPE_INT32: 00232 case DBUS_TYPE_UINT32: 00233 dbus_message_iter_get_basic(it, &i); 00234 return i; 00235 00236 case DBUS_TYPE_INT64: 00237 case DBUS_TYPE_UINT64: 00238 dbus_message_iter_get_basic(it, &l); 00239 return l; 00240 00241 case DBUS_TYPE_STRING: 00242 dbus_message_iter_get_basic(it, &str); 00243 return WvString(str).num(); 00244 00245 case DBUS_TYPE_VARIANT: 00246 return open().getnext().get_uint(); 00247 00248 default: 00249 return 0; 00250 } 00251 } 00252 00253 00254 double WvDBusMsg::Iter::get_double() const 00255 { 00256 dbus_bool_t b; 00257 unsigned char c; 00258 dbus_uint16_t s; 00259 dbus_uint32_t i; 00260 dbus_uint64_t l; 00261 char *str; 00262 double d; 00263 00264 switch (type()) 00265 { 00266 case DBUS_TYPE_DOUBLE: 00267 dbus_message_iter_get_basic(it, &d); 00268 return d; 00269 00270 case DBUS_TYPE_BYTE: 00271 dbus_message_iter_get_basic(it, &c); 00272 return c; 00273 00274 case DBUS_TYPE_BOOLEAN: 00275 dbus_message_iter_get_basic(it, &b); 00276 return b; 00277 00278 case DBUS_TYPE_INT16: 00279 case DBUS_TYPE_UINT16: 00280 dbus_message_iter_get_basic(it, &s); 00281 return s; 00282 00283 case DBUS_TYPE_INT32: 00284 case DBUS_TYPE_UINT32: 00285 dbus_message_iter_get_basic(it, &i); 00286 return i; 00287 00288 case DBUS_TYPE_INT64: 00289 case DBUS_TYPE_UINT64: 00290 dbus_message_iter_get_basic(it, &l); 00291 return l; 00292 00293 case DBUS_TYPE_STRING: 00294 dbus_message_iter_get_basic(it, &str); 00295 return atof(str); 00296 00297 case DBUS_TYPE_VARIANT: 00298 return open().getnext().get_double(); 00299 00300 default: 00301 return 0; 00302 } 00303 } 00304 00305 00306 WvString *WvDBusMsg::Iter::ptr() const 00307 { 00308 s = get_str(); 00309 return &s; 00310 } 00311 00312 00313 00314 00315 static DBusMessageIter *new_append_iter(WvDBusMsg &msg) 00316 { 00317 DBusMessageIter *it = new DBusMessageIter; 00318 dbus_message_iter_init_append(msg, it); 00319 return it; 00320 } 00321 00322 00323 WvDBusMsg::WvDBusMsg(WvStringParm busname, WvStringParm objectname, 00324 WvStringParm interface, WvStringParm method) 00325 { 00326 msg = dbus_message_new_method_call(busname, objectname, interface, method); 00327 itlist.prepend(new_append_iter(*this), true); 00328 } 00329 00330 00331 WvDBusMsg::WvDBusMsg(WvDBusMsg &_msg) 00332 { 00333 msg = _msg.msg; 00334 dbus_message_ref(msg); 00335 itlist.prepend(new_append_iter(*this), true); 00336 } 00337 00338 00339 WvDBusMsg::WvDBusMsg(DBusMessage *_msg) 00340 { 00341 msg = _msg; 00342 dbus_message_ref(msg); 00343 itlist.prepend(new_append_iter(*this), true); 00344 } 00345 00346 00347 WvDBusMsg::~WvDBusMsg() 00348 { 00349 dbus_message_unref(msg); 00350 } 00351 00352 00353 WvDBusMsg::operator DBusMessage* () const 00354 { 00355 return msg; 00356 } 00357 00358 00359 WvString WvDBusMsg::get_sender() const 00360 { 00361 return dbus_message_get_sender(msg); 00362 } 00363 00364 00365 WvString WvDBusMsg::get_dest() const 00366 { 00367 return dbus_message_get_destination(msg); 00368 } 00369 00370 00371 WvString WvDBusMsg::get_path() const 00372 { 00373 return dbus_message_get_path(msg); 00374 } 00375 00376 00377 WvString WvDBusMsg::get_interface() const 00378 { 00379 return dbus_message_get_interface(msg); 00380 } 00381 00382 00383 WvString WvDBusMsg::get_member() const 00384 { 00385 return dbus_message_get_member(msg); 00386 } 00387 00388 00389 WvString WvDBusMsg::get_error() const 00390 { 00391 if (iserror()) 00392 return dbus_message_get_error_name(msg); 00393 00394 return WvString::null; 00395 } 00396 00397 bool WvDBusMsg::is_reply() const 00398 { 00399 // This used to have a hack to deal with replies to message #0. 00400 // But it turns out the first message is #1, so that's not an actual 00401 // problem. 00402 return get_replyserial() != 0; 00403 } 00404 00405 00406 uint32_t WvDBusMsg::get_serial() const 00407 { 00408 return dbus_message_get_serial(msg); 00409 } 00410 00411 00412 uint32_t WvDBusMsg::get_replyserial() const 00413 { 00414 return dbus_message_get_reply_serial(msg); 00415 } 00416 00417 00418 void WvDBusMsg::get_arglist(WvStringList &list) const 00419 { 00420 Iter(*this).get_all(list); 00421 } 00422 00423 00424 WvString WvDBusMsg::get_argstr() const 00425 { 00426 return Iter(*this).get_all(); 00427 } 00428 00429 00430 WvDBusMsg::operator WvString() const 00431 { 00432 WvString dest(get_dest()); 00433 if (!dest) 00434 dest = ""; 00435 else 00436 dest = WvString("%s:", dest); 00437 if (is_reply()) 00438 { 00439 if (iserror()) 00440 return WvString("ERR#%s->%s#%s(%s)", 00441 get_serial(), dest, get_replyserial(), 00442 get_argstr()); 00443 else 00444 return WvString("REPLY#%s->%s#%s(%s)", 00445 get_serial(), dest, get_replyserial(), 00446 get_argstr()); 00447 } 00448 else 00449 { 00450 WvString s("%s%s/%s.%s(%s)#%s", 00451 dest, 00452 get_path(), get_interface(), get_member(), 00453 get_argstr(), get_serial()); 00454 s = strreplace(s, "org.freedesktop.DBus", "o.f.D"); 00455 s = strreplace(s, "org/freedesktop/DBus", "o/f/D"); 00456 return s; 00457 } 00458 } 00459 00460 00461 WvDBusMsg &WvDBusMsg::append(const char *s) 00462 { 00463 assert(msg); 00464 assert(s); 00465 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_STRING, &s); 00466 return *this; 00467 } 00468 00469 00470 WvDBusMsg &WvDBusMsg::append(bool b) 00471 { 00472 assert(msg); 00473 dbus_bool_t bb = b; 00474 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BOOLEAN, &bb); 00475 return *this; 00476 } 00477 00478 00479 WvDBusMsg &WvDBusMsg::append(signed char c) 00480 { 00481 assert(msg); 00482 dbus_unichar_t cc = c; 00483 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc); 00484 return *this; 00485 } 00486 00487 00488 WvDBusMsg &WvDBusMsg::append(unsigned char c) 00489 { 00490 assert(msg); 00491 dbus_unichar_t cc = c; 00492 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_BYTE, &cc); 00493 return *this; 00494 } 00495 00496 00497 WvDBusMsg &WvDBusMsg::append(int16_t i) 00498 { 00499 assert(msg); 00500 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT16, &i); 00501 return *this; 00502 } 00503 00504 00505 WvDBusMsg &WvDBusMsg::append(uint16_t i) 00506 { 00507 assert(msg); 00508 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT16, &i); 00509 return *this; 00510 } 00511 00512 00513 WvDBusMsg &WvDBusMsg::append(int32_t i) 00514 { 00515 assert(msg); 00516 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT32, &i); 00517 return *this; 00518 } 00519 00520 00521 WvDBusMsg &WvDBusMsg::append(uint32_t i) 00522 { 00523 assert(msg); 00524 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT32, &i); 00525 return *this; 00526 } 00527 00528 00529 WvDBusMsg &WvDBusMsg::append(int64_t i) 00530 { 00531 assert(msg); 00532 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_INT64, &i); 00533 return *this; 00534 } 00535 00536 00537 WvDBusMsg &WvDBusMsg::append(uint64_t i) 00538 { 00539 assert(msg); 00540 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_UINT64, &i); 00541 return *this; 00542 } 00543 00544 00545 WvDBusMsg &WvDBusMsg::append(double d) 00546 { 00547 assert(msg); 00548 dbus_message_iter_append_basic(itlist.first(), DBUS_TYPE_DOUBLE, &d); 00549 return *this; 00550 } 00551 00552 00553 WvDBusMsg &WvDBusMsg::variant_start(WvStringParm element_type) 00554 { 00555 DBusMessageIter *parent = itlist.first(); 00556 DBusMessageIter *sub = new DBusMessageIter; 00557 dbus_message_iter_open_container(parent, 00558 DBUS_TYPE_VARIANT, element_type, sub); 00559 itlist.prepend(sub, true); 00560 return *this; 00561 } 00562 00563 00564 WvDBusMsg &WvDBusMsg::variant_end() 00565 { 00566 assert(itlist.count() >= 2); 00567 00568 WvList<DBusMessageIter>::Iter i(itlist); 00569 i.rewind(); i.next(); 00570 DBusMessageIter *sub = i.ptr(); 00571 i.next(); 00572 DBusMessageIter *parent = i.ptr(); 00573 00574 dbus_message_iter_close_container(parent, sub); 00575 itlist.unlink_first(); 00576 return *this; 00577 } 00578 00579 00580 WvDBusMsg &WvDBusMsg::struct_start(WvStringParm element_type) 00581 { 00582 DBusMessageIter *parent = itlist.first(); 00583 DBusMessageIter *sub = new DBusMessageIter; 00584 dbus_message_iter_open_container(parent, 00585 DBUS_TYPE_STRUCT, 0, sub); 00586 itlist.prepend(sub, true); 00587 return *this; 00588 } 00589 00590 00591 WvDBusMsg &WvDBusMsg::struct_end() 00592 { 00593 return array_end(); // same thing 00594 } 00595 00596 00597 WvDBusMsg &WvDBusMsg::array_start(WvStringParm element_type) 00598 { 00599 DBusMessageIter *parent = itlist.first(); 00600 DBusMessageIter *sub = new DBusMessageIter; 00601 dbus_message_iter_open_container(parent, 00602 DBUS_TYPE_ARRAY, element_type, sub); 00603 itlist.prepend(sub, true); 00604 return *this; 00605 } 00606 00607 00608 WvDBusMsg &WvDBusMsg::array_end() 00609 { 00610 return variant_end(); // same thing 00611 } 00612 00613 00614 WvDBusMsg &WvDBusMsg::varray_start(WvStringParm element_type) 00615 { 00616 variant_start(WvString("a%s", element_type)); 00617 return array_start(element_type); 00618 } 00619 00620 00621 WvDBusMsg &WvDBusMsg::varray_end() 00622 { 00623 assert(itlist.count() >= 3); 00624 array_end(); 00625 return variant_end(); 00626 } 00627 00628 00629 WvDBusMsg WvDBusMsg::reply() 00630 { 00631 return WvDBusReplyMsg(*this); 00632 } 00633 00634 00635 bool WvDBusMsg::iserror() const 00636 { 00637 return dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR; 00638 } 00639 00640 00641 void WvDBusMsg::send(WvDBusConn &conn) 00642 { 00643 conn.send(*this); 00644 } 00645 00646 00647 WvDBusReplyMsg::WvDBusReplyMsg(DBusMessage *_msg) 00648 : WvDBusMsg(dbus_message_new_method_return(_msg)) 00649 { 00650 dbus_message_unref(msg); 00651 } 00652 00653 00654 WvDBusSignal::WvDBusSignal(WvStringParm objectname, WvStringParm interface, 00655 WvStringParm name) 00656 : WvDBusMsg(dbus_message_new_signal(objectname, interface, name)) 00657 { 00658 dbus_message_unref(msg); 00659 } 00660 00661 00662 DBusMessage *WvDBusError::setup1(WvDBusMsg &in_reply_to, 00663 WvStringParm errname, WvStringParm message) 00664 { 00665 return dbus_message_new_error(in_reply_to, errname, message); 00666 } 00667 00668 void WvDBusError::setup2() 00669 { 00670 dbus_message_unref(msg); 00671 }