message.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *  D-Bus++ - C++ bindings for D-Bus
00004  *
00005  *  Copyright (C) 2005-2007  Paolo Durante <shackan@gmail.com>
00006  *
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Lesser General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2.1 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <dbus-c++/message.h>
00029 
00030 #include <dbus/dbus.h>
00031 #include <cstdlib>
00032 
00033 #include "internalerror.h"
00034 #include "message_p.h"
00035 
00036 using namespace DBus;
00037 
00038 /*
00039 */
00040 
00041 int MessageIter::type()
00042 {
00043   return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter);
00044 }
00045 
00046 bool MessageIter::at_end()
00047 {
00048   return type() == DBUS_TYPE_INVALID;
00049 }
00050 
00051 bool MessageIter::has_next()
00052 {
00053   return dbus_message_iter_has_next((DBusMessageIter *)&_iter);
00054 }
00055 
00056 MessageIter &MessageIter::operator ++()
00057 {
00058   dbus_message_iter_next((DBusMessageIter *)&_iter);
00059   return (*this);
00060 }
00061 
00062 MessageIter MessageIter::operator ++(int)
00063 {
00064   MessageIter copy(*this);
00065   ++(*this);
00066   return copy;
00067 }
00068 
00069 bool MessageIter::append_basic(int type_id, void *value)
00070 {
00071   return dbus_message_iter_append_basic((DBusMessageIter *)&_iter, type_id, value);
00072 }
00073 
00074 void MessageIter::get_basic(int type_id, void *ptr)
00075 {
00076   if (type() != type_id)
00077     throw ErrorInvalidArgs("type mismatch");
00078 
00079   dbus_message_iter_get_basic((DBusMessageIter *)_iter, ptr);
00080 }
00081 
00082 bool MessageIter::append_byte(unsigned char b)
00083 {
00084   return append_basic(DBUS_TYPE_BYTE, &b);
00085 }
00086 
00087 unsigned char MessageIter::get_byte()
00088 {
00089   unsigned char b;
00090   get_basic(DBUS_TYPE_BYTE, &b);
00091   return b;
00092 }
00093 
00094 bool MessageIter::append_bool(bool b)
00095 {
00096   dbus_bool_t db = b;
00097   return append_basic(DBUS_TYPE_BOOLEAN, &db);
00098 }
00099 
00100 bool MessageIter::get_bool()
00101 {
00102   dbus_bool_t db;
00103   get_basic(DBUS_TYPE_BOOLEAN, &db);
00104   return (bool)db;
00105 }
00106 
00107 bool MessageIter::append_int16(signed short i)
00108 {
00109   return append_basic(DBUS_TYPE_INT16, &i);
00110 }
00111 
00112 signed short MessageIter::get_int16()
00113 {
00114   signed short i;
00115   get_basic(DBUS_TYPE_INT16, &i);
00116   return i;
00117 }
00118 
00119 bool MessageIter::append_uint16(unsigned short u)
00120 {
00121   return append_basic(DBUS_TYPE_UINT16, &u);
00122 }
00123 
00124 unsigned short MessageIter::get_uint16()
00125 {
00126   unsigned short u;
00127   get_basic(DBUS_TYPE_UINT16, &u);
00128   return u;
00129 }
00130 
00131 bool MessageIter::append_int32(signed int i)
00132 {
00133   return append_basic(DBUS_TYPE_INT32, &i);
00134 }
00135 
00136 signed int MessageIter::get_int32()
00137 {
00138   signed int i;
00139   get_basic(DBUS_TYPE_INT32, &i);
00140   return i;
00141 }
00142 
00143 bool MessageIter::append_uint32(unsigned int u)
00144 {
00145   return append_basic(DBUS_TYPE_UINT32, &u);
00146 }
00147 
00148 unsigned int MessageIter::get_uint32()
00149 {
00150   unsigned int u;
00151   get_basic(DBUS_TYPE_UINT32, &u);
00152   return u;
00153 }
00154 
00155 signed long long MessageIter::get_int64()
00156 {
00157   signed long long i;
00158   get_basic(DBUS_TYPE_INT64, &i);
00159   return i;
00160 }
00161 
00162 bool MessageIter::append_int64(signed long long i)
00163 {
00164   return append_basic(DBUS_TYPE_INT64, &i);
00165 }
00166 
00167 unsigned long long MessageIter::get_uint64()
00168 {
00169   unsigned long long u;
00170   get_basic(DBUS_TYPE_UINT64, &u);
00171   return u;
00172 }
00173 
00174 bool MessageIter::append_uint64(unsigned long long u)
00175 {
00176   return append_basic(DBUS_TYPE_UINT64, &u);
00177 }
00178 
00179 double MessageIter::get_double()
00180 {
00181   double d;
00182   get_basic(DBUS_TYPE_DOUBLE, &d);
00183   return d;
00184 }
00185 
00186 bool MessageIter::append_double(double d)
00187 {
00188   return append_basic(DBUS_TYPE_DOUBLE, &d);
00189 }
00190 
00191 bool MessageIter::append_string(const char *chars)
00192 {
00193   return append_basic(DBUS_TYPE_STRING, &chars);
00194 }
00195 
00196 const char *MessageIter::get_string()
00197 {
00198   char *chars;
00199   get_basic(DBUS_TYPE_STRING, &chars);
00200   return chars;
00201 }
00202 
00203 bool MessageIter::append_path(const char *chars)
00204 {
00205   return append_basic(DBUS_TYPE_OBJECT_PATH, &chars);
00206 }
00207 
00208 const char *MessageIter::get_path()
00209 {
00210   char *chars;
00211   get_basic(DBUS_TYPE_OBJECT_PATH, &chars);
00212   return chars;
00213 }
00214 
00215 bool MessageIter::append_signature(const char *chars)
00216 {
00217   return append_basic(DBUS_TYPE_SIGNATURE, &chars);
00218 }
00219 
00220 const char *MessageIter::get_signature()
00221 {
00222   char *chars;
00223   get_basic(DBUS_TYPE_SIGNATURE, &chars);
00224   return chars;
00225 }
00226 
00227 MessageIter MessageIter::recurse()
00228 {
00229   MessageIter iter(msg());
00230   dbus_message_iter_recurse((DBusMessageIter *)&_iter, (DBusMessageIter *) & (iter._iter));
00231   return iter;
00232 }
00233 
00234 char *MessageIter::signature() const
00235 {
00236   return dbus_message_iter_get_signature((DBusMessageIter *)&_iter);
00237 }
00238 
00239 bool MessageIter::append_array(char type, const void *ptr, size_t length)
00240 {
00241   return dbus_message_iter_append_fixed_array((DBusMessageIter *)&_iter, type, &ptr, length);
00242 }
00243 
00244 int MessageIter::array_type()
00245 {
00246   return dbus_message_iter_get_element_type((DBusMessageIter *)&_iter);
00247 }
00248 
00249 int MessageIter::get_array(void *ptr)
00250 {
00251   int length;
00252   dbus_message_iter_get_fixed_array((DBusMessageIter *)&_iter, ptr, &length);
00253   return length;
00254 }
00255 
00256 bool MessageIter::is_array()
00257 {
00258   return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter) == DBUS_TYPE_ARRAY;
00259 }
00260 
00261 bool MessageIter::is_dict()
00262 {
00263   return is_array() && dbus_message_iter_get_element_type((DBusMessageIter *)_iter) == DBUS_TYPE_DICT_ENTRY;
00264 }
00265 
00266 MessageIter MessageIter::new_array(const char *sig)
00267 {
00268   MessageIter arr(msg());
00269   dbus_message_iter_open_container(
00270     (DBusMessageIter *)&_iter, DBUS_TYPE_ARRAY, sig, (DBusMessageIter *) & (arr._iter)
00271   );
00272   return arr;
00273 }
00274 
00275 MessageIter MessageIter::new_variant(const char *sig)
00276 {
00277   MessageIter var(msg());
00278   dbus_message_iter_open_container(
00279     (DBusMessageIter *)_iter, DBUS_TYPE_VARIANT, sig, (DBusMessageIter *) & (var._iter)
00280   );
00281   return var;
00282 }
00283 
00284 MessageIter MessageIter::new_struct()
00285 {
00286   MessageIter stu(msg());
00287   dbus_message_iter_open_container(
00288     (DBusMessageIter *)_iter, DBUS_TYPE_STRUCT, NULL, (DBusMessageIter *) & (stu._iter)
00289   );
00290   return stu;
00291 }
00292 
00293 MessageIter MessageIter::new_dict_entry()
00294 {
00295   MessageIter ent(msg());
00296   dbus_message_iter_open_container(
00297     (DBusMessageIter *)_iter, DBUS_TYPE_DICT_ENTRY, NULL, (DBusMessageIter *) & (ent._iter)
00298   );
00299   return ent;
00300 }
00301 
00302 void MessageIter::close_container(MessageIter &container)
00303 {
00304   dbus_message_iter_close_container((DBusMessageIter *)&_iter, (DBusMessageIter *) & (container._iter));
00305 }
00306 
00307 static bool is_basic_type(int typecode)
00308 {
00309   switch (typecode)
00310   {
00311   case 'y':
00312   case 'b':
00313   case 'n':
00314   case 'q':
00315   case 'i':
00316   case 'u':
00317   case 'x':
00318   case 't':
00319   case 'd':
00320   case 's':
00321   case 'o':
00322   case 'g':
00323     return true;
00324   default:
00325     return false;
00326   }
00327 }
00328 
00329 void MessageIter::copy_data(MessageIter &to)
00330 {
00331   for (MessageIter &from = *this; !from.at_end(); ++from)
00332   {
00333     if (is_basic_type(from.type()))
00334     {
00335       debug_log("copying basic type: %c", from.type());
00336 
00337       unsigned char value[8];
00338       from.get_basic(from.type(), &value);
00339       to.append_basic(from.type(), &value);
00340     }
00341     else
00342     {
00343       MessageIter from_container = from.recurse();
00344       char *sig = from_container.signature();
00345 
00346       debug_log("copying compound type: %c[%s]", from.type(), sig);
00347 
00348       MessageIter to_container(to.msg());
00349       dbus_message_iter_open_container
00350       (
00351         (DBusMessageIter *) & (to._iter),
00352         from.type(),
00353         from.type() == DBUS_TYPE_VARIANT ? NULL : sig,
00354         (DBusMessageIter *) & (to_container._iter)
00355       );
00356 
00357       from_container.copy_data(to_container);
00358       to.close_container(to_container);
00359       free(sig);
00360     }
00361   }
00362 }
00363 
00364 /*
00365 */
00366 
00367 Message::Message()
00368   : _pvt(new Private)
00369 {
00370 }
00371 
00372 Message::Message(Message::Private *p, bool incref)
00373   : _pvt(p)
00374 {
00375   if (_pvt->msg && incref) dbus_message_ref(_pvt->msg);
00376 }
00377 
00378 Message::Message(const Message &m)
00379   : _pvt(m._pvt)
00380 {
00381   dbus_message_ref(_pvt->msg);
00382 }
00383 
00384 Message::~Message()
00385 {
00386   dbus_message_unref(_pvt->msg);
00387 }
00388 
00389 Message &Message::operator = (const Message &m)
00390 {
00391   if (&m != this)
00392   {
00393     dbus_message_unref(_pvt->msg);
00394     _pvt = m._pvt;
00395     dbus_message_ref(_pvt->msg);
00396   }
00397   return *this;
00398 }
00399 
00400 Message Message::copy()
00401 {
00402   Private *pvt = new Private(dbus_message_copy(_pvt->msg));
00403   return Message(pvt);
00404 }
00405 
00406 bool Message::append(int first_type, ...)
00407 {
00408   va_list vl;
00409   va_start(vl, first_type);
00410 
00411   bool b = dbus_message_append_args_valist(_pvt->msg, first_type, vl);
00412 
00413   va_end(vl);
00414   return b;
00415 }
00416 
00417 void Message::terminate()
00418 {
00419   dbus_message_append_args(_pvt->msg, DBUS_TYPE_INVALID);
00420 }
00421 
00422 int Message::type() const
00423 {
00424   return dbus_message_get_type(_pvt->msg);
00425 }
00426 
00427 int Message::serial() const
00428 {
00429   return dbus_message_get_serial(_pvt->msg);
00430 }
00431 
00432 int Message::reply_serial() const
00433 {
00434   return dbus_message_get_reply_serial(_pvt->msg);
00435 }
00436 
00437 bool Message::reply_serial(int s)
00438 {
00439   return dbus_message_set_reply_serial(_pvt->msg, s);
00440 }
00441 
00442 const char *Message::sender() const
00443 {
00444   return dbus_message_get_sender(_pvt->msg);
00445 }
00446 
00447 bool Message::sender(const char *s)
00448 {
00449   return dbus_message_set_sender(_pvt->msg, s);
00450 }
00451 
00452 const char *Message::destination() const
00453 {
00454   return dbus_message_get_destination(_pvt->msg);
00455 }
00456 
00457 bool Message::destination(const char *s)
00458 {
00459   return dbus_message_set_destination(_pvt->msg, s);
00460 }
00461 
00462 bool Message::is_error() const
00463 {
00464   return type() == DBUS_MESSAGE_TYPE_ERROR;
00465 }
00466 
00467 bool Message::is_signal(const char *interface, const char *member) const
00468 {
00469   return dbus_message_is_signal(_pvt->msg, interface, member);
00470 }
00471 
00472 MessageIter Message::writer()
00473 {
00474   MessageIter iter(*this);
00475   dbus_message_iter_init_append(_pvt->msg, (DBusMessageIter *) & (iter._iter));
00476   return iter;
00477 }
00478 
00479 MessageIter Message::reader() const
00480 {
00481   MessageIter iter(const_cast<Message &>(*this));
00482   dbus_message_iter_init(_pvt->msg, (DBusMessageIter *) & (iter._iter));
00483   return iter;
00484 }
00485 
00486 /*
00487 */
00488 
00489 ErrorMessage::ErrorMessage()
00490 {
00491   _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
00492 }
00493 
00494 ErrorMessage::ErrorMessage(const Message &to_reply, const char *name, const char *message)
00495 {
00496   _pvt->msg = dbus_message_new_error(to_reply._pvt->msg, name, message);
00497 }
00498 
00499 bool ErrorMessage::operator == (const ErrorMessage &m) const
00500 {
00501   return dbus_message_is_error(_pvt->msg, m.name());
00502 }
00503 
00504 const char *ErrorMessage::name() const
00505 {
00506   return dbus_message_get_error_name(_pvt->msg);
00507 }
00508 
00509 bool ErrorMessage::name(const char *n)
00510 {
00511   return dbus_message_set_error_name(_pvt->msg, n);
00512 }
00513 
00514 /*
00515 */
00516 
00517 SignalMessage::SignalMessage(const char *name)
00518 {
00519   _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
00520   member(name);
00521 }
00522 
00523 SignalMessage::SignalMessage(const char *path, const char *interface, const char *name)
00524 {
00525   _pvt->msg = dbus_message_new_signal(path, interface, name);
00526 }
00527 
00528 bool SignalMessage::operator == (const SignalMessage &m) const
00529 {
00530   return dbus_message_is_signal(_pvt->msg, m.interface(), m.member());
00531 }
00532 
00533 const char *SignalMessage::interface() const
00534 {
00535   return dbus_message_get_interface(_pvt->msg);
00536 }
00537 
00538 bool SignalMessage::interface(const char *i)
00539 {
00540   return dbus_message_set_interface(_pvt->msg, i);
00541 }
00542 
00543 const char *SignalMessage::member() const
00544 {
00545   return dbus_message_get_member(_pvt->msg);
00546 }
00547 
00548 bool SignalMessage::member(const char *m)
00549 {
00550   return dbus_message_set_member(_pvt->msg, m);
00551 }
00552 
00553 const char *SignalMessage::path() const
00554 {
00555   return dbus_message_get_path(_pvt->msg);
00556 }
00557 
00558 char **SignalMessage::path_split() const
00559 {
00560   char **p;
00561   dbus_message_get_path_decomposed(_pvt->msg, &p);  //todo: return as a std::vector ?
00562   return p;
00563 }
00564 
00565 bool SignalMessage::path(const char *p)
00566 {
00567   return dbus_message_set_path(_pvt->msg, p);
00568 }
00569 
00570 /*
00571 */
00572 
00573 CallMessage::CallMessage()
00574 {
00575   _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
00576 }
00577 
00578 CallMessage::CallMessage(const char *dest, const char *path, const char *iface, const char *method)
00579 {
00580   _pvt->msg = dbus_message_new_method_call(dest, path, iface, method);
00581 }
00582 
00583 bool CallMessage::operator == (const CallMessage &m) const
00584 {
00585   return dbus_message_is_method_call(_pvt->msg, m.interface(), m.member());
00586 }
00587 
00588 const char *CallMessage::interface() const
00589 {
00590   return dbus_message_get_interface(_pvt->msg);
00591 }
00592 
00593 bool CallMessage::interface(const char *i)
00594 {
00595   return dbus_message_set_interface(_pvt->msg, i);
00596 }
00597 
00598 const char *CallMessage::member() const
00599 {
00600   return dbus_message_get_member(_pvt->msg);
00601 }
00602 
00603 bool CallMessage::member(const char *m)
00604 {
00605   return dbus_message_set_member(_pvt->msg, m);
00606 }
00607 
00608 const char *CallMessage::path() const
00609 {
00610   return dbus_message_get_path(_pvt->msg);
00611 }
00612 
00613 char **CallMessage::path_split() const
00614 {
00615   char **p;
00616   dbus_message_get_path_decomposed(_pvt->msg, &p);
00617   return p;
00618 }
00619 
00620 bool CallMessage::path(const char *p)
00621 {
00622   return dbus_message_set_path(_pvt->msg, p);
00623 }
00624 
00625 const char *CallMessage::signature() const
00626 {
00627   return dbus_message_get_signature(_pvt->msg);
00628 }
00629 
00630 /*
00631 */
00632 
00633 ReturnMessage::ReturnMessage(const CallMessage &callee)
00634 {
00635   _pvt = new Private(dbus_message_new_method_return(callee._pvt->msg));
00636 }
00637 
00638 const char *ReturnMessage::signature() const
00639 {
00640   return dbus_message_get_signature(_pvt->msg);
00641 }
00642