1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2016 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include "qdbusmessage.h" |
6 | #include "qdbusmessage_p.h" |
7 | |
8 | #include <qdebug.h> |
9 | #include <qstringlist.h> |
10 | |
11 | #include "qdbus_symbols_p.h" |
12 | |
13 | #include "qdbusargument_p.h" |
14 | #include "qdbuserror.h" |
15 | #include "qdbusmetatype.h" |
16 | #include "qdbusconnection_p.h" |
17 | #include "qdbusutil_p.h" |
18 | |
19 | #ifndef QT_NO_DBUS |
20 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | using namespace Qt::StringLiterals; |
24 | |
25 | QT_IMPL_METATYPE_EXTERN(QDBusMessage) |
26 | |
27 | static_assert(QDBusMessage::InvalidMessage == DBUS_MESSAGE_TYPE_INVALID); |
28 | static_assert(QDBusMessage::MethodCallMessage == DBUS_MESSAGE_TYPE_METHOD_CALL); |
29 | static_assert(QDBusMessage::ReplyMessage == DBUS_MESSAGE_TYPE_METHOD_RETURN); |
30 | static_assert(QDBusMessage::ErrorMessage == DBUS_MESSAGE_TYPE_ERROR); |
31 | static_assert(QDBusMessage::SignalMessage == DBUS_MESSAGE_TYPE_SIGNAL); |
32 | |
33 | static inline const char *data(const QByteArray &arr) |
34 | { |
35 | return arr.isEmpty() ? nullptr : arr.constData(); |
36 | } |
37 | |
38 | QDBusMessagePrivate::QDBusMessagePrivate() |
39 | : msg(nullptr), reply(nullptr), localReply(nullptr), ref(1), type(QDBusMessage::InvalidMessage), |
40 | delayedReply(false), localMessage(false), |
41 | parametersValidated(false), autoStartService(true), |
42 | interactiveAuthorizationAllowed(false) |
43 | { |
44 | } |
45 | |
46 | QDBusMessagePrivate::~QDBusMessagePrivate() |
47 | { |
48 | if (msg) |
49 | q_dbus_message_unref(message: msg); |
50 | if (reply) |
51 | q_dbus_message_unref(message: reply); |
52 | delete localReply; |
53 | } |
54 | |
55 | /*! |
56 | \since 4.3 |
57 | Returns the human-readable message associated with the error that was received. |
58 | */ |
59 | QString QDBusMessage::errorMessage() const |
60 | { |
61 | if (d_ptr->type == ErrorMessage) { |
62 | if (!d_ptr->message.isEmpty()) |
63 | return d_ptr->message; |
64 | if (!d_ptr->arguments.isEmpty()) |
65 | return d_ptr->arguments.at(i: 0).toString(); |
66 | } |
67 | return QString(); |
68 | } |
69 | |
70 | /*! |
71 | \internal |
72 | Constructs a DBusMessage object from \a message. The returned value must be de-referenced |
73 | with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use. |
74 | |
75 | The \a error object is set to indicate the error if anything went wrong with the |
76 | marshalling. Usually, this error message will be placed in the reply, as if the call failed. |
77 | The \a error pointer must not be null. |
78 | */ |
79 | DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities, |
80 | QDBusError *error) |
81 | { |
82 | if (!qdbus_loadLibDBus()) { |
83 | *error = QDBusError(QDBusError::Failed, "Could not open lidbus-1 library"_L1 ); |
84 | return nullptr; |
85 | } |
86 | |
87 | DBusMessage *msg = nullptr; |
88 | const QDBusMessagePrivate *d_ptr = message.d_ptr; |
89 | |
90 | switch (d_ptr->type) { |
91 | case QDBusMessage::InvalidMessage: |
92 | //qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid"; |
93 | break; |
94 | case QDBusMessage::MethodCallMessage: |
95 | // only service and interface can be empty -> path and name must not be empty |
96 | if (!d_ptr->parametersValidated) { |
97 | if (!QDBusUtil::checkBusName(name: d_ptr->service, empty: QDBusUtil::EmptyAllowed, error)) |
98 | return nullptr; |
99 | if (!QDBusUtil::checkObjectPath(path: d_ptr->path, empty: QDBusUtil::EmptyNotAllowed, error)) |
100 | return nullptr; |
101 | if (!QDBusUtil::checkInterfaceName(name: d_ptr->interface, empty: QDBusUtil::EmptyAllowed, error)) |
102 | return nullptr; |
103 | if (!QDBusUtil::checkMemberName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error, nameType: "method" )) |
104 | return nullptr; |
105 | } |
106 | |
107 | msg = q_dbus_message_new_method_call(bus_name: data(arr: d_ptr->service.toUtf8()), path: d_ptr->path.toUtf8(), |
108 | interface: data(arr: d_ptr->interface.toUtf8()), method: d_ptr->name.toUtf8()); |
109 | q_dbus_message_set_auto_start( message: msg, auto_start: d_ptr->autoStartService ); |
110 | q_dbus_message_set_allow_interactive_authorization(message: msg, allow: d_ptr->interactiveAuthorizationAllowed); |
111 | |
112 | break; |
113 | case QDBusMessage::ReplyMessage: |
114 | msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); |
115 | if (!d_ptr->localMessage) { |
116 | q_dbus_message_set_destination(message: msg, destination: q_dbus_message_get_sender(message: d_ptr->reply)); |
117 | q_dbus_message_set_reply_serial(message: msg, reply_serial: q_dbus_message_get_serial(message: d_ptr->reply)); |
118 | } |
119 | break; |
120 | case QDBusMessage::ErrorMessage: |
121 | // error name can't be empty |
122 | if (!d_ptr->parametersValidated |
123 | && !QDBusUtil::checkErrorName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error)) |
124 | return nullptr; |
125 | |
126 | msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); |
127 | q_dbus_message_set_error_name(message: msg, name: d_ptr->name.toUtf8()); |
128 | if (!d_ptr->localMessage) { |
129 | q_dbus_message_set_destination(message: msg, destination: q_dbus_message_get_sender(message: d_ptr->reply)); |
130 | q_dbus_message_set_reply_serial(message: msg, reply_serial: q_dbus_message_get_serial(message: d_ptr->reply)); |
131 | } |
132 | break; |
133 | case QDBusMessage::SignalMessage: |
134 | // only the service name can be empty here |
135 | if (!d_ptr->parametersValidated) { |
136 | if (!QDBusUtil::checkBusName(name: d_ptr->service, empty: QDBusUtil::EmptyAllowed, error)) |
137 | return nullptr; |
138 | if (!QDBusUtil::checkObjectPath(path: d_ptr->path, empty: QDBusUtil::EmptyNotAllowed, error)) |
139 | return nullptr; |
140 | if (!QDBusUtil::checkInterfaceName(name: d_ptr->interface, empty: QDBusUtil::EmptyAllowed, error)) |
141 | return nullptr; |
142 | if (!QDBusUtil::checkMemberName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error, nameType: "method" )) |
143 | return nullptr; |
144 | } |
145 | |
146 | msg = q_dbus_message_new_signal(path: d_ptr->path.toUtf8(), interface: d_ptr->interface.toUtf8(), |
147 | name: d_ptr->name.toUtf8()); |
148 | q_dbus_message_set_destination(message: msg, destination: data(arr: d_ptr->service.toUtf8())); |
149 | break; |
150 | } |
151 | |
152 | // if we got here, the parameters validated |
153 | // and since the message parameters cannot be changed once the message is created |
154 | // we can record this fact |
155 | d_ptr->parametersValidated = true; |
156 | |
157 | QDBusMarshaller marshaller(capabilities); |
158 | q_dbus_message_iter_init_append(message: msg, iter: &marshaller.iterator); |
159 | if (!d_ptr->message.isEmpty()) |
160 | // prepend the error message |
161 | marshaller.append(arg: d_ptr->message); |
162 | for (const QVariant &argument : std::as_const(t: d_ptr->arguments)) |
163 | marshaller.appendVariantInternal(arg: argument); |
164 | |
165 | // check if everything is ok |
166 | if (marshaller.ok) |
167 | return msg; |
168 | |
169 | // not ok; |
170 | q_dbus_message_unref(message: msg); |
171 | *error = QDBusError(QDBusError::Failed, "Marshalling failed: "_L1 + marshaller.errorString); |
172 | return nullptr; |
173 | } |
174 | |
175 | /* |
176 | struct DBusMessage |
177 | { |
178 | DBusAtomic refcount; |
179 | DBusHeader header; |
180 | DBusString body; |
181 | char byte_order; |
182 | unsigned int locked : 1; |
183 | DBUS_DISABLE_CHECKS |
184 | unsigned int in_cache : 1; |
185 | #endif |
186 | DBusList *size_counters; |
187 | long size_counter_delta; |
188 | dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; |
189 | DBusDataSlotList slot_list; |
190 | #ifndef DBUS_DISABLE_CHECKS |
191 | int generation; |
192 | #endif |
193 | }; |
194 | */ |
195 | |
196 | /*! |
197 | \internal |
198 | Constructs a QDBusMessage by parsing the given DBusMessage object. |
199 | */ |
200 | QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities) |
201 | { |
202 | QDBusMessage message; |
203 | if (!dmsg) |
204 | return message; |
205 | |
206 | message.d_ptr->type = QDBusMessage::MessageType(q_dbus_message_get_type(message: dmsg)); |
207 | message.d_ptr->path = QString::fromUtf8(utf8: q_dbus_message_get_path(message: dmsg)); |
208 | message.d_ptr->interface = QString::fromUtf8(utf8: q_dbus_message_get_interface(message: dmsg)); |
209 | message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ? |
210 | QString::fromUtf8(utf8: q_dbus_message_get_error_name(message: dmsg)) : |
211 | QString::fromUtf8(utf8: q_dbus_message_get_member(message: dmsg)); |
212 | message.d_ptr->service = QString::fromUtf8(utf8: q_dbus_message_get_sender(message: dmsg)); |
213 | message.d_ptr->signature = QString::fromUtf8(utf8: q_dbus_message_get_signature(message: dmsg)); |
214 | message.d_ptr->interactiveAuthorizationAllowed = q_dbus_message_get_allow_interactive_authorization(message: dmsg); |
215 | message.d_ptr->msg = q_dbus_message_ref(message: dmsg); |
216 | |
217 | QDBusDemarshaller demarshaller(capabilities); |
218 | demarshaller.message = q_dbus_message_ref(message: dmsg); |
219 | if (q_dbus_message_iter_init(message: demarshaller.message, iter: &demarshaller.iterator)) |
220 | while (!demarshaller.atEnd()) |
221 | message << demarshaller.toVariantInternal(); |
222 | return message; |
223 | } |
224 | |
225 | bool QDBusMessagePrivate::isLocal(const QDBusMessage &message) |
226 | { |
227 | return message.d_ptr->localMessage; |
228 | } |
229 | |
230 | QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn, |
231 | const QDBusMessage &asSent) |
232 | { |
233 | // simulate the message being sent to the bus and then received back |
234 | // the only field that the bus sets when delivering the message |
235 | // (as opposed to the message as we send it), is the sender |
236 | // so we simply set the sender to our unique name |
237 | |
238 | // determine if we are carrying any complex types |
239 | QString computedSignature; |
240 | for (const QVariant &argument : std::as_const(t&: asSent.d_ptr->arguments)) { |
241 | QMetaType id = argument.metaType(); |
242 | const char *signature = QDBusMetaType::typeToSignature(type: id); |
243 | if ((id.id() != QMetaType::QStringList && id.id() != QMetaType::QByteArray && |
244 | qstrlen(str: signature) != 1) || id == QMetaType::fromType<QDBusVariant>()) { |
245 | // yes, we are |
246 | // we must marshall and demarshall again so as to create QDBusArgument |
247 | // entries for the complex types |
248 | QDBusError error; |
249 | DBusMessage *message = toDBusMessage(message: asSent, capabilities: conn.connectionCapabilities(), error: &error); |
250 | if (!message) { |
251 | // failed to marshall, so it's a call error |
252 | return QDBusMessage::createError(err: error); |
253 | } |
254 | |
255 | q_dbus_message_set_sender(message, sender: conn.baseService.toUtf8()); |
256 | |
257 | QDBusMessage retval = fromDBusMessage(dmsg: message, capabilities: conn.connectionCapabilities()); |
258 | retval.d_ptr->localMessage = true; |
259 | q_dbus_message_unref(message); |
260 | if (retval.d_ptr->service.isEmpty()) |
261 | retval.d_ptr->service = conn.baseService; |
262 | return retval; |
263 | } else { |
264 | computedSignature += QLatin1StringView(signature); |
265 | } |
266 | } |
267 | |
268 | // no complex types seen |
269 | // optimize by using the variant list itself |
270 | QDBusMessage retval; |
271 | QDBusMessagePrivate *d = retval.d_ptr; |
272 | d->arguments = asSent.d_ptr->arguments; |
273 | d->path = asSent.d_ptr->path; |
274 | d->interface = asSent.d_ptr->interface; |
275 | d->name = asSent.d_ptr->name; |
276 | d->message = asSent.d_ptr->message; |
277 | d->type = asSent.d_ptr->type; |
278 | |
279 | d->service = conn.baseService; |
280 | d->signature = computedSignature; |
281 | d->localMessage = true; |
282 | return retval; |
283 | } |
284 | |
285 | QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn, |
286 | const QDBusMessage &callMsg) |
287 | { |
288 | // simulate the reply (return or error) message being sent to the bus and |
289 | // then received back. |
290 | if (callMsg.d_ptr->localReply) |
291 | return makeLocal(conn, asSent: *callMsg.d_ptr->localReply); |
292 | return QDBusMessage(); // failed |
293 | } |
294 | |
295 | /*! |
296 | \class QDBusMessage |
297 | \inmodule QtDBus |
298 | \since 4.2 |
299 | |
300 | \brief The QDBusMessage class represents one message sent or |
301 | received over the D-Bus bus. |
302 | |
303 | This object can represent any of the four different types of |
304 | messages (MessageType) that can occur on the bus: |
305 | |
306 | \list |
307 | \li Method calls |
308 | \li Method return values |
309 | \li Signal emissions |
310 | \li Error codes |
311 | \endlist |
312 | |
313 | Objects of this type are created with the static createError(), |
314 | createMethodCall() and createSignal() functions. Use the |
315 | QDBusConnection::send() function to send the messages. |
316 | */ |
317 | |
318 | /*! |
319 | \enum QDBusMessage::MessageType |
320 | The possible message types: |
321 | |
322 | \value MethodCallMessage a message representing an outgoing or incoming method call |
323 | \value SignalMessage a message representing an outgoing or incoming signal emission |
324 | \value ReplyMessage a message representing the return values of a method call |
325 | \value ErrorMessage a message representing an error condition in response to a method call |
326 | \value InvalidMessage an invalid message: this is never set on messages received from D-Bus |
327 | */ |
328 | |
329 | /*! |
330 | Constructs a new DBus message with the given \a path, \a interface |
331 | and \a name, representing a signal emission. |
332 | |
333 | A DBus signal is emitted from one application and is received by |
334 | all applications that are listening for that signal from that |
335 | interface. |
336 | |
337 | The QDBusMessage object that is returned can be sent using the |
338 | QDBusConnection::send() function. |
339 | */ |
340 | QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface, |
341 | const QString &name) |
342 | { |
343 | QDBusMessage message; |
344 | message.d_ptr->type = SignalMessage; |
345 | message.d_ptr->path = path; |
346 | message.d_ptr->interface = interface; |
347 | message.d_ptr->name = name; |
348 | |
349 | return message; |
350 | } |
351 | |
352 | /*! |
353 | \since 5.6 |
354 | |
355 | Constructs a new DBus message with the given \a path, \a interface |
356 | and \a name, representing a signal emission to a specific destination. |
357 | |
358 | A DBus signal is emitted from one application and is received only by |
359 | the application owning the destination \a service name. |
360 | |
361 | The QDBusMessage object that is returned can be sent using the |
362 | QDBusConnection::send() function. |
363 | */ |
364 | QDBusMessage QDBusMessage::createTargetedSignal(const QString &service, const QString &path, |
365 | const QString &interface, const QString &name) |
366 | { |
367 | QDBusMessage message; |
368 | message.d_ptr->type = SignalMessage; |
369 | message.d_ptr->service = service; |
370 | message.d_ptr->path = path; |
371 | message.d_ptr->interface = interface; |
372 | message.d_ptr->name = name; |
373 | |
374 | return message; |
375 | } |
376 | |
377 | /*! |
378 | Constructs a new DBus message representing a method call. |
379 | A method call always informs its destination address |
380 | (\a service, \a path, \a interface and \a method). |
381 | |
382 | The DBus bus allows calling a method on a given remote object without specifying the |
383 | destination interface, if the method name is unique. However, if two interfaces on the |
384 | remote object export the same method name, the result is undefined (one of the two may be |
385 | called or an error may be returned). |
386 | |
387 | When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is |
388 | optional. |
389 | |
390 | The QDBusInterface class provides a simpler abstraction to synchronous |
391 | method calling. |
392 | |
393 | This function returns a QDBusMessage object that can be sent with |
394 | QDBusConnection::call(). |
395 | */ |
396 | QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path, |
397 | const QString &interface, const QString &method) |
398 | { |
399 | QDBusMessage message; |
400 | message.d_ptr->type = MethodCallMessage; |
401 | message.d_ptr->service = service; |
402 | message.d_ptr->path = path; |
403 | message.d_ptr->interface = interface; |
404 | message.d_ptr->name = method; |
405 | |
406 | return message; |
407 | } |
408 | |
409 | /*! |
410 | Constructs a new DBus message representing an error, |
411 | with the given \a name and \a msg. |
412 | */ |
413 | QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg) |
414 | { |
415 | QDBusMessage error; |
416 | error.d_ptr->type = ErrorMessage; |
417 | error.d_ptr->name = name; |
418 | error.d_ptr->message = msg; |
419 | |
420 | return error; |
421 | } |
422 | |
423 | /*! |
424 | \fn QDBusMessage QDBusMessage::createError(const QDBusError &error) |
425 | |
426 | Constructs a new DBus message representing the given \a error. |
427 | */ |
428 | |
429 | /*! |
430 | \fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg) |
431 | |
432 | Constructs a new DBus message for the error type \a type using |
433 | the message \a msg. Returns the DBus message. |
434 | */ |
435 | |
436 | /*! |
437 | \fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const |
438 | |
439 | Constructs a new DBus message representing a reply, with the given |
440 | \a arguments. |
441 | */ |
442 | QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const |
443 | { |
444 | QDBusMessage reply; |
445 | reply.setArguments(arguments); |
446 | reply.d_ptr->type = ReplyMessage; |
447 | if (d_ptr->msg) |
448 | reply.d_ptr->reply = q_dbus_message_ref(message: d_ptr->msg); |
449 | if (d_ptr->localMessage) { |
450 | reply.d_ptr->localMessage = true; |
451 | d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy |
452 | } |
453 | |
454 | // the reply must have a msg or be a local-loop optimization |
455 | Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); |
456 | return reply; |
457 | } |
458 | |
459 | /*! |
460 | Constructs a new DBus message representing an error reply message, |
461 | with the given \a name and \a msg. |
462 | */ |
463 | QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const |
464 | { |
465 | QDBusMessage reply = QDBusMessage::createError(name, msg); |
466 | if (d_ptr->msg) |
467 | reply.d_ptr->reply = q_dbus_message_ref(message: d_ptr->msg); |
468 | if (d_ptr->localMessage) { |
469 | reply.d_ptr->localMessage = true; |
470 | d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy |
471 | } |
472 | |
473 | // the reply must have a msg or be a local-loop optimization |
474 | Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage); |
475 | return reply; |
476 | } |
477 | |
478 | /*! |
479 | Constructs a new DBus message representing a reply, with the |
480 | given \a argument. |
481 | */ |
482 | QDBusMessage QDBusMessage::createReply(const QVariant &argument) const |
483 | { |
484 | return createReply(arguments: QList{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(name: QDBusError::errorString(error: atype), msg: 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&: d_ptr, x: 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 | // Only method calls can have replies |
617 | if (d_ptr->type != QDBusMessage::MethodCallMessage) |
618 | return false; |
619 | |
620 | if (!d_ptr->msg) |
621 | return d_ptr->localMessage; // if it's a local message, reply is required |
622 | return !q_dbus_message_get_no_reply(message: d_ptr->msg); |
623 | } |
624 | |
625 | /*! |
626 | Sets whether the message will be replied later (if \a enable is |
627 | true) or if an automatic reply should be generated by Qt D-Bus |
628 | (if \a enable is false). |
629 | |
630 | In D-Bus, all method calls must generate a reply to the caller, unless the |
631 | caller explicitly indicates otherwise (see isReplyRequired()). QtDBus |
632 | automatically generates such replies for any slots being called, but it |
633 | also allows slots to indicate whether they will take responsibility |
634 | of sending the reply at a later time, after the function has finished |
635 | processing. |
636 | |
637 | \sa {Delayed Replies} |
638 | */ |
639 | void QDBusMessage::setDelayedReply(bool enable) const |
640 | { |
641 | d_ptr->delayedReply = enable; |
642 | } |
643 | |
644 | /*! |
645 | Returns the delayed reply flag, as set by setDelayedReply(). By default, this |
646 | flag is false, which means Qt D-Bus will generate automatic replies |
647 | when necessary. |
648 | */ |
649 | bool QDBusMessage::isDelayedReply() const |
650 | { |
651 | return d_ptr->delayedReply; |
652 | } |
653 | |
654 | /*! |
655 | Sets the auto start flag to \a enable. This flag only makes sense |
656 | for method call messages, where it tells the D-Bus server to |
657 | either auto start the service responsible for the service name, or |
658 | not to auto start it. |
659 | |
660 | By default this flag is true, i.e. a service is autostarted. |
661 | This means: |
662 | |
663 | When the service that this method call is sent to is already |
664 | running, the method call is sent to it. If the service is not |
665 | running yet, the D-Bus daemon is requested to autostart the |
666 | service that is assigned to this service name. This is |
667 | handled by .service files that are placed in a directory known |
668 | to the D-Bus server. These files then each contain a service |
669 | name and the path to a program that should be executed when |
670 | this service name is requested. |
671 | |
672 | \since 4.7 |
673 | */ |
674 | void QDBusMessage::setAutoStartService(bool enable) |
675 | { |
676 | d_ptr->autoStartService = enable; |
677 | } |
678 | |
679 | /*! |
680 | Returns the auto start flag, as set by setAutoStartService(). By default, this |
681 | flag is true, which means Qt D-Bus will auto start a service, if it is |
682 | not running already. |
683 | |
684 | \sa setAutoStartService() |
685 | |
686 | \since 4.7 |
687 | */ |
688 | bool QDBusMessage::autoStartService() const |
689 | { |
690 | return d_ptr->autoStartService; |
691 | } |
692 | |
693 | /*! |
694 | Sets the interactive authorization flag to \a enable. |
695 | This flag only makes sense for method call messages, where it |
696 | tells the D-Bus server that the caller of the method is prepared |
697 | to wait for interactive authorization to take place (for instance |
698 | via Polkit) before the actual method is processed. |
699 | |
700 | By default this flag is false and the other end is expected to |
701 | make any authorization decisions non-interactively and promptly. |
702 | |
703 | The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired |
704 | error indicates that authorization failed, but could have succeeded |
705 | if this flag had been set. |
706 | |
707 | \sa isInteractiveAuthorizationAllowed() |
708 | |
709 | \since 5.12 |
710 | */ |
711 | void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable) |
712 | { |
713 | d_ptr->interactiveAuthorizationAllowed = enable; |
714 | } |
715 | |
716 | /*! |
717 | Returns the interactive authorization allowed flag, as set by |
718 | setInteractiveAuthorizationAllowed(). By default this flag |
719 | is false and the other end is expected to make any authorization |
720 | decisions non-interactively and promptly. |
721 | |
722 | \sa setInteractiveAuthorizationAllowed() |
723 | |
724 | \since 5.12 |
725 | */ |
726 | bool QDBusMessage::isInteractiveAuthorizationAllowed() const |
727 | { |
728 | return d_ptr->interactiveAuthorizationAllowed; |
729 | } |
730 | |
731 | /*! |
732 | Sets the arguments that are going to be sent over D-Bus to \a arguments. Those |
733 | will be the arguments to a method call or the parameters in the signal. |
734 | |
735 | \sa arguments() |
736 | */ |
737 | void QDBusMessage::setArguments(const QList<QVariant> &arguments) |
738 | { |
739 | d_ptr->arguments = arguments; |
740 | } |
741 | |
742 | /*! |
743 | Returns the list of arguments that are going to be sent or were received from |
744 | D-Bus. |
745 | */ |
746 | QList<QVariant> QDBusMessage::arguments() const |
747 | { |
748 | return d_ptr->arguments; |
749 | } |
750 | |
751 | /*! |
752 | Appends the argument \a arg to the list of arguments to be sent over D-Bus in |
753 | a method call or signal emission. |
754 | */ |
755 | |
756 | QDBusMessage &QDBusMessage::operator<<(const QVariant &arg) |
757 | { |
758 | d_ptr->arguments.append(t: arg); |
759 | return *this; |
760 | } |
761 | |
762 | /*! |
763 | Returns the message type. |
764 | */ |
765 | QDBusMessage::MessageType QDBusMessage::type() const |
766 | { |
767 | switch (d_ptr->type) { |
768 | case DBUS_MESSAGE_TYPE_METHOD_CALL: |
769 | return MethodCallMessage; |
770 | case DBUS_MESSAGE_TYPE_METHOD_RETURN: |
771 | return ReplyMessage; |
772 | case DBUS_MESSAGE_TYPE_ERROR: |
773 | return ErrorMessage; |
774 | case DBUS_MESSAGE_TYPE_SIGNAL: |
775 | return SignalMessage; |
776 | default: |
777 | break; |
778 | } |
779 | return InvalidMessage; |
780 | } |
781 | |
782 | #ifndef QT_NO_DEBUG_STREAM |
783 | static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t) |
784 | { |
785 | switch (t) |
786 | { |
787 | case QDBusMessage::MethodCallMessage: |
788 | return dbg << "MethodCall" ; |
789 | case QDBusMessage::ReplyMessage: |
790 | return dbg << "MethodReturn" ; |
791 | case QDBusMessage::SignalMessage: |
792 | return dbg << "Signal" ; |
793 | case QDBusMessage::ErrorMessage: |
794 | return dbg << "Error" ; |
795 | default: |
796 | return dbg << "Invalid" ; |
797 | } |
798 | } |
799 | |
800 | static void debugVariantList(QDebug dbg, const QVariantList &list) |
801 | { |
802 | bool first = true; |
803 | for (const QVariant &elem : list) { |
804 | if (!first) |
805 | dbg.nospace() << ", " ; |
806 | dbg.nospace() << qPrintable(QDBusUtil::argumentToString(elem)); |
807 | first = false; |
808 | } |
809 | } |
810 | |
811 | QDebug operator<<(QDebug dbg, const QDBusMessage &msg) |
812 | { |
813 | QDebugStateSaver saver(dbg); |
814 | dbg.nospace() << "QDBusMessage(type=" << msg.type() |
815 | << ", service=" << msg.service(); |
816 | if (msg.type() == QDBusMessage::MethodCallMessage || |
817 | msg.type() == QDBusMessage::SignalMessage) |
818 | dbg.nospace() << ", path=" << msg.path() |
819 | << ", interface=" << msg.interface() |
820 | << ", member=" << msg.member(); |
821 | if (msg.type() == QDBusMessage::ErrorMessage) |
822 | dbg.nospace() << ", error name=" << msg.errorName() |
823 | << ", error message=" << msg.errorMessage(); |
824 | dbg.nospace() << ", signature=" << msg.signature() |
825 | << ", contents=(" ; |
826 | debugVariantList(dbg, list: msg.arguments()); |
827 | dbg.nospace() << ") )" ; |
828 | return dbg; |
829 | } |
830 | #endif |
831 | |
832 | /*! |
833 | \fn void QDBusMessage::swap(QDBusMessage &other) |
834 | |
835 | Swaps this QDBusMessage instance with \a other. |
836 | */ |
837 | |
838 | QT_END_NAMESPACE |
839 | |
840 | #endif // QT_NO_DBUS |
841 | |