1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtDBus module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 2.1 or version 3 as published by the Free 20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22 ** following information to ensure the GNU Lesser General Public License 23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 ** 26 ** As a special exception, The Qt Company gives you certain additional 27 ** rights. These rights are described in The Qt Company LGPL Exception 28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 ** 30 ** GNU General Public License Usage 31 ** Alternatively, this file may be used under the terms of the GNU 32 ** General Public License version 3.0 as published by the Free Software 33 ** Foundation and appearing in the file LICENSE.GPL included in the 34 ** packaging of this file. Please review the following information to 35 ** ensure the GNU General Public License version 3.0 requirements will be 36 ** met: http://www.gnu.org/copyleft/gpl.html. 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 class QDBusErrorInternal 92 { 93 mutable DBusError error; Q_DISABLE_COPY(QDBusErrorInternal)94 Q_DISABLE_COPY(QDBusErrorInternal) 95 public: 96 inline QDBusErrorInternal() { q_dbus_error_init(&error); } ~QDBusErrorInternal()97 inline ~QDBusErrorInternal() { q_dbus_error_free(&error); } 98 inline bool operator !() const { return !q_dbus_error_is_set(&error); } 99 inline operator DBusError *() { q_dbus_error_free(&error); return &error; } QDBusError()100 inline operator QDBusError() const { QDBusError err(&error); q_dbus_error_free(&error); return err; } 101 }; 102 103 // QDBusConnectionPrivate holds the DBusConnection and 104 // can have many QDBusConnection objects referring to it 105 106 class QDBusConnectionPrivate: public QObject 107 { 108 Q_OBJECT 109 public: 110 // structs and enums 111 enum ConnectionMode { InvalidMode, ServerMode, ClientMode, PeerMode }; // LocalMode 112 113 struct Watcher 114 { WatcherWatcher115 Watcher(): watch(0), read(0), write(0) {} 116 DBusWatch *watch; 117 QSocketNotifier *read; 118 QSocketNotifier *write; 119 }; 120 121 struct SignalHook 122 { SignalHookSignalHook123 inline SignalHook() : obj(0), midx(-1) { } 124 QString service, path, signature; 125 QObject* obj; 126 int midx; 127 QList<int> params; 128 QStringList argumentMatch; 129 QByteArray matchRule; 130 }; 131 132 enum TreeNodeType { 133 Object = 0x0, 134 VirtualObject = 0x01000000 135 }; 136 137 struct ObjectTreeNode 138 { 139 typedef QVector<ObjectTreeNode> DataList; 140 ObjectTreeNodeObjectTreeNode141 inline ObjectTreeNode() : obj(0), flags(0) { } ObjectTreeNodeObjectTreeNode142 inline ObjectTreeNode(const QString &n) // intentionally implicit 143 : name(n), obj(0), flags(0) { } ~ObjectTreeNodeObjectTreeNode144 inline ~ObjectTreeNode() { } 145 inline bool operator<(const QString &other) const 146 { return name < other; } 147 inline bool operator<(const QStringRef &other) const 148 { return QStringRef(&name) < other; } 149 150 QString name; 151 union { 152 QObject *obj; 153 QDBusVirtualObject *treeNode; 154 }; 155 int flags; 156 157 DataList children; 158 }; 159 160 public: 161 // typedefs 162 typedef QMultiHash<int, Watcher> WatcherHash; 163 typedef QHash<int, DBusTimeout *> TimeoutHash; 164 typedef QList<QPair<DBusTimeout *, int> > PendingTimeoutList; 165 166 typedef QMultiHash<QString, SignalHook> SignalHookHash; 167 typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; 168 typedef QHash<QByteArray, int> MatchRefCountHash; 169 170 struct WatchedServiceData { WatchedServiceDataWatchedServiceData171 WatchedServiceData() : refcount(0) {} 172 WatchedServiceData(const QString &owner, int refcount = 0) ownerWatchedServiceData173 : owner(owner), refcount(refcount) 174 {} 175 QString owner; 176 int refcount; 177 }; 178 typedef QHash<QString, WatchedServiceData> WatchedServicesHash; 179 180 public: 181 // public methods are entry points from other objects 182 explicit QDBusConnectionPrivate(QObject *parent = 0); 183 ~QDBusConnectionPrivate(); 184 void deleteYourself(); 185 186 void setBusService(const QDBusConnection &connection); 187 void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); 188 void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); 189 void setServer(DBusServer *server, const QDBusErrorInternal &error); 190 void closeConnection(); 191 192 QString getNameOwner(const QString &service); 193 194 int send(const QDBusMessage &message); 195 QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1); 196 QDBusMessage sendWithReplyLocal(const QDBusMessage &message); 197 QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, 198 const char *returnMethod, const char *errorMethod,int timeout = -1); 199 bool connectSignal(const QString &service, const QString &path, const QString& interface, 200 const QString &name, const QStringList &argumentMatch, const QString &signature, 201 QObject *receiver, const char *slot); 202 void connectSignal(const QString &key, const SignalHook &hook); 203 SignalHookHash::Iterator disconnectSignal(SignalHookHash::Iterator &it); 204 bool disconnectSignal(const QString &service, const QString &path, const QString& interface, 205 const QString &name, const QStringList &argumentMatch, const QString &signature, 206 QObject *receiver, const char *slot); 207 void registerObject(const ObjectTreeNode *node); 208 void connectRelay(const QString &service, 209 const QString &path, const QString &interface, 210 QDBusAbstractInterface *receiver, const char *signal); 211 void disconnectRelay(const QString &service, 212 const QString &path, const QString &interface, 213 QDBusAbstractInterface *receiver, const char *signal); 214 void registerService(const QString &serviceName); 215 void unregisterService(const QString &serviceName); 216 217 bool handleMessage(const QDBusMessage &msg); 218 void waitForFinished(QDBusPendingCallPrivate *pcall); 219 220 QDBusMetaObject *findMetaObject(const QString &service, const QString &path, 221 const QString &interface, QDBusError &error); 222 223 void postEventToThread(int action, QObject *target, QEvent *event); 224 serverConnection(const QDBusConnection & connection)225 inline void serverConnection(const QDBusConnection &connection) 226 { emit newServerConnection(connection); } 227 228 private: 229 void checkThread(); 230 bool handleError(const QDBusErrorInternal &error); 231 232 void handleSignal(const QString &key, const QDBusMessage &msg); 233 void handleSignal(const QDBusMessage &msg); 234 void handleObjectCall(const QDBusMessage &message); 235 236 void activateSignal(const SignalHook& hook, const QDBusMessage &msg); 237 void activateObject(ObjectTreeNode &node, const QDBusMessage &msg, int pathStartPos); 238 bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg); 239 bool activateCall(QObject *object, int flags, const QDBusMessage &msg); 240 241 void sendError(const QDBusMessage &msg, QDBusError::ErrorType code); 242 void deliverCall(QObject *object, int flags, const QDBusMessage &msg, 243 const QList<int> &metaTypes, int slotIdx); 244 245 bool isServiceRegisteredByThread(const QString &serviceName) const; 246 247 QString getNameOwnerNoCache(const QString &service); 248 249 protected: 250 void customEvent(QEvent *e); 251 void timerEvent(QTimerEvent *e); 252 253 public slots: 254 // public slots 255 void doDispatch(); 256 void socketRead(int); 257 void socketWrite(int); 258 void objectDestroyed(QObject *o); 259 void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args); 260 261 private slots: 262 void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner); 263 void registerServiceNoLock(const QString &serviceName); 264 void unregisterServiceNoLock(const QString &serviceName); 265 266 signals: 267 void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); 268 void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); 269 void newServerConnection(const QDBusConnection &connection); 270 271 public: 272 QAtomicInt ref; 273 QDBusConnection::ConnectionCapabilities capabilities; 274 QString name; // this connection's name 275 QString baseService; // this connection's base service 276 QStringList serverConnectionNames; 277 278 ConnectionMode mode; 279 280 // members accessed in unlocked mode (except for deletion) 281 // connection and server provide their own locking mechanisms 282 // busService doesn't have state to be changed 283 DBusConnection *connection; 284 DBusServer *server; 285 QDBusConnectionInterface *busService; 286 287 // watchers and timeouts are accessed from any thread 288 // but the corresponding timer and QSocketNotifier must be handled 289 // only in the object's thread 290 QMutex watchAndTimeoutLock; 291 WatcherHash watchers; 292 TimeoutHash timeouts; 293 PendingTimeoutList timeoutsPendingAdd; 294 295 // members accessed through a lock 296 QMutex dispatchLock; 297 QReadWriteLock lock; 298 QDBusError lastError; 299 300 QStringList serviceNames; 301 WatchedServicesHash watchedServices; 302 SignalHookHash signalHooks; 303 MatchRefCountHash matchRefCounts; 304 ObjectTreeNode rootNode; 305 MetaObjectHash cachedMetaObjects; 306 307 QMutex callDeliveryMutex; 308 QDBusCallDeliveryEvent *callDeliveryState; // protected by the callDeliveryMutex mutex 309 310 public: 311 // static methods 312 static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<int>& params); 313 static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, 314 const QString &service, 315 const QString &path, const QString &interface, const QString &name, 316 const QStringList &argMatch, 317 QObject *receiver, const char *signal, int minMIdx, 318 bool buildSignature); 319 static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *); 320 static bool checkReplyForDelivery(QDBusConnectionPrivate *target, QObject *object, 321 int idx, const QList<int> &metaTypes, 322 const QDBusMessage &msg); 323 static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object, 324 int idx, const QList<int> &metaTypes, 325 const QDBusMessage &msg); 326 static void processFinishedCall(QDBusPendingCallPrivate *call); 327 d(const QDBusConnection & q)328 static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; } q(QDBusConnectionPrivate * connection)329 static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); } 330 331 static void setSender(const QDBusConnectionPrivate *s); 332 333 friend class QDBusActivateObjectEvent; 334 friend class QDBusCallDeliveryEvent; 335 }; 336 337 // in qdbusmisc.cpp 338 extern int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes); 339 extern int qDBusNameToTypeId(const char *name); 340 extern bool qDBusCheckAsyncTag(const char *tag); 341 extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name); 342 extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo); 343 344 // in qdbusinternalfilters.cpp 345 extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node, const QString &path); 346 extern QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node, 347 const QDBusMessage &msg); 348 extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node, 349 const QDBusMessage &msg); 350 extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node, 351 const QDBusMessage &msg); 352 353 QT_END_NAMESPACE 354 355 #endif // QT_NO_DBUS 356 #endif 357