/* * * D-Bus++ - C++ bindings for D-Bus * * Copyright (C) 2005-2007 Paolo Durante * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "internalerror.h" #include "message_p.h" using namespace DBus; /* */ int MessageIter::type() { return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter); } bool MessageIter::at_end() { return type() == DBUS_TYPE_INVALID; } bool MessageIter::has_next() { return dbus_message_iter_has_next((DBusMessageIter *)&_iter); } MessageIter &MessageIter::operator ++() { dbus_message_iter_next((DBusMessageIter *)&_iter); return (*this); } MessageIter MessageIter::operator ++(int) { MessageIter copy(*this); ++(*this); return copy; } bool MessageIter::append_basic(int type_id, void *value) { return dbus_message_iter_append_basic((DBusMessageIter *)&_iter, type_id, value); } void MessageIter::get_basic(int type_id, void *ptr) { if (type() != type_id) throw ErrorInvalidArgs("type mismatch"); dbus_message_iter_get_basic((DBusMessageIter *)_iter, ptr); } bool MessageIter::append_byte(unsigned char b) { return append_basic(DBUS_TYPE_BYTE, &b); } unsigned char MessageIter::get_byte() { unsigned char b; get_basic(DBUS_TYPE_BYTE, &b); return b; } bool MessageIter::append_bool(bool b) { dbus_bool_t db = b; return append_basic(DBUS_TYPE_BOOLEAN, &db); } bool MessageIter::get_bool() { dbus_bool_t db; get_basic(DBUS_TYPE_BOOLEAN, &db); return (bool)db; } bool MessageIter::append_int16(signed short i) { return append_basic(DBUS_TYPE_INT16, &i); } signed short MessageIter::get_int16() { signed short i; get_basic(DBUS_TYPE_INT16, &i); return i; } bool MessageIter::append_uint16(unsigned short u) { return append_basic(DBUS_TYPE_UINT16, &u); } unsigned short MessageIter::get_uint16() { unsigned short u; get_basic(DBUS_TYPE_UINT16, &u); return u; } bool MessageIter::append_int32(signed int i) { return append_basic(DBUS_TYPE_INT32, &i); } signed int MessageIter::get_int32() { signed int i; get_basic(DBUS_TYPE_INT32, &i); return i; } bool MessageIter::append_uint32(unsigned int u) { return append_basic(DBUS_TYPE_UINT32, &u); } unsigned int MessageIter::get_uint32() { unsigned int u; get_basic(DBUS_TYPE_UINT32, &u); return u; } signed long long MessageIter::get_int64() { signed long long i; get_basic(DBUS_TYPE_INT64, &i); return i; } bool MessageIter::append_int64(signed long long i) { return append_basic(DBUS_TYPE_INT64, &i); } unsigned long long MessageIter::get_uint64() { unsigned long long u; get_basic(DBUS_TYPE_UINT64, &u); return u; } bool MessageIter::append_uint64(unsigned long long u) { return append_basic(DBUS_TYPE_UINT64, &u); } double MessageIter::get_double() { double d; get_basic(DBUS_TYPE_DOUBLE, &d); return d; } bool MessageIter::append_double(double d) { return append_basic(DBUS_TYPE_DOUBLE, &d); } bool MessageIter::append_string(const char *chars) { return append_basic(DBUS_TYPE_STRING, &chars); } const char *MessageIter::get_string() { char *chars; get_basic(DBUS_TYPE_STRING, &chars); return chars; } bool MessageIter::append_path(const char *chars) { return append_basic(DBUS_TYPE_OBJECT_PATH, &chars); } const char *MessageIter::get_path() { char *chars; get_basic(DBUS_TYPE_OBJECT_PATH, &chars); return chars; } bool MessageIter::append_signature(const char *chars) { return append_basic(DBUS_TYPE_SIGNATURE, &chars); } const char *MessageIter::get_signature() { char *chars; get_basic(DBUS_TYPE_SIGNATURE, &chars); return chars; } MessageIter MessageIter::recurse() { MessageIter iter(msg()); dbus_message_iter_recurse((DBusMessageIter *)&_iter, (DBusMessageIter *) & (iter._iter)); return iter; } char *MessageIter::signature() const { return dbus_message_iter_get_signature((DBusMessageIter *)&_iter); } bool MessageIter::append_array(char type, const void *ptr, size_t length) { return dbus_message_iter_append_fixed_array((DBusMessageIter *)&_iter, type, &ptr, length); } int MessageIter::array_type() { return dbus_message_iter_get_element_type((DBusMessageIter *)&_iter); } int MessageIter::get_array(void *ptr) { int length; dbus_message_iter_get_fixed_array((DBusMessageIter *)&_iter, ptr, &length); return length; } bool MessageIter::is_array() { return dbus_message_iter_get_arg_type((DBusMessageIter *)&_iter) == DBUS_TYPE_ARRAY; } bool MessageIter::is_dict() { return is_array() && dbus_message_iter_get_element_type((DBusMessageIter *)_iter) == DBUS_TYPE_DICT_ENTRY; } MessageIter MessageIter::new_array(const char *sig) { MessageIter arr(msg()); dbus_message_iter_open_container( (DBusMessageIter *)&_iter, DBUS_TYPE_ARRAY, sig, (DBusMessageIter *) & (arr._iter) ); return arr; } MessageIter MessageIter::new_variant(const char *sig) { MessageIter var(msg()); dbus_message_iter_open_container( (DBusMessageIter *)_iter, DBUS_TYPE_VARIANT, sig, (DBusMessageIter *) & (var._iter) ); return var; } MessageIter MessageIter::new_struct() { MessageIter stu(msg()); dbus_message_iter_open_container( (DBusMessageIter *)_iter, DBUS_TYPE_STRUCT, NULL, (DBusMessageIter *) & (stu._iter) ); return stu; } MessageIter MessageIter::new_dict_entry() { MessageIter ent(msg()); dbus_message_iter_open_container( (DBusMessageIter *)_iter, DBUS_TYPE_DICT_ENTRY, NULL, (DBusMessageIter *) & (ent._iter) ); return ent; } void MessageIter::close_container(MessageIter &container) { dbus_message_iter_close_container((DBusMessageIter *)&_iter, (DBusMessageIter *) & (container._iter)); } static bool is_basic_type(int typecode) { switch (typecode) { case 'y': case 'b': case 'n': case 'q': case 'i': case 'u': case 'x': case 't': case 'd': case 's': case 'o': case 'g': return true; default: return false; } } void MessageIter::copy_data(MessageIter &to) { for (MessageIter &from = *this; !from.at_end(); ++from) { if (is_basic_type(from.type())) { debug_log("copying basic type: %c", from.type()); unsigned char value[8]; from.get_basic(from.type(), &value); to.append_basic(from.type(), &value); } else { MessageIter from_container = from.recurse(); char *sig = from_container.signature(); debug_log("copying compound type: %c[%s]", from.type(), sig); MessageIter to_container(to.msg()); dbus_bool_t ret = dbus_message_iter_open_container ( (DBusMessageIter *) & (to._iter), from.type(), (from.type() == DBUS_TYPE_VARIANT || from.type() == DBUS_TYPE_ARRAY) ? sig : NULL, (DBusMessageIter *) & (to_container._iter) ); if (!ret) { throw ErrorNoMemory("Unable to append container"); } from_container.copy_data(to_container); to.close_container(to_container); free(sig); } } } /* */ Message::Message() : _pvt(new Private) { } Message::Message(Message::Private *p, bool incref) : _pvt(p) { if (_pvt->msg && incref) dbus_message_ref(_pvt->msg); } Message::Message(const Message &m) : _pvt(m._pvt) { dbus_message_ref(_pvt->msg); } Message::~Message() { dbus_message_unref(_pvt->msg); } Message &Message::operator = (const Message &m) { if (&m != this) { dbus_message_unref(_pvt->msg); _pvt = m._pvt; dbus_message_ref(_pvt->msg); } return *this; } Message Message::copy() { Private *pvt = new Private(dbus_message_copy(_pvt->msg)); return Message(pvt); } bool Message::append(int first_type, ...) { va_list vl; va_start(vl, first_type); bool b = dbus_message_append_args_valist(_pvt->msg, first_type, vl); va_end(vl); return b; } void Message::terminate() { dbus_message_append_args(_pvt->msg, DBUS_TYPE_INVALID); } int Message::type() const { return dbus_message_get_type(_pvt->msg); } int Message::serial() const { return dbus_message_get_serial(_pvt->msg); } int Message::reply_serial() const { return dbus_message_get_reply_serial(_pvt->msg); } bool Message::reply_serial(int s) { return dbus_message_set_reply_serial(_pvt->msg, s); } const char *Message::sender() const { return dbus_message_get_sender(_pvt->msg); } bool Message::sender(const char *s) { return dbus_message_set_sender(_pvt->msg, s); } const char *Message::destination() const { return dbus_message_get_destination(_pvt->msg); } bool Message::destination(const char *s) { return dbus_message_set_destination(_pvt->msg, s); } bool Message::is_error() const { return type() == DBUS_MESSAGE_TYPE_ERROR; } bool Message::is_signal(const char *interface, const char *member) const { return dbus_message_is_signal(_pvt->msg, interface, member); } MessageIter Message::writer() { MessageIter iter(*this); dbus_message_iter_init_append(_pvt->msg, (DBusMessageIter *) & (iter._iter)); return iter; } MessageIter Message::reader() const { MessageIter iter(const_cast(*this)); dbus_message_iter_init(_pvt->msg, (DBusMessageIter *) & (iter._iter)); return iter; } /* */ ErrorMessage::ErrorMessage() { _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); } ErrorMessage::ErrorMessage(const Message &to_reply, const char *name, const char *message) { _pvt->msg = dbus_message_new_error(to_reply._pvt->msg, name, message); } bool ErrorMessage::operator == (const ErrorMessage &m) const { return dbus_message_is_error(_pvt->msg, m.name()); } const char *ErrorMessage::name() const { return dbus_message_get_error_name(_pvt->msg); } bool ErrorMessage::name(const char *n) { return dbus_message_set_error_name(_pvt->msg, n); } /* */ SignalMessage::SignalMessage(const char *name) { _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); member(name); } SignalMessage::SignalMessage(const char *path, const char *interface, const char *name) { _pvt->msg = dbus_message_new_signal(path, interface, name); } bool SignalMessage::operator == (const SignalMessage &m) const { return dbus_message_is_signal(_pvt->msg, m.interface(), m.member()); } const char *SignalMessage::interface() const { return dbus_message_get_interface(_pvt->msg); } bool SignalMessage::interface(const char *i) { return dbus_message_set_interface(_pvt->msg, i); } const char *SignalMessage::member() const { return dbus_message_get_member(_pvt->msg); } bool SignalMessage::member(const char *m) { return dbus_message_set_member(_pvt->msg, m); } const char *SignalMessage::path() const { return dbus_message_get_path(_pvt->msg); } char **SignalMessage::path_split() const { char **p; dbus_message_get_path_decomposed(_pvt->msg, &p); //todo: return as a std::vector ? return p; } bool SignalMessage::path(const char *p) { return dbus_message_set_path(_pvt->msg, p); } /* */ CallMessage::CallMessage() { _pvt->msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); } CallMessage::CallMessage(const char *dest, const char *path, const char *iface, const char *method) { _pvt->msg = dbus_message_new_method_call(dest, path, iface, method); } bool CallMessage::operator == (const CallMessage &m) const { return dbus_message_is_method_call(_pvt->msg, m.interface(), m.member()); } const char *CallMessage::interface() const { return dbus_message_get_interface(_pvt->msg); } bool CallMessage::interface(const char *i) { return dbus_message_set_interface(_pvt->msg, i); } const char *CallMessage::member() const { return dbus_message_get_member(_pvt->msg); } bool CallMessage::member(const char *m) { return dbus_message_set_member(_pvt->msg, m); } const char *CallMessage::path() const { return dbus_message_get_path(_pvt->msg); } char **CallMessage::path_split() const { char **p; dbus_message_get_path_decomposed(_pvt->msg, &p); return p; } bool CallMessage::path(const char *p) { return dbus_message_set_path(_pvt->msg, p); } const char *CallMessage::signature() const { return dbus_message_get_signature(_pvt->msg); } /* */ ReturnMessage::ReturnMessage(const CallMessage &callee) { _pvt = new Private(dbus_message_new_method_return(callee._pvt->msg)); } const char *ReturnMessage::signature() const { return dbus_message_get_signature(_pvt->msg); }