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//
6// W A R N I N G
7// -------------
8//
9// This file is not part of the public API. This header file may
10// change from version to version without notice, or even be
11// removed.
12//
13// We mean it.
14//
15//
16
17#ifndef QDBUSCONNECTION_P_H
18#define QDBUSCONNECTION_P_H
19
20#include <QtDBus/private/qtdbusglobal_p.h>
21#include <qdbuserror.h>
22#include <qdbusconnection.h>
23
24#include <QtCore/qatomic.h>
25#include <QtCore/qhash.h>
26#include <QtCore/qlist.h>
27#include <QtCore/qobject.h>
28#include <QtCore/qpointer.h>
29#include <QtCore/qreadwritelock.h>
30#include <QtCore/qstringlist.h>
31#include <QtCore/qvarlengtharray.h>
32
33#include "qdbus_symbols_p.h"
34
35#include <qdbusmessage.h>
36#include <qdbusservicewatcher.h> // for the WatchMode enum
37Q_MOC_INCLUDE(<QtDBus/private/qdbuspendingcall_p.h>)
38
39#ifndef QT_NO_DBUS
40
41QT_BEGIN_NAMESPACE
42
43class QDBusMessage;
44class QSocketNotifier;
45class QTimerEvent;
46class QDBusObjectPrivate;
47class QDBusCallDeliveryEvent;
48class QDBusActivateObjectEvent;
49class QMetaMethod;
50class QDBusInterfacePrivate;
51struct QDBusMetaObject;
52class QDBusAbstractInterface;
53class QDBusConnectionInterface;
54class QDBusPendingCallPrivate;
55class QDBusServer;
56
57#ifndef QT_BOOTSTRAPPED
58
59class QDBusErrorInternal
60{
61 mutable DBusError error;
62 Q_DISABLE_COPY_MOVE(QDBusErrorInternal)
63public:
64 inline QDBusErrorInternal() { q_dbus_error_init(error: &error); }
65 inline ~QDBusErrorInternal() { q_dbus_error_free(error: &error); }
66 inline bool operator !() const { return !q_dbus_error_is_set(error: &error); }
67 inline operator DBusError *() { q_dbus_error_free(error: &error); return &error; }
68 inline operator QDBusError() const { QDBusError err(&error); q_dbus_error_free(error: &error); return err; }
69};
70
71// QDBusConnectionPrivate holds the DBusConnection and
72// can have many QDBusConnection objects referring to it
73
74class Q_AUTOTEST_EXPORT QDBusConnectionPrivate: public QObject
75{
76 Q_OBJECT
77public:
78 // structs and enums
79 enum ConnectionMode { InvalidMode, ServerMode, ClientMode, PeerMode }; // LocalMode
80
81 struct Watcher
82 {
83 Watcher(): watch(nullptr), read(nullptr), write(nullptr) {}
84 DBusWatch *watch;
85 QSocketNotifier *read;
86 QSocketNotifier *write;
87 };
88
89 struct ArgMatchRules {
90 QStringList args;
91 QString arg0namespace;
92 bool operator==(const ArgMatchRules &other) const {
93 return args == other.args &&
94 arg0namespace == other.arg0namespace;
95 }
96 };
97
98 struct SignalHook
99 {
100 inline SignalHook() : obj(nullptr), midx(-1) { }
101 QString service, path, signature;
102 QObject* obj;
103 int midx;
104 QList<QMetaType> params;
105 ArgMatchRules argumentMatch;
106 QByteArray matchRule;
107 };
108
109 enum TreeNodeType {
110 Object = 0x0,
111 VirtualObject = 0x01000000
112 };
113
114 struct ObjectTreeNode
115 {
116 typedef QList<ObjectTreeNode> DataList;
117
118 inline ObjectTreeNode() : obj(nullptr) { }
119 inline ObjectTreeNode(const QString &n) // intentionally implicit
120 : name(n), obj(nullptr)
121 {
122 }
123 inline bool operator<(const QString &other) const
124 { return name < other; }
125 inline bool operator<(QStringView other) const
126 { return name < other; }
127 inline bool isActive() const
128 { return obj || !children.isEmpty(); }
129
130 QString name;
131 QString interfaceName;
132 union {
133 QObject *obj;
134 QDBusVirtualObject *treeNode;
135 };
136 QDBusConnection::RegisterOptions flags;
137
138 DataList children;
139 };
140
141 // typedefs
142 typedef QMultiHash<qintptr, Watcher> WatcherHash;
143 typedef QHash<int, DBusTimeout *> TimeoutHash;
144 typedef QList<QDBusMessage> PendingMessageList;
145
146 typedef QMultiHash<QString, SignalHook> SignalHookHash;
147 typedef QHash<QString, QDBusMetaObject* > MetaObjectHash;
148 typedef QHash<QByteArray, int> MatchRefCountHash;
149 typedef QList<QDBusPendingCallPrivate *> PendingCallList;
150
151 struct WatchedServiceData {
152 WatchedServiceData() : refcount(0) {}
153 WatchedServiceData(const QString &owner, int refcount = 0)
154 : owner(owner), refcount(refcount)
155 {}
156 QString owner;
157 int refcount;
158 };
159 typedef QHash<QString, WatchedServiceData> WatchedServicesHash;
160
161 // public methods are entry points from other objects
162 QDBusConnectionPrivate();
163 ~QDBusConnectionPrivate();
164
165 void createBusService();
166 void setPeer(DBusConnection *connection, const QDBusErrorInternal &error);
167 void setConnection(DBusConnection *connection, const QDBusErrorInternal &error);
168 void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error);
169 void closeConnection();
170
171 QString getNameOwner(const QString &service);
172
173 bool shouldWatchService(const QString &service);
174 void watchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
175 QObject *obj, const char *member);
176 void unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
177 QObject *obj, const char *member);
178
179 bool send(const QDBusMessage &message);
180 QDBusMessage sendWithReply(const QDBusMessage &message, QDBus::CallMode mode, int timeout = -1);
181 QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
182 QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
183 const char *returnMethod, const char *errorMethod,int timeout = -1);
184
185 bool connectSignal(const QString &service, const QString &path, const QString& interface,
186 const QString &name, const QStringList &argumentMatch, const QString &signature,
187 QObject *receiver, const char *slot);
188 bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
189 const QString &name, const QStringList &argumentMatch, const QString &signature,
190 QObject *receiver, const char *slot);
191 bool connectSignal(const QString &service, const QString &path, const QString& interface,
192 const QString &name, const ArgMatchRules &argumentMatch, const QString &signature,
193 QObject *receiver, const char *slot);
194 bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
195 const QString &name, const ArgMatchRules &argumentMatch, const QString &signature,
196 QObject *receiver, const char *slot);
197 void registerObject(const ObjectTreeNode *node);
198 void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode);
199 void connectRelay(const QString &service,
200 const QString &path, const QString &interface,
201 QDBusAbstractInterface *receiver, const QMetaMethod &signal);
202 void disconnectRelay(const QString &service,
203 const QString &path, const QString &interface,
204 QDBusAbstractInterface *receiver, const QMetaMethod &signal);
205 void registerService(const QString &serviceName);
206 void unregisterService(const QString &serviceName);
207
208 bool handleMessage(const QDBusMessage &msg);
209
210 QDBusMetaObject *findMetaObject(const QString &service, const QString &path,
211 const QString &interface, QDBusError &error);
212
213 void postEventToThread(int action, QObject *target, QEvent *event);
214
215 void enableDispatchDelayed(QObject *context);
216
217private:
218 void checkThread();
219 bool handleError(const QDBusErrorInternal &error);
220
221 void handleSignal(const QString &key, const QDBusMessage &msg);
222 void handleSignal(const QDBusMessage &msg);
223 void handleObjectCall(const QDBusMessage &message);
224
225 void activateSignal(const SignalHook& hook, const QDBusMessage &msg);
226 void activateObject(ObjectTreeNode &node, const QDBusMessage &msg, int pathStartPos);
227 bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg);
228 bool activateCall(QObject *object, QDBusConnection::RegisterOptions flags,
229 const QDBusMessage &msg);
230
231 void sendInternal(QDBusPendingCallPrivate *pcall, void *msg, int timeout);
232 void sendError(const QDBusMessage &msg, QDBusError::ErrorType code);
233 void deliverCall(QObject *object, const QDBusMessage &msg, const QList<QMetaType> &metaTypes,
234 int slotIdx);
235
236 SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it);
237 void collectAllObjects(ObjectTreeNode &node, QSet<QObject *> &set);
238
239 bool isServiceRegisteredByThread(const QString &serviceName);
240
241 QString getNameOwnerNoCache(const QString &service);
242
243 void watchForDBusDisconnection();
244
245 void handleAuthentication();
246
247 bool addSignalHook(const QString &key, const SignalHook &hook);
248 bool removeSignalHook(const QString &key, const SignalHook &hook);
249
250 bool addSignalHookImpl(const QString &key, const SignalHook &hook);
251 bool removeSignalHookImpl(const QString &key, const SignalHook &hook);
252
253protected:
254 void timerEvent(QTimerEvent *e) override;
255
256public slots:
257 // public slots
258 void setDispatchEnabled(bool enable);
259 void doDispatch();
260 void socketRead(qintptr);
261 void socketWrite(qintptr);
262 void objectDestroyed(QObject *o);
263 void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args);
264
265private slots:
266 void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner);
267 void registerServiceNoLock(const QString &serviceName);
268 void unregisterServiceNoLock(const QString &serviceName);
269 void handleDBusDisconnection();
270
271signals:
272 void dispatchStatusChanged();
273 void spyHooksFinished(const QDBusMessage &msg);
274 void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1);
275 void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
276 void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message);
277
278public:
279 static constexpr QDBusConnection::ConnectionCapabilities ConnectionIsBus =
280 QDBusConnection::ConnectionCapabilities::fromInt(i: 0x8000'0000);
281 static constexpr QDBusConnection::ConnectionCapabilities InternalCapabilitiesMask = ConnectionIsBus;
282
283 QAtomicInt ref;
284 QAtomicInt capabilities;
285 QDBusConnection::ConnectionCapabilities connectionCapabilities() const
286 {
287 uint capa = capabilities.loadRelaxed();
288 if (mode == ClientMode)
289 capa |= ConnectionIsBus;
290 return QDBusConnection::ConnectionCapabilities(capa);
291 }
292 QString name; // this connection's name
293 QString baseService; // this connection's base service
294 QStringList serverConnectionNames;
295
296 ConnectionMode mode;
297 union {
298 QDBusConnectionInterface *busService;
299 QDBusServer *serverObject;
300 };
301
302 union {
303 DBusConnection *connection;
304 DBusServer *server;
305 };
306 WatcherHash watchers;
307 TimeoutHash timeouts;
308 PendingMessageList pendingMessages;
309
310 // the master lock protects our own internal state
311 QReadWriteLock lock;
312 QDBusError lastError;
313
314 QStringList serviceNames;
315 WatchedServicesHash watchedServices;
316 SignalHookHash signalHooks;
317 MatchRefCountHash matchRefCounts;
318 ObjectTreeNode rootNode;
319 MetaObjectHash cachedMetaObjects;
320 PendingCallList pendingCalls;
321
322 bool anonymousAuthenticationAllowed;
323 bool dispatchEnabled; // protected by the dispatch lock, not the main lock
324 bool isAuthenticated;
325
326 // static methods
327 static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<QMetaType> &params,
328 QString &errorMsg);
329 static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
330 const QString &service, const QString &path, const QString &interface,
331 const QString &name, const ArgMatchRules &argMatch, QObject *receiver,
332 const char *signal, int minMIdx, bool buildSignature,
333 QString &errorMsg);
334 static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object,
335 int idx, const QList<QMetaType> &metaTypes,
336 const QDBusMessage &msg);
337 static void processFinishedCall(QDBusPendingCallPrivate *call);
338
339 static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; }
340 static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); }
341
342 friend class QDBusActivateObjectEvent;
343 friend class QDBusCallDeliveryEvent;
344 friend class QDBusServer;
345};
346
347// in qdbusmisc.cpp
348extern int qDBusParametersForMethod(const QMetaMethod &mm, QList<QMetaType> &metaTypes, QString &errorMsg);
349# endif // QT_BOOTSTRAPPED
350extern Q_DBUS_EXPORT int qDBusParametersForMethod(const QList<QByteArray> &parameters,
351 QList<QMetaType> &metaTypes, QString &errorMsg);
352extern Q_DBUS_EXPORT bool qDBusCheckAsyncTag(const char *tag);
353#ifndef QT_BOOTSTRAPPED
354extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name);
355extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo);
356
357// in qdbusinternalfilters.cpp
358extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node, const QString &path);
359extern QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node,
360 const QDBusMessage &msg);
361extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node,
362 const QDBusMessage &msg);
363extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node,
364 const QDBusMessage &msg);
365
366#endif // QT_BOOTSTRAPPED
367
368QT_END_NAMESPACE
369
370#endif // QT_NO_DBUS
371#endif
372

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/dbus/qdbusconnection_p.h