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), flags(0) { }
119 inline ObjectTreeNode(const QString &n) // intentionally implicit
120 : name(n), obj(nullptr), flags(0) { }
121 inline bool operator<(const QString &other) const
122 { return name < other; }
123 inline bool operator<(QStringView other) const
124 { return name < other; }
125 inline bool isActive() const
126 { return obj || !children.isEmpty(); }
127
128 QString name;
129 QString interfaceName;
130 union {
131 QObject *obj;
132 QDBusVirtualObject *treeNode;
133 };
134 int flags;
135
136 DataList children;
137 };
138
139public:
140 // typedefs
141 typedef QMultiHash<qintptr, Watcher> WatcherHash;
142 typedef QHash<int, DBusTimeout *> TimeoutHash;
143 typedef QList<QDBusMessage> PendingMessageList;
144
145 typedef QMultiHash<QString, SignalHook> SignalHookHash;
146 typedef QHash<QString, QDBusMetaObject* > MetaObjectHash;
147 typedef QHash<QByteArray, int> MatchRefCountHash;
148 typedef QList<QDBusPendingCallPrivate *> PendingCallList;
149
150 struct WatchedServiceData {
151 WatchedServiceData() : refcount(0) {}
152 WatchedServiceData(const QString &owner, int refcount = 0)
153 : owner(owner), refcount(refcount)
154 {}
155 QString owner;
156 int refcount;
157 };
158 typedef QHash<QString, WatchedServiceData> WatchedServicesHash;
159
160public:
161 // public methods are entry points from other objects
162 explicit QDBusConnectionPrivate(QObject *parent = nullptr);
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, int 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, int flags, const QDBusMessage &msg);
229
230 void sendInternal(QDBusPendingCallPrivate *pcall, void *msg, int timeout);
231 void sendError(const QDBusMessage &msg, QDBusError::ErrorType code);
232 void deliverCall(QObject *object, int flags, const QDBusMessage &msg,
233 const QList<QMetaType> &metaTypes, int slotIdx);
234
235 SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it);
236 void collectAllObjects(ObjectTreeNode &node, QSet<QObject *> &set);
237
238 bool isServiceRegisteredByThread(const QString &serviceName);
239
240 QString getNameOwnerNoCache(const QString &service);
241
242 void watchForDBusDisconnection();
243
244 void _q_newConnection(QDBusConnectionPrivate *newConnection);
245
246 void handleAuthentication();
247
248protected:
249 void timerEvent(QTimerEvent *e) override;
250
251public slots:
252 // public slots
253 void setDispatchEnabled(bool enable);
254 void doDispatch();
255 void socketRead(qintptr);
256 void socketWrite(qintptr);
257 void objectDestroyed(QObject *o);
258 void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args);
259 bool addSignalHook(const QString &key, const SignalHook &hook);
260 bool removeSignalHook(const QString &key, const SignalHook &hook);
261
262private slots:
263 void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner);
264 void registerServiceNoLock(const QString &serviceName);
265 void unregisterServiceNoLock(const QString &serviceName);
266 void handleDBusDisconnection();
267
268signals:
269 void dispatchStatusChanged();
270 void spyHooksFinished(const QDBusMessage &msg);
271 void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1);
272 bool signalNeedsConnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook);
273 bool signalNeedsDisconnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook);
274 void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
275 void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message);
276 void newServerConnection(QDBusConnectionPrivate *newConnection);
277
278public:
279 QAtomicInt ref;
280 QAtomicInt capabilities;
281 QDBusConnection::ConnectionCapabilities connectionCapabilities() const
282 {
283 return (QDBusConnection::ConnectionCapabilities)capabilities.loadRelaxed();
284 }
285 QString name; // this connection's name
286 QString baseService; // this connection's base service
287 QStringList serverConnectionNames;
288
289 ConnectionMode mode;
290 union {
291 QDBusConnectionInterface *busService;
292 QDBusServer *serverObject;
293 };
294
295 union {
296 DBusConnection *connection;
297 DBusServer *server;
298 };
299 WatcherHash watchers;
300 TimeoutHash timeouts;
301 PendingMessageList pendingMessages;
302
303 // the master lock protects our own internal state
304 QReadWriteLock lock;
305 QDBusError lastError;
306
307 QStringList serviceNames;
308 WatchedServicesHash watchedServices;
309 SignalHookHash signalHooks;
310 MatchRefCountHash matchRefCounts;
311 ObjectTreeNode rootNode;
312 MetaObjectHash cachedMetaObjects;
313 PendingCallList pendingCalls;
314
315 bool anonymousAuthenticationAllowed;
316 bool dispatchEnabled; // protected by the dispatch lock, not the main lock
317 bool isAuthenticated;
318
319public:
320 // static methods
321 static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<QMetaType> &params,
322 QString &errorMsg);
323 static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
324 const QString &service,
325 const QString &path, const QString &interface, const QString &name,
326 const ArgMatchRules &argMatch,
327 QObject *receiver, const char *signal, int minMIdx,
328 bool buildSignature);
329 static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
330 static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object,
331 int idx, const QList<QMetaType> &metaTypes,
332 const QDBusMessage &msg);
333 static void processFinishedCall(QDBusPendingCallPrivate *call);
334
335 static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; }
336 static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); }
337
338 friend class QDBusActivateObjectEvent;
339 friend class QDBusCallDeliveryEvent;
340 friend class QDBusServer;
341};
342
343// in qdbusmisc.cpp
344extern int qDBusParametersForMethod(const QMetaMethod &mm, QList<QMetaType> &metaTypes, QString &errorMsg);
345# endif // QT_BOOTSTRAPPED
346extern Q_DBUS_EXPORT int qDBusParametersForMethod(const QList<QByteArray> &parameters,
347 QList<QMetaType> &metaTypes, QString &errorMsg);
348extern Q_DBUS_EXPORT bool qDBusCheckAsyncTag(const char *tag);
349#ifndef QT_BOOTSTRAPPED
350extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name);
351extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo);
352
353// in qdbusinternalfilters.cpp
354extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node, const QString &path);
355extern QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node,
356 const QDBusMessage &msg);
357extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node,
358 const QDBusMessage &msg);
359extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node,
360 const QDBusMessage &msg);
361
362#endif // QT_BOOTSTRAPPED
363
364QT_END_NAMESPACE
365
366#endif // QT_NO_DBUS
367#endif
368

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