1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtDBus module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include "qdbusmessage.h"
43
#include "qdbusmessage_p.h"
46
#include <qstringlist.h>
48
#include "qdbus_symbols_p.h"
50
#include "qdbusargument_p.h"
51
#include "qdbuserror.h"
52
#include "qdbusmetatype.h"
53
#include "qdbusconnection_p.h"
54
#include "qdbusutil_p.h"
60
static inline const char *data(const QByteArray &arr)
62
return arr.isEmpty() ? 0 : arr.constData();
65
QDBusMessagePrivate::QDBusMessagePrivate()
66
: msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
67
timeout(-1), localReply(0), ref(1), delayedReply(false), localMessage(false),
68
parametersValidated(false), autoStartService(true)
72
QDBusMessagePrivate::~QDBusMessagePrivate()
75
q_dbus_message_unref(msg);
77
q_dbus_message_unref(reply);
83
Returns the human-readable message associated with the error that was received.
85
QString QDBusMessage::errorMessage() const
87
if (d_ptr->type == ErrorMessage) {
88
if (!d_ptr->message.isEmpty())
89
return d_ptr->message;
90
if (!d_ptr->arguments.isEmpty())
91
return d_ptr->arguments.at(0).toString();
98
Constructs a DBusMessage object from \a message. The returned value must be de-referenced
99
with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
101
The \a error object is set to indicate the error if anything went wrong with the
102
marshalling. Usually, this error message will be placed in the reply, as if the call failed.
103
The \a error pointer must not be null.
105
DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
108
if (!qdbus_loadLibDBus()) {
109
*error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library"));
113
DBusMessage *msg = 0;
114
const QDBusMessagePrivate *d_ptr = message.d_ptr;
116
switch (d_ptr->type) {
117
case DBUS_MESSAGE_TYPE_INVALID:
118
//qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid";
120
case DBUS_MESSAGE_TYPE_METHOD_CALL:
121
// only service and interface can be empty -> path and name must not be empty
122
if (!d_ptr->parametersValidated) {
123
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
125
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
127
if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
129
if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
133
msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(),
134
data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8());
135
q_dbus_message_set_auto_start( msg, d_ptr->autoStartService );
137
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
138
msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
139
if (!d_ptr->localMessage) {
140
q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
141
q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
144
case DBUS_MESSAGE_TYPE_ERROR:
145
// error name can't be empty
146
if (!d_ptr->parametersValidated
147
&& !QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error))
150
msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
151
q_dbus_message_set_error_name(msg, d_ptr->name.toUtf8());
152
if (!d_ptr->localMessage) {
153
q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
154
q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
157
case DBUS_MESSAGE_TYPE_SIGNAL:
158
// nothing can be empty here
159
if (!d_ptr->parametersValidated) {
160
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
162
if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
164
if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
168
msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(),
169
d_ptr->name.toUtf8());
176
// if we got here, the parameters validated
177
// and since the message parameters cannot be changed once the message is created
178
// we can record this fact
179
d_ptr->parametersValidated = true;
181
QDBusMarshaller marshaller(capabilities);
182
QVariantList::ConstIterator it = d_ptr->arguments.constBegin();
183
QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
184
q_dbus_message_iter_init_append(msg, &marshaller.iterator);
185
if (!d_ptr->message.isEmpty())
186
// prepend the error message
187
marshaller.append(d_ptr->message);
188
for ( ; it != cend; ++it)
189
marshaller.appendVariantInternal(*it);
191
// check if everything is ok
196
q_dbus_message_unref(msg);
197
*error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: ") + marshaller.errorString);
208
unsigned int locked : 1;
210
unsigned int in_cache : 1;
212
DBusList *size_counters;
213
long size_counter_delta;
214
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
215
DBusDataSlotList slot_list;
216
#ifndef DBUS_DISABLE_CHECKS
224
Constructs a QDBusMessage by parsing the given DBusMessage object.
226
QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
228
QDBusMessage message;
232
message.d_ptr->type = q_dbus_message_get_type(dmsg);
233
message.d_ptr->path = QString::fromUtf8(q_dbus_message_get_path(dmsg));
234
message.d_ptr->interface = QString::fromUtf8(q_dbus_message_get_interface(dmsg));
235
message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
236
QString::fromUtf8(q_dbus_message_get_error_name(dmsg)) :
237
QString::fromUtf8(q_dbus_message_get_member(dmsg));
238
message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg));
239
message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg));
240
message.d_ptr->msg = q_dbus_message_ref(dmsg);
242
QDBusDemarshaller demarshaller(capabilities);
243
demarshaller.message = q_dbus_message_ref(dmsg);
244
if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
245
while (!demarshaller.atEnd())
246
message << demarshaller.toVariantInternal();
250
bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
252
return message.d_ptr->localMessage;
255
QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
256
const QDBusMessage &asSent)
258
// simulate the message being sent to the bus and then received back
259
// the only field that the bus sets when delivering the message
260
// (as opposed to the message as we send it), is the sender
261
// so we simply set the sender to our unique name
263
// determine if we are carrying any complex types
264
QString computedSignature;
265
QVariantList::ConstIterator it = asSent.d_ptr->arguments.constBegin();
266
QVariantList::ConstIterator end = asSent.d_ptr->arguments.constEnd();
267
for ( ; it != end; ++it) {
268
int id = it->userType();
269
const char *signature = QDBusMetaType::typeToSignature(id);
270
if ((id != QVariant::StringList && id != QVariant::ByteArray &&
271
qstrlen(signature) != 1) || id == qMetaTypeId<QDBusVariant>()) {
273
// we must marshall and demarshall again so as to create QDBusArgument
274
// entries for the complex types
276
DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
278
// failed to marshall, so it's a call error
279
return QDBusMessage::createError(error);
282
q_dbus_message_set_sender(message, conn.baseService.toUtf8());
284
QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
285
retval.d_ptr->localMessage = true;
286
q_dbus_message_unref(message);
287
if (retval.d_ptr->service.isEmpty())
288
retval.d_ptr->service = conn.baseService;
291
computedSignature += QLatin1String(signature);
295
// no complex types seen
296
// optimize by using the variant list itself
298
QDBusMessagePrivate *d = retval.d_ptr;
299
d->arguments = asSent.d_ptr->arguments;
300
d->path = asSent.d_ptr->path;
301
d->interface = asSent.d_ptr->interface;
302
d->name = asSent.d_ptr->name;
303
d->message = asSent.d_ptr->message;
304
d->type = asSent.d_ptr->type;
306
d->service = conn.baseService;
307
d->signature = computedSignature;
308
d->localMessage = true;
312
QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn,
313
const QDBusMessage &callMsg)
315
// simulate the reply (return or error) message being sent to the bus and
316
// then received back.
317
if (callMsg.d_ptr->localReply)
318
return makeLocal(conn, *callMsg.d_ptr->localReply);
319
return QDBusMessage(); // failed
327
\brief The QDBusMessage class represents one message sent or
328
received over the D-Bus bus.
330
This object can represent any of the four different types of
331
messages (MessageType) that can occur on the bus:
335
\li Method return values
340
Objects of this type are created with the static createError(),
341
createMethodCall() and createSignal() functions. Use the
342
QDBusConnection::send() function to send the messages.
346
\enum QDBusMessage::MessageType
347
The possible message types:
349
\value MethodCallMessage a message representing an outgoing or incoming method call
350
\value SignalMessage a message representing an outgoing or incoming signal emission
351
\value ReplyMessage a message representing the return values of a method call
352
\value ErrorMessage a message representing an error condition in response to a method call
353
\value InvalidMessage an invalid message: this is never set on messages received from D-Bus
357
Constructs a new DBus message with the given \a path, \a interface
358
and \a name, representing a signal emission.
360
A DBus signal is emitted from one application and is received by
361
all applications that are listening for that signal from that
364
The QDBusMessage object that is returned can be sent using the
365
QDBusConnection::send() function.
367
QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
370
QDBusMessage message;
371
message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
372
message.d_ptr->path = path;
373
message.d_ptr->interface = interface;
374
message.d_ptr->name = name;
380
Constructs a new DBus message representing a method call.
381
A method call always informs its destination address
382
(\a service, \a path, \a interface and \a method).
384
The DBus bus allows calling a method on a given remote object without specifying the
385
destination interface, if the method name is unique. However, if two interfaces on the
386
remote object export the same method name, the result is undefined (one of the two may be
387
called or an error may be returned).
389
When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
392
The QDBusInterface class provides a simpler abstraction to synchronous
395
This function returns a QDBusMessage object that can be sent with
396
QDBusConnection::call().
398
QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
399
const QString &interface, const QString &method)
401
QDBusMessage message;
402
message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
403
message.d_ptr->service = service;
404
message.d_ptr->path = path;
405
message.d_ptr->interface = interface;
406
message.d_ptr->name = method;
412
Constructs a new DBus message representing an error,
413
with the given \a name and \a msg.
415
QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
418
error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
419
error.d_ptr->name = name;
420
error.d_ptr->message = msg;
426
\fn QDBusMessage QDBusMessage::createError(const QDBusError &error)
428
Constructs a new DBus message representing the given \a error.
432
\fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg)
434
Constructs a new DBus message for the error type \a type using
435
the message \a msg. Returns the DBus message.
439
\fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const
441
Constructs a new DBus message representing a reply, with the given
444
QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
447
reply.setArguments(arguments);
448
reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
450
reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
451
if (d_ptr->localMessage) {
452
reply.d_ptr->localMessage = true;
453
d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
456
// the reply must have a msg or be a local-loop optimization
457
Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
462
Constructs a new DBus message representing an error reply message,
463
with the given \a name and \a msg.
465
QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
467
QDBusMessage reply = QDBusMessage::createError(name, msg);
469
reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
470
if (d_ptr->localMessage) {
471
reply.d_ptr->localMessage = true;
472
d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
475
// the reply must have a msg or be a local-loop optimization
476
Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
481
\fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
483
Constructs a new DBus message representing a reply, with the
488
\fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
490
Constructs a new DBus message representing an error reply message,
491
from the given \a error object.
495
\fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
497
Constructs a new DBus reply message for the error type \a type using
498
the message \a msg. Returns the DBus message.
500
QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
502
QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg);
503
msg.d_ptr->parametersValidated = true;
509
Constructs an empty, invalid QDBusMessage object.
511
\sa createError(), createMethodCall(), createSignal()
513
QDBusMessage::QDBusMessage()
515
d_ptr = new QDBusMessagePrivate;
519
Constructs a copy of the object given by \a other.
521
Note: QDBusMessage objects are shared. Modifications made to the
522
copy will affect the original one as well. See setDelayedReply()
523
for more information.
525
QDBusMessage::QDBusMessage(const QDBusMessage &other)
532
Disposes of the object and frees any resources that were being held.
534
QDBusMessage::~QDBusMessage()
536
if (!d_ptr->ref.deref())
541
Copies the contents of the object given by \a other.
543
Note: QDBusMessage objects are shared. Modifications made to the
544
copy will affect the original one as well. See setDelayedReply()
545
for more information.
547
QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
549
qAtomicAssign(d_ptr, other.d_ptr);
554
Returns the name of the service or the bus address of the remote method call.
556
QString QDBusMessage::service() const
558
return d_ptr->service;
562
Returns the path of the object that this message is being sent to (in the case of a
563
method call) or being received from (for a signal).
565
QString QDBusMessage::path() const
571
Returns the interface of the method being called (in the case of a method call) or of
572
the signal being received from.
574
QString QDBusMessage::interface() const
576
return d_ptr->interface;
580
Returns the name of the signal that was emitted or the name of the method that was called.
582
QString QDBusMessage::member() const
584
if (d_ptr->type != ErrorMessage)
590
Returns the name of the error that was received.
592
QString QDBusMessage::errorName() const
594
if (d_ptr->type == ErrorMessage)
600
Returns the signature of the signal that was received or for the output arguments
603
QString QDBusMessage::signature() const
605
return d_ptr->signature;
609
Returns the flag that indicates if this message should see a reply
610
or not. This is only meaningful for \l {MethodCallMessage}{method
611
call messages}: any other kind of message cannot have replies and
612
this function will always return false for them.
614
bool QDBusMessage::isReplyRequired() const
617
return d_ptr->localMessage; // if it's a local message, reply is required
618
return !q_dbus_message_get_no_reply(d_ptr->msg);
622
Sets whether the message will be replied later (if \a enable is
623
true) or if an automatic reply should be generated by QtDBus
624
(if \a enable is false).
626
In D-Bus, all method calls must generate a reply to the caller, unless the
627
caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
628
automatically generates such replies for any slots being called, but it
629
also allows slots to indicate whether they will take responsibility
630
of sending the reply at a later time, after the function has finished
633
\sa {Delayed Replies}
635
void QDBusMessage::setDelayedReply(bool enable) const
637
d_ptr->delayedReply = enable;
641
Returns the delayed reply flag, as set by setDelayedReply(). By default, this
642
flag is false, which means QtDBus will generate automatic replies
645
bool QDBusMessage::isDelayedReply() const
647
return d_ptr->delayedReply;
651
Sets the auto start flag to \a enable. This flag only makes sense
652
for method call messages, where it tells the D-Bus server to
653
either auto start the service responsible for the service name, or
654
not to auto start it.
656
By default this flag is true, i.e. a service is autostarted.
659
When the service that this method call is sent to is already
660
running, the method call is sent to it. If the service is not
661
running yet, the D-Bus daemon is requested to autostart the
662
service that is assigned to this service name. This is
663
handled by .service files that are placed in a directory known
664
to the D-Bus server. These files then each contain a service
665
name and the path to a program that should be executed when
666
this service name is requested.
670
void QDBusMessage::setAutoStartService(bool enable)
672
d_ptr->autoStartService = enable;
676
Returns the auto start flag, as set by setAutoStartService(). By default, this
677
flag is true, which means QtDBus will auto start a service, if it is
680
\sa setAutoStartService()
684
bool QDBusMessage::autoStartService() const
686
return d_ptr->autoStartService;
690
Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
691
will be the arguments to a method call or the parameters in the signal.
695
void QDBusMessage::setArguments(const QList<QVariant> &arguments)
697
// FIXME: should we detach?
698
d_ptr->arguments = arguments;
702
Returns the list of arguments that are going to be sent or were received from
705
QList<QVariant> QDBusMessage::arguments() const
707
return d_ptr->arguments;
711
Appends the argument \a arg to the list of arguments to be sent over D-Bus in
712
a method call or signal emission.
715
QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
717
// FIXME: should we detach?
718
d_ptr->arguments.append(arg);
723
Returns the message type.
725
QDBusMessage::MessageType QDBusMessage::type() const
727
switch (d_ptr->type) {
728
case DBUS_MESSAGE_TYPE_METHOD_CALL:
729
return MethodCallMessage;
730
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
732
case DBUS_MESSAGE_TYPE_ERROR:
734
case DBUS_MESSAGE_TYPE_SIGNAL:
735
return SignalMessage;
739
return InvalidMessage;
743
Sends the message without waiting for a reply. This is suitable
744
for errors, signals, and return values as well as calls whose
745
return values are not necessary.
747
Returns true if the message was queued successfully;
748
otherwise returns false.
750
\sa QDBusConnection::send()
752
#ifndef QT_NO_DEBUG_STREAM
753
static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
757
case QDBusMessage::MethodCallMessage:
758
return dbg << "MethodCall";
759
case QDBusMessage::ReplyMessage:
760
return dbg << "MethodReturn";
761
case QDBusMessage::SignalMessage:
762
return dbg << "Signal";
763
case QDBusMessage::ErrorMessage:
764
return dbg << "Error";
766
return dbg << "Invalid";
770
static void debugVariantList(QDebug dbg, const QVariantList &list)
773
QVariantList::ConstIterator it = list.constBegin();
774
QVariantList::ConstIterator end = list.constEnd();
775
for ( ; it != end; ++it) {
777
dbg.nospace() << ", ";
778
dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it));
783
QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
785
dbg.nospace() << "QDBusMessage(type=" << msg.type()
786
<< ", service=" << msg.service();
787
if (msg.type() == QDBusMessage::MethodCallMessage ||
788
msg.type() == QDBusMessage::SignalMessage)
789
dbg.nospace() << ", path=" << msg.path()
790
<< ", interface=" << msg.interface()
791
<< ", member=" << msg.member();
792
if (msg.type() == QDBusMessage::ErrorMessage)
793
dbg.nospace() << ", error name=" << msg.errorName()
794
<< ", error message=" << msg.errorMessage();
795
dbg.nospace() << ", signature=" << msg.signature()
797
debugVariantList(dbg, msg.arguments());
798
dbg.nospace() << ") )";