1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtDBus module of the Qt Toolkit. |
7 | ** |
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. |
16 | ** |
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. |
24 | ** |
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. |
28 | ** |
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. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include "qdbusmessage.h" |
43 | |
44 | #include <qdebug.h> |
45 | #include <qstringlist.h> |
46 | |
47 | #include "qdbus_symbols_p.h" |
48 | |
49 | #include "qdbusargument_p.h" |
50 | #include "qdbuserror.h" |
51 | #include "qdbusmessage_p.h" |
52 | #include "qdbusmetatype.h" |
53 | #include "qdbusconnection_p.h" |
54 | #include "qdbusutil_p.h" |
55 | |
56 | #ifndef QT_NO_DBUS |
57 | |
58 | QT_BEGIN_NAMESPACE |
59 | |
60 | static inline const char *data(const QByteArray &arr) |
61 | { |
62 | return arr.isEmpty() ? 0 : arr.constData(); |
63 | } |
64 | |
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) |
69 | { |
70 | } |
71 | |
72 | QDBusMessagePrivate::~QDBusMessagePrivate() |
73 | { |
74 | if (msg) |
75 | q_dbus_message_unref(msg); |
76 | if (reply) |
77 | q_dbus_message_unref(reply); |
78 | delete localReply; |
79 | } |
80 | |
81 | /*! |
82 | \since 4.3 |
83 | Returns the human-readable message associated with the error that was received. |
84 | */ |
85 | QString QDBusMessage::errorMessage() const |
86 | { |
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(); |
92 | } |
93 | return QString(); |
94 | } |
95 | |
96 | /*! |
97 | \internal |
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. |
100 | |
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. |
104 | */ |
105 | DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities, |
106 | QDBusError *error) |
107 | { |
108 | if (!qdbus_loadLibDBus()) { |
109 | *error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library" )); |
110 | return 0; |
111 | } |
112 | |
113 | DBusMessage *msg = 0; |
114 | const QDBusMessagePrivate *d_ptr = message.d_ptr; |
115 | |
116 | switch (d_ptr->type) { |
117 | case DBUS_MESSAGE_TYPE_INVALID: |
118 | //qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid"; |
119 | break; |
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)) |
124 | return 0; |
125 | if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) |
126 | return 0; |
127 | if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) |
128 | return 0; |
129 | if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method" )) |
130 | return 0; |
131 | } |
132 | |
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 ); |
136 | break; |
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)); |
142 | } |
143 | break; |
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)) |
148 | return 0; |
149 | |
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)); |
155 | } |
156 | break; |
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)) |
161 | return 0; |
162 | if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) |
163 | return 0; |
164 | if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method" )) |
165 | return 0; |
166 | } |
167 | |
168 | msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(), |
169 | d_ptr->name.toUtf8()); |
170 | break; |
171 | default: |
172 | Q_ASSERT(false); |
173 | break; |
174 | } |
175 | |
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; |
180 | |
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); |
190 | |
191 | // check if everything is ok |
192 | if (marshaller.ok) |
193 | return msg; |
194 | |
195 | // not ok; |
196 | q_dbus_message_unref(msg); |
197 | *error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: " ) + marshaller.errorString); |
198 | return 0; |
199 | } |
200 | |
201 | /* |
202 | struct DBusMessage |
203 | { |
204 | DBusAtomic refcount; |
205 | DBusHeader header; |
206 | DBusString body; |
207 | char byte_order; |
208 | unsigned int locked : 1; |
209 | DBUS_DISABLE_CHECKS |
210 | unsigned int in_cache : 1; |
211 | #endif |
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 |
217 | int generation; |
218 | #endif |
219 | }; |
220 | */ |
221 | |
222 | /*! |
223 | \internal |
224 | Constructs a QDBusMessage by parsing the given DBusMessage object. |
225 | */ |
226 | QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities) |
227 | { |
228 | QDBusMessage message; |
229 | if (!dmsg) |
230 | return message; |
231 | |
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); |
241 | |
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(); |
247 | return message; |
248 | } |
249 | |
250 | bool QDBusMessagePrivate::isLocal(const QDBusMessage &message) |
251 | { |
252 | return message.d_ptr->localMessage; |
253 | } |
254 | |
255 | QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn, |
256 | const QDBusMessage &asSent) |
257 | { |
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 |
262 | |
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>()) { |
272 | // yes, we are |
273 | // we must marshall and demarshall again so as to create QDBusArgument |
274 | // entries for the complex types |
275 | QDBusError error; |
276 | DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error); |
277 | if (!message) { |
278 | // failed to marshall, so it's a call error |
279 | return QDBusMessage::createError(error); |
280 | } |
281 | |
282 | q_dbus_message_set_sender(message, conn.baseService.toUtf8()); |
283 | |
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; |
289 | return retval; |
290 | } else { |
291 | computedSignature += QLatin1String(signature); |
292 | } |
293 | } |
294 | |
295 | // no complex types seen |
296 | // optimize by using the variant list itself |
297 | QDBusMessage retval; |
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; |
305 | |
306 | d->service = conn.baseService; |
307 | d->signature = computedSignature; |
308 | d->localMessage = true; |
309 | return retval; |
310 | } |
311 | |
312 | QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn, |
313 | const QDBusMessage &callMsg) |
314 | { |
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 |
320 | } |
321 | |
322 | /*! |
323 | \class QDBusMessage |
324 | \inmodule QtDBus |
325 | \since 4.2 |
326 | |
327 | \brief The QDBusMessage class represents one message sent or |
328 | received over the D-Bus bus. |
329 | |
330 | This object can represent any of the four different types of |
331 | messages (MessageType) that can occur on the bus: |
332 | |
333 | \list |
334 | \o Method calls |
335 | \o Method return values |
336 | \o Signal emissions |
337 | \o Error codes |
338 | \endlist |
339 | |
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. |
343 | */ |
344 | |
345 | /*! |
346 | \enum QDBusMessage::MessageType |
347 | The possible message types: |
348 | |
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 |
354 | */ |
355 | |
356 | /*! |
357 | Constructs a new DBus message with the given \a path, \a interface |
358 | and \a name, representing a signal emission. |
359 | |
360 | A DBus signal is emitted from one application and is received by |
361 | all applications that are listening for that signal from that |
362 | interface. |
363 | |
364 | The QDBusMessage object that is returned can be sent using the |
365 | QDBusConnection::send() function. |
366 | */ |
367 | QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface, |
368 | const QString &name) |
369 | { |
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; |
375 | |
376 | return message; |
377 | } |
378 | |
379 | /*! |
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). |
383 | |
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). |
388 | |
389 | When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is |
390 | optional. |
391 | |
392 | The QDBusObject and QDBusInterface classes provide a simpler abstraction to synchronous |
393 | method calling. |
394 | |
395 | This function returns a QDBusMessage object that can be sent with |
396 | QDBusConnection::call(). |
397 | */ |
398 | QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path, |
399 | const QString &interface, const QString &method) |
400 | { |
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; |
407 | |
408 | return message; |
409 | } |
410 | |
411 | /*! |
412 | Constructs a new DBus message representing an error, |
413 | with the given \a name and \a msg. |
414 | */ |
415 | QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg) |
416 | { |
417 | QDBusMessage error; |
418 | error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR; |
419 | error.d_ptr->name = name; |
420 | error.d_ptr->message = msg; |
421 | |
422 | return error; |
423 | } |
424 | |
425 | /*! |
426 | \fn QDBusMessage QDBusMessage::createError(const QDBusError &error) |
427 | |
428 | Constructs a new DBus message representing the given \a error. |
429 | */ |
430 | |
431 | /*! |
432 | \fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg) |
433 | |
434 | Constructs a new DBus message for the error type \a type using |
435 | the message \a msg. Returns the DBus message. |
436 | */ |
437 | |
438 | /*! |
439 | \fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const |
440 | |
441 | Constructs a new DBus message representing a reply, with the given |
442 | \a arguments. |
443 | */ |
444 | QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const |
445 | { |
446 | QDBusMessage reply; |
447 | reply.setArguments(arguments); |
448 | reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN; |
449 | if (d_ptr->msg) |
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 |
454 | } |
455 | |
456 | // the reply must have a msg or be a local-loop optimization |
457 | Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); |
458 | return reply; |
459 | } |
460 | |
461 | /*! |
462 | Constructs a new DBus message representing an error reply message, |
463 | with the given \a name and \a msg. |
464 | */ |
465 | QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const |
466 | { |
467 | QDBusMessage reply = QDBusMessage::createError(name, msg); |
468 | if (d_ptr->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 |
473 | } |
474 | |
475 | // the reply must have a msg or be a local-loop optimization |
476 | Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); |
477 | return reply; |
478 | } |
479 | |
480 | /*! |
481 | \fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const |
482 | |
483 | Constructs a new DBus message representing a reply, with the |
484 | given \a argument. |
485 | */ |
486 | |
487 | /*! |
488 | \fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const |
489 | |
490 | Constructs a new DBus message representing an error reply message, |
491 | from the given \a error object. |
492 | */ |
493 | |
494 | /*! |
495 | \fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const |
496 | |
497 | Constructs a new DBus reply message for the error type \a type using |
498 | the message \a msg. Returns the DBus message. |
499 | */ |
500 | QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const |
501 | { |
502 | QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg); |
503 | msg.d_ptr->parametersValidated = true; |
504 | return msg; |
505 | } |
506 | |
507 | |
508 | /*! |
509 | Constructs an empty, invalid QDBusMessage object. |
510 | |
511 | \sa createError(), createMethodCall(), createSignal() |
512 | */ |
513 | QDBusMessage::QDBusMessage() |
514 | { |
515 | d_ptr = new QDBusMessagePrivate; |
516 | } |
517 | |
518 | /*! |
519 | Constructs a copy of the object given by \a other. |
520 | |
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. |
524 | */ |
525 | QDBusMessage::QDBusMessage(const QDBusMessage &other) |
526 | { |
527 | d_ptr = other.d_ptr; |
528 | d_ptr->ref.ref(); |
529 | } |
530 | |
531 | /*! |
532 | Disposes of the object and frees any resources that were being held. |
533 | */ |
534 | QDBusMessage::~QDBusMessage() |
535 | { |
536 | if (!d_ptr->ref.deref()) |
537 | delete d_ptr; |
538 | } |
539 | |
540 | /*! |
541 | Copies the contents of the object given by \a other. |
542 | |
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. |
546 | */ |
547 | QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other) |
548 | { |
549 | qAtomicAssign(d_ptr, other.d_ptr); |
550 | return *this; |
551 | } |
552 | |
553 | /*! |
554 | Returns the name of the service or the bus address of the remote method call. |
555 | */ |
556 | QString QDBusMessage::service() const |
557 | { |
558 | return d_ptr->service; |
559 | } |
560 | |
561 | /*! |
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). |
564 | */ |
565 | QString QDBusMessage::path() const |
566 | { |
567 | return d_ptr->path; |
568 | } |
569 | |
570 | /*! |
571 | Returns the interface of the method being called (in the case of a method call) or of |
572 | the signal being received from. |
573 | */ |
574 | QString QDBusMessage::interface() const |
575 | { |
576 | return d_ptr->interface; |
577 | } |
578 | |
579 | /*! |
580 | Returns the name of the signal that was emitted or the name of the method that was called. |
581 | */ |
582 | QString QDBusMessage::member() const |
583 | { |
584 | if (d_ptr->type != ErrorMessage) |
585 | return d_ptr->name; |
586 | return QString(); |
587 | } |
588 | |
589 | /*! |
590 | Returns the name of the error that was received. |
591 | */ |
592 | QString QDBusMessage::errorName() const |
593 | { |
594 | if (d_ptr->type == ErrorMessage) |
595 | return d_ptr->name; |
596 | return QString(); |
597 | } |
598 | |
599 | /*! |
600 | Returns the signature of the signal that was received or for the output arguments |
601 | of a method call. |
602 | */ |
603 | QString QDBusMessage::signature() const |
604 | { |
605 | return d_ptr->signature; |
606 | } |
607 | |
608 | /*! |
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. |
613 | */ |
614 | bool QDBusMessage::isReplyRequired() const |
615 | { |
616 | if (!d_ptr->msg) |
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); |
619 | } |
620 | |
621 | /*! |
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). |
625 | |
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 |
631 | processing. |
632 | |
633 | \sa {Delayed Replies} |
634 | */ |
635 | void QDBusMessage::setDelayedReply(bool enable) const |
636 | { |
637 | d_ptr->delayedReply = enable; |
638 | } |
639 | |
640 | /*! |
641 | Returns the delayed reply flag, as set by setDelayedReply(). By default, this |
642 | flag is false, which means QtDBus will generate automatic replies |
643 | when necessary. |
644 | */ |
645 | bool QDBusMessage::isDelayedReply() const |
646 | { |
647 | return d_ptr->delayedReply; |
648 | } |
649 | |
650 | /*! |
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. |
655 | |
656 | By default this flag is true, i.e. a service is autostarted. |
657 | This means: |
658 | |
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. |
667 | |
668 | \since 4.7 |
669 | */ |
670 | void QDBusMessage::setAutoStartService(bool enable) |
671 | { |
672 | d_ptr->autoStartService = enable; |
673 | } |
674 | |
675 | /*! |
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 |
678 | not running already. |
679 | |
680 | \sa setAutoStartService() |
681 | |
682 | \since 4.7 |
683 | */ |
684 | bool QDBusMessage::autoStartService() const |
685 | { |
686 | return d_ptr->autoStartService; |
687 | } |
688 | |
689 | /*! |
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. |
692 | |
693 | \sa arguments() |
694 | */ |
695 | void QDBusMessage::setArguments(const QList<QVariant> &arguments) |
696 | { |
697 | // FIXME: should we detach? |
698 | d_ptr->arguments = arguments; |
699 | } |
700 | |
701 | /*! |
702 | Returns the list of arguments that are going to be sent or were received from |
703 | D-Bus. |
704 | */ |
705 | QList<QVariant> QDBusMessage::arguments() const |
706 | { |
707 | return d_ptr->arguments; |
708 | } |
709 | |
710 | /*! |
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. |
713 | */ |
714 | |
715 | QDBusMessage &QDBusMessage::operator<<(const QVariant &arg) |
716 | { |
717 | // FIXME: should we detach? |
718 | d_ptr->arguments.append(arg); |
719 | return *this; |
720 | } |
721 | |
722 | /*! |
723 | Returns the message type. |
724 | */ |
725 | QDBusMessage::MessageType QDBusMessage::type() const |
726 | { |
727 | switch (d_ptr->type) { |
728 | case DBUS_MESSAGE_TYPE_METHOD_CALL: |
729 | return MethodCallMessage; |
730 | case DBUS_MESSAGE_TYPE_METHOD_RETURN: |
731 | return ReplyMessage; |
732 | case DBUS_MESSAGE_TYPE_ERROR: |
733 | return ErrorMessage; |
734 | case DBUS_MESSAGE_TYPE_SIGNAL: |
735 | return SignalMessage; |
736 | default: |
737 | break; |
738 | } |
739 | return InvalidMessage; |
740 | } |
741 | |
742 | /*! |
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. |
746 | |
747 | Returns true if the message was queued successfully; |
748 | otherwise returns false. |
749 | |
750 | \sa QDBusConnection::send() |
751 | */ |
752 | #ifndef QT_NO_DEBUG_STREAM |
753 | static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t) |
754 | { |
755 | switch (t) |
756 | { |
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" ; |
765 | default: |
766 | return dbg << "Invalid" ; |
767 | } |
768 | } |
769 | |
770 | static void debugVariantList(QDebug dbg, const QVariantList &list) |
771 | { |
772 | bool first = true; |
773 | QVariantList::ConstIterator it = list.constBegin(); |
774 | QVariantList::ConstIterator end = list.constEnd(); |
775 | for ( ; it != end; ++it) { |
776 | if (!first) |
777 | dbg.nospace() << ", " ; |
778 | dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it)); |
779 | first = false; |
780 | } |
781 | } |
782 | |
783 | QDebug operator<<(QDebug dbg, const QDBusMessage &msg) |
784 | { |
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() |
796 | << ", contents=(" ; |
797 | debugVariantList(dbg, msg.arguments()); |
798 | dbg.nospace() << ") )" ; |
799 | return dbg.space(); |
800 | } |
801 | #endif |
802 | |
803 | QT_END_NAMESPACE |
804 | |
805 | #endif // QT_NO_DBUS |
806 | |