Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdbusreply.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qdbusreply.h"
8#include <QDebug>
9
10#ifndef QT_NO_DBUS
11
13
14using namespace Qt::StringLiterals;
15
16/*!
17 \class QDBusReply
18 \inmodule QtDBus
19 \since 4.2
20
21 \brief The QDBusReply class stores the reply for a method call to a remote object.
22
23 A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
24 reply. It contains only the first output argument or the error code and is used by
25 QDBusInterface-derived classes to allow returning the error code as the function's return
26 argument.
27
28 It can be used in the following manner:
29 \snippet code/src_qdbus_qdbusreply.cpp 0
30
31 If the remote method call cannot fail, you can skip the error checking:
32 \snippet code/src_qdbus_qdbusreply.cpp 1
33
34 However, if it does fail under those conditions, the value returned by QDBusReply<T>::value() is
35 a default-constructed value. It may be indistinguishable from a valid return value.
36
37 QDBusReply objects are used for remote calls that have no output
38 arguments or return values (i.e., they have a "void" return
39 type). Use the isValid() function to test if the reply succeeded.
40
41 \sa QDBusMessage, QDBusInterface
42*/
43
44/*!
45 \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusMessage &reply)
46 Automatically construct a QDBusReply object from the reply message \a reply, extracting the
47 first return value from it if it is a success reply.
48*/
49
50/*!
51 \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusPendingReply<T> &reply)
52 Constructs a QDBusReply object from the pending reply message, \a reply.
53*/
54
55/*!
56 \fn template <typename T> QDBusReply<T>::QDBusReply(const QDBusPendingCall &pcall)
57 Automatically construct a QDBusReply object from the asynchronous
58 pending call \a pcall. If the call isn't finished yet, QDBusReply
59 will call QDBusPendingCall::waitForFinished(), which is a blocking
60 operation.
61
62 If the return types patch, QDBusReply will extract the first
63 return argument from the reply.
64*/
65
66/*!
67 \fn template <typename T> QDBusReply<T>::QDBusReply(const QDBusError &error)
68 Constructs an error reply from the D-Bus error code given by \a error.
69*/
70
71/*!
72 \fn template <typename T> QDBusReply<T>::operator=(const QDBusError &dbusError)
73 Sets this object to contain the error code given by \a dbusError. You
74 can later access it with error().
75*/
76
77/*!
78 \fn template <typename T> QDBusReply<T>::operator=(const QDBusMessage &reply)
79
80 Makes this object contain the \a reply message. If \a reply
81 is an error message, this function will
82 copy the error code and message into this object
83
84 If \a reply is a standard reply message and contains at least
85 one parameter, it will be copied into this object, as long as it
86 is of the correct type. If it's not of the same type as this
87 QDBusError object, this function will instead set an error code
88 indicating a type mismatch.
89*/
90
91/*!
92 \fn template <typename T> QDBusReply<T>::operator=(const QDBusPendingCall &pcall)
93
94 Makes this object contain the reply specified by the pending
95 asynchronous call \a pcall. If the call is not finished yet, this
96 function will call QDBusPendingCall::waitForFinished() to block
97 until the reply arrives.
98
99 If \a pcall finishes with an error message, this function will
100 copy the error code and message into this object
101
102 If \a pcall finished with a standard reply message and contains at
103 least one parameter, it will be copied into this object, as long
104 as it is of the correct type. If it's not of the same type as this
105 QDBusError object, this function will instead set an error code
106 indicating a type mismatch.
107*/
108
109/*!
110 \fn template <typename T> bool QDBusReply<T>::isValid() const
111
112 Returns \c true if no error occurred; otherwise, returns \c false.
113
114 \sa error()
115*/
116
117/*!
118 \fn template<typename T> const QDBusError& QDBusReply<T>::error() const
119
120 Returns the error code that was returned from the remote function call. If the remote call did
121 not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
122 not be a valid error code (QDBusError::isValid() will return false).
123
124 \sa isValid()
125*/
126
127/*!
128 \fn template <typename T> Type QDBusReply<T>::value() const
129 Returns the remote function's calls return value. If the remote call returned with an error,
130 the return value of this function is undefined and may be undistinguishable from a valid return
131 value.
132
133 This function is not available if the remote call returns \c void.
134*/
135
136/*!
137 \fn template <typename T> QDBusReply<T>::operator Type() const
138 Returns the same as value().
139
140 This function is not available if the remote call returns \c void.
141*/
142
143/*!
144 \internal
145 Fills in the QDBusReply data \a error and \a data from the reply message \a reply.
146*/
147void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)
148{
149 error = QDBusError(reply);
150
151 if (error.isValid()) {
152 data = QVariant(); // clear it
153 return;
154 }
155
156 if (reply.arguments().size() >= 1 && reply.arguments().at(0).metaType() == data.metaType()) {
157 data = reply.arguments().at(0);
158 return;
159 }
160
161 const char *expectedSignature = QDBusMetaType::typeToSignature(data.metaType());
162 const char *receivedType = nullptr;
163 QByteArray receivedSignature;
164
165 if (reply.arguments().size() >= 1) {
166 if (reply.arguments().at(0).metaType() == QDBusMetaTypeId::argument()) {
167 // compare signatures instead
168 QDBusArgument arg = qvariant_cast<QDBusArgument>(reply.arguments().at(0));
169 receivedSignature = arg.currentSignature().toLatin1();
170 if (receivedSignature == expectedSignature) {
171 // matched. Demarshall it
172 QDBusMetaType::demarshall(arg, data.metaType(), data.data());
173 return;
174 }
175 } else {
176 // not an argument and doesn't match?
177 QMetaType type = reply.arguments().at(0).metaType();
178 receivedType = type.name();
179 receivedSignature = QDBusMetaType::typeToSignature(type);
180 }
181 }
182
183 // error
184 if (receivedSignature.isEmpty())
185 receivedSignature = "<empty signature>";
186 QString errorMsg;
187 if (receivedType) {
188 errorMsg = "Unexpected reply signature: got \"%1\" (%4), expected \"%2\" (%3)"_L1
189 .arg(QLatin1StringView(receivedSignature),
190 QLatin1StringView(expectedSignature),
191 QLatin1StringView(data.typeName()),
192 QLatin1StringView(receivedType));
193 } else {
194 errorMsg = "Unexpected reply signature: got \"%1\", expected \"%2\" (%3)"_L1
195 .arg(QLatin1StringView(receivedSignature),
196 QLatin1StringView(expectedSignature),
197 QLatin1StringView(data.typeName()));
198 }
199
200 error = QDBusError(QDBusError::InvalidSignature, errorMsg);
201 data = QVariant(); // clear it
202}
203
204QT_END_NAMESPACE
205
206#endif // QT_NO_DBUS
\inmodule QtDBus
void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)