Merge remote-tracking branch 'origin/api_changes'
[profile/ivi/qtbase.git] / src / dbus / qdbusconnection_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDBus module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 //
43 //  W A R N I N G
44 //  -------------
45 //
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
48 // removed.
49 //
50 // We mean it.
51 //
52 //
53
54 #ifndef QDBUSCONNECTION_P_H
55 #define QDBUSCONNECTION_P_H
56
57 #include <qdbuserror.h>
58 #include <qdbusconnection.h>
59
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>
69
70 #include "qdbus_symbols_p.h"
71
72 #include <qdbusmessage.h>
73
74 #ifndef QT_NO_DBUS
75
76 QT_BEGIN_NAMESPACE
77
78 class QDBusMessage;
79 class QSocketNotifier;
80 class QTimerEvent;
81 class QDBusObjectPrivate;
82 class QDBusCallDeliveryEvent;
83 class QDBusActivateObjectEvent;
84 class QMetaMethod;
85 class QDBusInterfacePrivate;
86 struct QDBusMetaObject;
87 class QDBusAbstractInterface;
88 class QDBusConnectionInterface;
89 class QDBusPendingCallPrivate;
90
91 #ifndef QT_BOOTSTRAPPED
92
93 class QDBusErrorInternal
94 {
95     mutable DBusError error;
96     Q_DISABLE_COPY(QDBusErrorInternal)
97 public:
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; }
103 };
104
105 // QDBusConnectionPrivate holds the DBusConnection and
106 // can have many QDBusConnection objects referring to it
107
108 class QDBusConnectionPrivate: public QObject
109 {
110     Q_OBJECT
111 public:
112     // structs and enums
113     enum ConnectionMode { InvalidMode, ServerMode, ClientMode, PeerMode }; // LocalMode
114
115     struct Watcher
116     {
117         Watcher(): watch(0), read(0), write(0) {}
118         DBusWatch *watch;
119         QSocketNotifier *read;
120         QSocketNotifier *write;
121     };
122
123     struct SignalHook
124     {
125         inline SignalHook() : obj(0), midx(-1) { }
126         QString service, path, signature;
127         QObject* obj;
128         int midx;
129         QVector<int> params;
130         QStringList argumentMatch;
131         QByteArray matchRule;
132     };
133
134     enum TreeNodeType {
135         Object = 0x0,
136         VirtualObject = 0x01000000
137     };
138
139     struct ObjectTreeNode
140     {
141         typedef QVector<ObjectTreeNode> DataList;
142
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; }
151
152         QString name;
153         union {
154             QObject *obj;
155             QDBusVirtualObject *treeNode;
156         };
157         int flags;
158
159         DataList children;
160     };
161
162 public:
163     // typedefs
164     typedef QMultiHash<int, Watcher> WatcherHash;
165     typedef QHash<int, DBusTimeout *> TimeoutHash;
166     typedef QList<QPair<DBusTimeout *, int> > PendingTimeoutList;
167
168     typedef QMultiHash<QString, SignalHook> SignalHookHash;
169     typedef QHash<QString, QDBusMetaObject* > MetaObjectHash;
170     typedef QHash<QByteArray, int> MatchRefCountHash;
171
172     struct WatchedServiceData {
173         WatchedServiceData() : refcount(0) {}
174         WatchedServiceData(const QString &owner, int refcount = 0)
175             : owner(owner), refcount(refcount)
176         {}
177         QString owner;
178         int refcount;
179     };
180     typedef QHash<QString, WatchedServiceData> WatchedServicesHash;
181
182 public:
183     // public methods are entry points from other objects
184     explicit QDBusConnectionPrivate(QObject *parent = 0);
185     ~QDBusConnectionPrivate();
186     void deleteYourself();
187
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();
193
194     QString getNameOwner(const QString &service);
195
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);
219
220     bool handleMessage(const QDBusMessage &msg);
221     void waitForFinished(QDBusPendingCallPrivate *pcall);
222
223     QDBusMetaObject *findMetaObject(const QString &service, const QString &path,
224                                     const QString &interface, QDBusError &error);
225
226     void postEventToThread(int action, QObject *target, QEvent *event);
227
228     inline void serverConnection(const QDBusConnection &connection)
229         { emit newServerConnection(connection); }
230
231 private:
232     void checkThread();
233     bool handleError(const QDBusErrorInternal &error);
234
235     void handleSignal(const QString &key, const QDBusMessage &msg);
236     void handleSignal(const QDBusMessage &msg);
237     void handleObjectCall(const QDBusMessage &message);
238
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);
243
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);
247
248     bool isServiceRegisteredByThread(const QString &serviceName) const;
249
250     QString getNameOwnerNoCache(const QString &service);
251
252 protected:
253     void customEvent(QEvent *e);
254     void timerEvent(QTimerEvent *e);
255
256 public slots:
257     // public slots
258     void doDispatch();
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);
263
264 private slots:
265     void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner);
266     void registerServiceNoLock(const QString &serviceName);
267     void unregisterServiceNoLock(const QString &serviceName);
268
269 signals:
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);
273
274 public:
275     QAtomicInt ref;
276     QDBusConnection::ConnectionCapabilities capabilities;
277     QString name;               // this connection's name
278     QString baseService;        // this connection's base service
279
280     ConnectionMode mode;
281
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;
286     DBusServer *server;
287     QDBusConnectionInterface *busService;
288
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;
296
297     // members accessed through a lock
298     QMutex dispatchLock;
299     QReadWriteLock lock;
300     QDBusError lastError;
301
302     QStringList serviceNames;
303     WatchedServicesHash watchedServices;
304     SignalHookHash signalHooks;
305     MatchRefCountHash matchRefCounts;
306     ObjectTreeNode rootNode;
307     MetaObjectHash cachedMetaObjects;
308
309     QMutex callDeliveryMutex;
310     QDBusCallDeliveryEvent *callDeliveryState; // protected by the callDeliveryMutex mutex
311
312 public:
313     // static methods
314     static int findSlot(QObject *obj, const QByteArray &normalizedName, QVector<int> &params);
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);
329
330     static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; }
331     static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); }
332
333     static void setSender(const QDBusConnectionPrivate *s);
334
335     friend class QDBusActivateObjectEvent;
336     friend class QDBusCallDeliveryEvent;
337 };
338
339 // in qdbusmisc.cpp
340 extern int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes);
341 #endif // QT_BOOTSTRAPPED
342 extern int qDBusParametersForMethod(const QList<QByteArray> &parameters, 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);
347
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
357
358 QT_END_NAMESPACE
359
360 #endif // QT_NO_DBUS
361 #endif