00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qdbusmessage.h"
00025
00026 #include <qdebug.h>
00027 #include <qstringlist.h>
00028
00029 #include <dbus/dbus.h>
00030
00031 #include "qdbusargument_p.h"
00032 #include "qdbuserror.h"
00033 #include "qdbusmessage_p.h"
00034 #include "qdbusmetatype.h"
00035
00036 static inline const char *data(const QByteArray &arr)
00037 {
00038 return arr.isEmpty() ? 0 : arr.constData();
00039 }
00040
00041 QDBusMessagePrivate::QDBusMessagePrivate()
00042 : msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
00043 timeout(-1), ref(1), delayedReply(false), localMessage(false)
00044 {
00045 }
00046
00047 QDBusMessagePrivate::~QDBusMessagePrivate()
00048 {
00049 if (msg)
00050 dbus_message_unref(msg);
00051 if (reply)
00052 dbus_message_unref(reply);
00053 }
00054
00059 QDBusMessage QDBusMessagePrivate::fromError(const QDBusError &error)
00060 {
00061 QDBusMessage message;
00062 message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
00063 message.d_ptr->name = error.name();
00064 message << error.message();
00065 return message;
00066 }
00067
00073 DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message)
00074 {
00075 DBusMessage *msg = 0;
00076 const QDBusMessagePrivate *d_ptr = message.d_ptr;
00077
00078 switch (d_ptr->type) {
00079 case DBUS_MESSAGE_TYPE_INVALID:
00080
00081 break;
00082 case DBUS_MESSAGE_TYPE_METHOD_CALL:
00083 msg = dbus_message_new_method_call(data(d_ptr->service.toUtf8()), data(d_ptr->path.toUtf8()),
00084 data(d_ptr->interface.toUtf8()), data(d_ptr->name.toUtf8()));
00085 break;
00086 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00087 if (d_ptr->reply)
00088 msg = dbus_message_new_method_return(d_ptr->reply);
00089 else
00090 qDebug() << "QDBusMessagePrivate::toDBusMessage" << "reply is invalid";
00091 break;
00092 case DBUS_MESSAGE_TYPE_ERROR:
00093 msg = dbus_message_new_error(d_ptr->reply, data(d_ptr->name.toUtf8()), data(d_ptr->message.toUtf8()));
00094 break;
00095 case DBUS_MESSAGE_TYPE_SIGNAL:
00096 msg = dbus_message_new_signal(data(d_ptr->path.toUtf8()), data(d_ptr->interface.toUtf8()),
00097 data(d_ptr->name.toUtf8()));
00098 break;
00099 default:
00100 Q_ASSERT(false);
00101 break;
00102 }
00103 #if 0
00104 DBusError err;
00105 dbus_error_init(&err);
00106 if (dbus_error_is_set(&err)) {
00107 QDBusError qe(&err);
00108 qDebug() << "QDBusMessagePrivate::toDBusMessage" << qe;
00109 }
00110 #endif
00111 if (!msg)
00112 return 0;
00113
00114 QDBusMarshaller marshaller;
00115 QVariantList::ConstIterator it = d_ptr->arguments.constBegin();
00116 QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
00117 dbus_message_iter_init_append(msg, &marshaller.iterator);
00118 for ( ; it != cend; ++it)
00119 marshaller.appendVariantInternal(*it);
00120
00121
00122 if (marshaller.ok)
00123 return msg;
00124
00125
00126 dbus_message_unref(msg);
00127 Q_ASSERT(false);
00128 return 0;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00156 QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg)
00157 {
00158 QDBusMessage message;
00159 if (!dmsg)
00160 return message;
00161
00162 message.d_ptr->type = dbus_message_get_type(dmsg);
00163 message.d_ptr->path = QString::fromUtf8(dbus_message_get_path(dmsg));
00164 message.d_ptr->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
00165 message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
00166 QString::fromUtf8(dbus_message_get_error_name(dmsg)) :
00167 QString::fromUtf8(dbus_message_get_member(dmsg));
00168 message.d_ptr->service = QString::fromUtf8(dbus_message_get_sender(dmsg));
00169 message.d_ptr->signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
00170 message.d_ptr->msg = dbus_message_ref(dmsg);
00171
00172 QDBusDemarshaller demarshaller;
00173 demarshaller.message = dbus_message_ref(dmsg);
00174 if (dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
00175 while (!demarshaller.atEnd())
00176 message << demarshaller.toVariantInternal();
00177 return message;
00178 }
00179
00180 QDBusMessage QDBusMessagePrivate::updateSignature(const QDBusMessage &message, DBusMessage *dmsg)
00181 {
00182 QDBusMessage messageWithSignature = message;
00183 QString signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
00184 messageWithSignature.d_ptr->signature = signature;
00185 return messageWithSignature;
00186 }
00187
00188 void QDBusMessagePrivate::setLocal(const QDBusMessage *message, bool local)
00189 {
00190 Q_ASSERT(message);
00191 message->d_ptr->localMessage = local;
00192 }
00193
00194 bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
00195 {
00196 return message.d_ptr->localMessage;
00197 }
00198
00199 void QDBusMessagePrivate::setArguments(const QDBusMessage *message, const QList<QVariant> &arguments)
00200 {
00201 Q_ASSERT(message);
00202 message->d_ptr->arguments = arguments;
00203 }
00204
00205 void QDBusMessagePrivate::setType(const QDBusMessage *message, QDBusMessage::MessageType type)
00206 {
00207 Q_ASSERT(message);
00208 message->d_ptr->type = type;
00209 }
00210
00256 QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
00257 const QString &name)
00258 {
00259 QDBusMessage message;
00260 message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
00261 message.d_ptr->path = path;
00262 message.d_ptr->interface = interface;
00263 message.d_ptr->name = name;
00264
00265 return message;
00266 }
00267
00287 QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
00288 const QString &interface, const QString &method)
00289 {
00290 QDBusMessage message;
00291 message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
00292 message.d_ptr->service = service;
00293 message.d_ptr->path = path;
00294 message.d_ptr->interface = interface;
00295 message.d_ptr->name = method;
00296
00297 return message;
00298 }
00299
00304 QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
00305 {
00306 QDBusMessage error;
00307 error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
00308 error.d_ptr->name = name;
00309 error.d_ptr->message = msg;
00310
00311 return error;
00312 }
00313
00327 QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
00328 {
00329 QDBusMessage reply;
00330 reply.setArguments(arguments);
00331 reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
00332 if (d_ptr->msg)
00333 reply.d_ptr->reply = dbus_message_ref(d_ptr->msg);
00334 else
00335 d_ptr->localMessage = true;
00336 Q_ASSERT(d_ptr->msg || d_ptr->localMessage);
00337
00338
00339 return reply;
00340 }
00341
00346 QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
00347 {
00348 QDBusMessage reply = QDBusMessage::createError(name, msg);
00349 if (d_ptr->msg)
00350 reply.d_ptr->reply = dbus_message_ref(d_ptr->msg);
00351 else
00352 d_ptr->localMessage = true;
00353 Q_ASSERT(d_ptr->msg || d_ptr->localMessage);
00354
00355 return reply;
00356 }
00357
00377 QDBusMessage::QDBusMessage()
00378 {
00379 d_ptr = new QDBusMessagePrivate;
00380 }
00381
00389 QDBusMessage::QDBusMessage(const QDBusMessage &other)
00390 {
00391 d_ptr = other.d_ptr;
00392 d_ptr->ref.ref();
00393 }
00394
00398 QDBusMessage::~QDBusMessage()
00399 {
00400 if (!d_ptr->ref.deref())
00401 delete d_ptr;
00402 }
00403
00411 QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
00412 {
00413 qAtomicAssign(d_ptr, other.d_ptr);
00414 return *this;
00415 }
00416
00420 QString QDBusMessage::service() const
00421 {
00422 return d_ptr->service;
00423 }
00424
00429 QString QDBusMessage::path() const
00430 {
00431 return d_ptr->path;
00432 }
00433
00438 QString QDBusMessage::interface() const
00439 {
00440 return d_ptr->interface;
00441 }
00442
00446 QString QDBusMessage::member() const
00447 {
00448 if (d_ptr->type != ErrorMessage)
00449 return d_ptr->name;
00450 return QString();
00451 }
00452
00456 QString QDBusMessage::errorName() const
00457 {
00458 if (d_ptr->type == ErrorMessage)
00459 return d_ptr->name;
00460 return QString();
00461 }
00462
00467 QString QDBusMessage::signature() const
00468 {
00469 return d_ptr->signature;
00470 }
00471
00478 bool QDBusMessage::isReplyRequired() const
00479 {
00480 if (!d_ptr->msg)
00481 return false;
00482 return dbus_message_get_no_reply(d_ptr->msg);
00483 }
00484
00499 void QDBusMessage::setDelayedReply(bool enable) const
00500 {
00501 d_ptr->delayedReply = enable;
00502 }
00503
00509 bool QDBusMessage::isDelayedReply() const
00510 {
00511 return d_ptr->delayedReply;
00512 }
00513
00520 void QDBusMessage::setArguments(const QList<QVariant> &arguments)
00521 {
00522 d_ptr->arguments = arguments;
00523 }
00524
00529 QList<QVariant> QDBusMessage::arguments() const
00530 {
00531 return d_ptr->arguments;
00532 }
00533
00539 QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
00540 {
00541 d_ptr->arguments.append(arg);
00542 return *this;
00543 }
00544
00548 QDBusMessage::MessageType QDBusMessage::type() const
00549 {
00550 switch (d_ptr->type) {
00551 case DBUS_MESSAGE_TYPE_METHOD_CALL:
00552 return MethodCallMessage;
00553 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00554 return ReplyMessage;
00555 case DBUS_MESSAGE_TYPE_ERROR:
00556 return ErrorMessage;
00557 case DBUS_MESSAGE_TYPE_SIGNAL:
00558 return SignalMessage;
00559 default:
00560 break;
00561 }
00562 return InvalidMessage;
00563 }
00564
00575 #ifndef QT_NO_DEBUG_STREAM
00576 QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
00577 {
00578 switch (t)
00579 {
00580 case QDBusMessage::MethodCallMessage:
00581 return dbg << "MethodCall";
00582 case QDBusMessage::ReplyMessage:
00583 return dbg << "MethodReturn";
00584 case QDBusMessage::SignalMessage:
00585 return dbg << "Signal";
00586 case QDBusMessage::ErrorMessage:
00587 return dbg << "Error";
00588 default:
00589 return dbg << "Invalid";
00590 }
00591 }
00592
00593 static void debugVariantList(QDebug dbg, const QVariantList &list);
00594 static void debugVariantMap(QDebug dbg, const QVariantMap &map);
00595
00596 static void debugVariant(QDebug dbg, const QVariant &v)
00597 {
00598 if (v.userType() == qMetaTypeId<QDBusArgument>()) {
00599 dbg.nospace() << "argument of type "
00600 << qvariant_cast<QDBusArgument>(v).currentSignature();
00601 return;
00602 }
00603 dbg.nospace() << v.typeName() << "(";
00604 switch (v.userType())
00605 {
00606 case QVariant::Bool:
00607 dbg.nospace() << v.toBool();
00608 break;
00609 case QMetaType::UChar:
00610 dbg.nospace() << qvariant_cast<uchar>(v);
00611 break;
00612 case QMetaType::Short:
00613 dbg.nospace() << qvariant_cast<short>(v);
00614 break;
00615 case QMetaType::UShort:
00616 dbg.nospace() << qvariant_cast<ushort>(v);
00617 break;
00618 case QVariant::Int:
00619 dbg.nospace() << v.toInt();
00620 break;
00621 case QVariant::UInt:
00622 dbg.nospace() << v.toUInt();
00623 break;
00624 case QVariant::LongLong:
00625 dbg.nospace() << v.toLongLong();
00626 break;
00627 case QVariant::ULongLong:
00628 dbg.nospace() << v.toULongLong();
00629 break;
00630 case QVariant::Double:
00631 dbg.nospace() << v.toDouble();
00632 break;
00633 case QVariant::String:
00634 dbg.nospace() << v.toString();
00635 break;
00636 case QVariant::ByteArray:
00637 dbg.nospace() << v.toByteArray();
00638 break;
00639 case QVariant::StringList:
00640 dbg.nospace() << v.toStringList();
00641 break;
00642 case QVariant::List:
00643 debugVariantList(dbg, v.toList());
00644 break;
00645 case QVariant::Map:
00646 debugVariantMap(dbg, v.toMap());
00647 break;
00648
00649 default: {
00650 int id = v.userType();
00651 if (id == qMetaTypeId<QDBusVariant>())
00652 debugVariant(dbg, qvariant_cast<QDBusVariant>(v).variant());
00653 else if (id == qMetaTypeId<QDBusObjectPath>())
00654 dbg.nospace() << qvariant_cast<QDBusObjectPath>(v).path();
00655 else if (id == qMetaTypeId<QDBusSignature>())
00656 dbg.nospace() << qvariant_cast<QDBusSignature>(v).signature();
00657 else
00658 dbg.nospace() << "unknown";
00659 }
00660 }
00661 dbg.nospace() << ")";
00662 }
00663
00664 static void debugVariantList(QDebug dbg, const QVariantList &list)
00665 {
00666 bool first = true;
00667 QVariantList::ConstIterator it = list.constBegin();
00668 QVariantList::ConstIterator end = list.constEnd();
00669 for ( ; it != end; ++it) {
00670 if (!first)
00671 dbg.nospace() << ", ";
00672 debugVariant(dbg, *it);
00673 first = false;
00674 }
00675 }
00676
00677 static void debugVariantMap(QDebug dbg, const QVariantMap &map)
00678 {
00679 QVariantMap::ConstIterator it = map.constBegin();
00680 QVariantMap::ConstIterator end = map.constEnd();
00681 for ( ; it != end; ++it) {
00682 dbg << "(" << it.key() << ", ";
00683 debugVariant(dbg, it.value());
00684 dbg.nospace() << ") ";
00685 }
00686 }
00687
00688 QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
00689 {
00690 dbg.nospace() << "QDBusMessage(type=" << msg.type()
00691 << ", service=" << msg.service()
00692 << ", path=" << msg.path()
00693 << ", interface=" << msg.interface()
00694 << ", member=" << msg.member()
00695 << ", signature=" << msg.signature()
00696 << ", contents=(";
00697 debugVariantList(dbg, msg.arguments());
00698 dbg.nospace() << ") )";
00699 return dbg.space();
00700 }
00701 #endif
00702