1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDBus module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
46 // This file is not part of the public API. This header file may
47 // change from version to version without notice, or even be
54 #ifndef QDBUSCONNECTION_P_H
55 #define QDBUSCONNECTION_P_H
57 #include <qdbuserror.h>
58 #include <qdbusconnection.h>
60 #include <QtCore/qatomic.h>
61 #include <QtCore/qhash.h>
62 #include <QtCore/qmutex.h>
63 #include <QtCore/qobject.h>
64 #include <QtCore/qpointer.h>
65 #include <QtCore/qreadwritelock.h>
66 #include <QtCore/qstringlist.h>
67 #include <QtCore/qvarlengtharray.h>
68 #include <QtCore/qvector.h>
70 #include "qdbus_symbols_p.h"
72 #include <qdbusmessage.h>
79 class QSocketNotifier;
81 class QDBusObjectPrivate;
82 class QDBusCallDeliveryEvent;
83 class QDBusActivateObjectEvent;
85 class QDBusInterfacePrivate;
86 struct QDBusMetaObject;
87 class QDBusAbstractInterface;
88 class QDBusConnectionInterface;
89 class QDBusPendingCallPrivate;
91 #ifndef QT_BOOTSTRAPPED
93 class QDBusErrorInternal
95 mutable DBusError error;
96 Q_DISABLE_COPY(QDBusErrorInternal)
98 inline QDBusErrorInternal() { q_dbus_error_init(&error); }
99 inline ~QDBusErrorInternal() { q_dbus_error_free(&error); }
100 inline bool operator !() const { return !q_dbus_error_is_set(&error); }
101 inline operator DBusError *() { q_dbus_error_free(&error); return &error; }
102 inline operator QDBusError() const { QDBusError err(&error); q_dbus_error_free(&error); return err; }
105 // QDBusConnectionPrivate holds the DBusConnection and
106 // can have many QDBusConnection objects referring to it
108 class QDBusConnectionPrivate: public QObject
113 enum ConnectionMode { InvalidMode, ServerMode, ClientMode, PeerMode }; // LocalMode
117 Watcher(): watch(0), read(0), write(0) {}
119 QSocketNotifier *read;
120 QSocketNotifier *write;
125 inline SignalHook() : obj(0), midx(-1) { }
126 QString service, path, signature;
130 QStringList argumentMatch;
131 QByteArray matchRule;
136 VirtualObject = 0x01000000
139 struct ObjectTreeNode
141 typedef QVector<ObjectTreeNode> DataList;
143 inline ObjectTreeNode() : obj(0), flags(0) { }
144 inline ObjectTreeNode(const QString &n) // intentionally implicit
145 : name(n), obj(0), flags(0) { }
146 inline ~ObjectTreeNode() { }
147 inline bool operator<(const QString &other) const
148 { return name < other; }
149 inline bool operator<(const QStringRef &other) const
150 { return QStringRef(&name) < other; }
155 QDBusVirtualObject *treeNode;
164 typedef QMultiHash<int, Watcher> WatcherHash;
165 typedef QHash<int, DBusTimeout *> TimeoutHash;
166 typedef QList<QPair<DBusTimeout *, int> > PendingTimeoutList;
168 typedef QMultiHash<QString, SignalHook> SignalHookHash;
169 typedef QHash<QString, QDBusMetaObject* > MetaObjectHash;
170 typedef QHash<QByteArray, int> MatchRefCountHash;
172 struct WatchedServiceData {
173 WatchedServiceData() : refcount(0) {}
174 WatchedServiceData(const QString &owner, int refcount = 0)
175 : owner(owner), refcount(refcount)
180 typedef QHash<QString, WatchedServiceData> WatchedServicesHash;
183 // public methods are entry points from other objects
184 explicit QDBusConnectionPrivate(QObject *parent = 0);
185 ~QDBusConnectionPrivate();
186 void deleteYourself();
188 void setBusService(const QDBusConnection &connection);
189 void setPeer(DBusConnection *connection, const QDBusErrorInternal &error);
190 void setConnection(DBusConnection *connection, const QDBusErrorInternal &error);
191 void setServer(DBusServer *server, const QDBusErrorInternal &error);
192 void closeConnection();
194 QString getNameOwner(const QString &service);
196 int send(const QDBusMessage &message);
197 QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1);
198 QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
199 QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, int timeout = -1);
200 int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
201 const char *returnMethod, const char *errorMethod, int timeout = -1);
202 bool connectSignal(const QString &service, const QString &path, const QString& interface,
203 const QString &name, const QStringList &argumentMatch, const QString &signature,
204 QObject *receiver, const char *slot);
205 void connectSignal(const QString &key, const SignalHook &hook);
206 SignalHookHash::Iterator disconnectSignal(SignalHookHash::Iterator &it);
207 bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
208 const QString &name, const QStringList &argumentMatch, const QString &signature,
209 QObject *receiver, const char *slot);
210 void registerObject(const ObjectTreeNode *node);
211 void connectRelay(const QString &service,
212 const QString &path, const QString &interface,
213 QDBusAbstractInterface *receiver, const QMetaMethod &signal);
214 void disconnectRelay(const QString &service,
215 const QString &path, const QString &interface,
216 QDBusAbstractInterface *receiver, const QMetaMethod &signal);
217 void registerService(const QString &serviceName);
218 void unregisterService(const QString &serviceName);
220 bool handleMessage(const QDBusMessage &msg);
221 void waitForFinished(QDBusPendingCallPrivate *pcall);
223 QDBusMetaObject *findMetaObject(const QString &service, const QString &path,
224 const QString &interface, QDBusError &error);
226 void postEventToThread(int action, QObject *target, QEvent *event);
228 inline void serverConnection(const QDBusConnection &connection)
229 { emit newServerConnection(connection); }
233 bool handleError(const QDBusErrorInternal &error);
235 void handleSignal(const QString &key, const QDBusMessage &msg);
236 void handleSignal(const QDBusMessage &msg);
237 void handleObjectCall(const QDBusMessage &message);
239 void activateSignal(const SignalHook& hook, const QDBusMessage &msg);
240 void activateObject(ObjectTreeNode &node, const QDBusMessage &msg, int pathStartPos);
241 bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg);
242 bool activateCall(QObject *object, int flags, const QDBusMessage &msg);
244 void sendError(const QDBusMessage &msg, QDBusError::ErrorType code);
245 void deliverCall(QObject *object, int flags, const QDBusMessage &msg,
246 const QVector<int> &metaTypes, int slotIdx);
248 bool isServiceRegisteredByThread(const QString &serviceName) const;
250 QString getNameOwnerNoCache(const QString &service);
253 void customEvent(QEvent *e);
254 void timerEvent(QTimerEvent *e);
259 void socketRead(int);
260 void socketWrite(int);
261 void objectDestroyed(QObject *o);
262 void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args);
265 void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner);
266 void registerServiceNoLock(const QString &serviceName);
267 void unregisterServiceNoLock(const QString &serviceName);
270 void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
271 void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message);
272 void newServerConnection(const QDBusConnection &connection);
276 QDBusConnection::ConnectionCapabilities capabilities;
277 QString name; // this connection's name
278 QString baseService; // this connection's base service
282 // members accessed in unlocked mode (except for deletion)
283 // connection and server provide their own locking mechanisms
284 // busService doesn't have state to be changed
285 DBusConnection *connection;
287 QDBusConnectionInterface *busService;
289 // watchers and timeouts are accessed from any thread
290 // but the corresponding timer and QSocketNotifier must be handled
291 // only in the object's thread
292 QMutex watchAndTimeoutLock;
293 WatcherHash watchers;
294 TimeoutHash timeouts;
295 PendingTimeoutList timeoutsPendingAdd;
297 // members accessed through a lock
300 QDBusError lastError;
302 QStringList serviceNames;
303 WatchedServicesHash watchedServices;
304 SignalHookHash signalHooks;
305 MatchRefCountHash matchRefCounts;
306 ObjectTreeNode rootNode;
307 MetaObjectHash cachedMetaObjects;
309 QMutex callDeliveryMutex;
310 QDBusCallDeliveryEvent *callDeliveryState; // protected by the callDeliveryMutex mutex
314 static int findSlot(QObject *obj, const QByteArray &normalizedName, QVector<int> ¶ms);
315 static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
316 const QString &service,
317 const QString &path, const QString &interface, const QString &name,
318 const QStringList &argMatch,
319 QObject *receiver, const char *signal, int minMIdx,
320 bool buildSignature);
321 static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
322 static bool checkReplyForDelivery(QDBusConnectionPrivate *target, QObject *object,
323 int idx, const QList<int> &metaTypes,
324 const QDBusMessage &msg);
325 static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object,
326 int idx, const QVector<int> &metaTypes,
327 const QDBusMessage &msg);
328 static void processFinishedCall(QDBusPendingCallPrivate *call);
330 static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; }
331 static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); }
333 static void setSender(const QDBusConnectionPrivate *s);
335 friend class QDBusActivateObjectEvent;
336 friend class QDBusCallDeliveryEvent;
340 extern int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes);
341 #endif // QT_BOOTSTRAPPED
342 extern int qDBusParametersForMethod(const QList<QByteArray> ¶meters, QVector<int>& metaTypes);
343 extern bool qDBusCheckAsyncTag(const char *tag);
344 #ifndef QT_BOOTSTRAPPED
345 extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name);
346 extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo);
348 // in qdbusinternalfilters.cpp
349 extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node, const QString &path);
350 extern QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node,
351 const QDBusMessage &msg);
352 extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node,
353 const QDBusMessage &msg);
354 extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node,
355 const QDBusMessage &msg);
356 #endif // QT_BOOTSTRAPPED