1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Copyright (C) 2016 Intel Corporation. 5 ** Contact: https://www.qt.io/licensing/ 6 ** 7 ** This file is part of the QtDBus module of the Qt Toolkit. 8 ** 9 ** $QT_BEGIN_LICENSE:LGPL$ 10 ** Commercial License Usage 11 ** Licensees holding valid commercial Qt licenses may use this file in 12 ** accordance with the commercial license agreement provided with the 13 ** Software or, alternatively, in accordance with the terms contained in 14 ** a written agreement between you and The Qt Company. For licensing terms 15 ** and conditions see https://www.qt.io/terms-conditions. For further 16 ** information use the contact form at https://www.qt.io/contact-us. 17 ** 18 ** GNU Lesser General Public License Usage 19 ** Alternatively, this file may be used under the terms of the GNU Lesser 20 ** General Public License version 3 as published by the Free Software 21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 22 ** packaging of this file. Please review the following information to 23 ** ensure the GNU Lesser General Public License version 3 requirements 24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 25 ** 26 ** GNU General Public License Usage 27 ** Alternatively, this file may be used under the terms of the GNU 28 ** General Public License version 2.0 or (at your option) the GNU General 29 ** Public license version 3 or any later version approved by the KDE Free 30 ** Qt Foundation. The licenses are as published by the Free Software 31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 32 ** included in the packaging of this file. Please review the following 33 ** information to ensure the GNU General Public License requirements will 34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 35 ** https://www.gnu.org/licenses/gpl-3.0.html. 36 ** 37 ** $QT_END_LICENSE$ 38 ** 39 ****************************************************************************/ 40 41 // 42 // W A R N I N G 43 // ------------- 44 // 45 // This file is not part of the public API. This header file may 46 // change from version to version without notice, or even be 47 // removed. 48 // 49 // We mean it. 50 // 51 // 52 53 #ifndef QDBUSCONNECTION_P_H 54 #define QDBUSCONNECTION_P_H 55 56 #include <QtDBus/private/qtdbusglobal_p.h> 57 #include <qdbuserror.h> 58 #include <qdbusconnection.h> 59 60 #include <QtCore/qatomic.h> 61 #include <QtCore/qhash.h> 62 #include <QtCore/qobject.h> 63 #include <QtCore/qpointer.h> 64 #include <QtCore/qreadwritelock.h> 65 #include <QtCore/qstringlist.h> 66 #include <QtCore/qvarlengtharray.h> 67 #include <QtCore/qvector.h> 68 69 #include "qdbus_symbols_p.h" 70 71 #include <qdbusmessage.h> 72 #include <qdbusservicewatcher.h> // for the WatchMode enum 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 class QDBusServer; 91 92 #ifndef QT_BOOTSTRAPPED 93 94 class QDBusErrorInternal 95 { 96 mutable DBusError error; Q_DISABLE_COPY_MOVE(QDBusErrorInternal)97 Q_DISABLE_COPY_MOVE(QDBusErrorInternal) 98 public: 99 inline QDBusErrorInternal() { q_dbus_error_init(&error); } ~QDBusErrorInternal()100 inline ~QDBusErrorInternal() { q_dbus_error_free(&error); } 101 inline bool operator !() const { return !q_dbus_error_is_set(&error); } 102 inline operator DBusError *() { q_dbus_error_free(&error); return &error; } QDBusError()103 inline operator QDBusError() const { QDBusError err(&error); q_dbus_error_free(&error); return err; } 104 }; 105 106 // QDBusConnectionPrivate holds the DBusConnection and 107 // can have many QDBusConnection objects referring to it 108 109 class Q_AUTOTEST_EXPORT QDBusConnectionPrivate: public QObject 110 { 111 Q_OBJECT 112 public: 113 // structs and enums 114 enum ConnectionMode { InvalidMode, ServerMode, ClientMode, PeerMode }; // LocalMode 115 116 struct Watcher 117 { WatcherWatcher118 Watcher(): watch(nullptr), read(nullptr), write(nullptr) {} 119 DBusWatch *watch; 120 QSocketNotifier *read; 121 QSocketNotifier *write; 122 }; 123 124 struct ArgMatchRules { 125 QStringList args; 126 QString arg0namespace; 127 bool operator==(const ArgMatchRules &other) const { 128 return args == other.args && 129 arg0namespace == other.arg0namespace; 130 } 131 }; 132 133 struct SignalHook 134 { SignalHookSignalHook135 inline SignalHook() : obj(nullptr), midx(-1) { } 136 QString service, path, signature; 137 QObject* obj; 138 int midx; 139 QVector<int> params; 140 ArgMatchRules argumentMatch; 141 QByteArray matchRule; 142 }; 143 144 enum TreeNodeType { 145 Object = 0x0, 146 VirtualObject = 0x01000000 147 }; 148 149 struct ObjectTreeNode 150 { 151 typedef QVector<ObjectTreeNode> DataList; 152 ObjectTreeNodeObjectTreeNode153 inline ObjectTreeNode() : obj(nullptr), flags(0) { } ObjectTreeNodeObjectTreeNode154 inline ObjectTreeNode(const QString &n) // intentionally implicit 155 : name(n), obj(nullptr), flags(0) { } 156 inline bool operator<(const QString &other) const 157 { return name < other; } 158 inline bool operator<(const QStringRef &other) const 159 { return QStringRef(&name) < other; } isActiveObjectTreeNode160 inline bool isActive() const 161 { return obj || !children.isEmpty(); } 162 163 QString name; 164 QString interfaceName; 165 union { 166 QObject *obj; 167 QDBusVirtualObject *treeNode; 168 }; 169 int flags; 170 171 DataList children; 172 }; 173 174 public: 175 // typedefs 176 typedef QMultiHash<qintptr, Watcher> WatcherHash; 177 typedef QHash<int, DBusTimeout *> TimeoutHash; 178 typedef QVector<QDBusMessage> PendingMessageList; 179 180 typedef QMultiHash<QString, SignalHook> SignalHookHash; 181 typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; 182 typedef QHash<QByteArray, int> MatchRefCountHash; 183 typedef QVector<QDBusPendingCallPrivate*> PendingCallList; 184 185 struct WatchedServiceData { WatchedServiceDataWatchedServiceData186 WatchedServiceData() : refcount(0) {} 187 WatchedServiceData(const QString &owner, int refcount = 0) ownerWatchedServiceData188 : owner(owner), refcount(refcount) 189 {} 190 QString owner; 191 int refcount; 192 }; 193 typedef QHash<QString, WatchedServiceData> WatchedServicesHash; 194 195 public: 196 // public methods are entry points from other objects 197 explicit QDBusConnectionPrivate(QObject *parent = nullptr); 198 ~QDBusConnectionPrivate(); 199 200 void createBusService(); 201 void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); 202 void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); 203 void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error); 204 void closeConnection(); 205 206 QString getNameOwner(const QString &service); 207 208 bool shouldWatchService(const QString &service); 209 void watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, 210 QObject *obj, const char *member); 211 void unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, 212 QObject *obj, const char *member); 213 214 bool send(const QDBusMessage &message); 215 QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1); 216 QDBusMessage sendWithReplyLocal(const QDBusMessage &message); 217 QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, 218 const char *returnMethod, const char *errorMethod,int timeout = -1); 219 220 bool connectSignal(const QString &service, const QString &path, const QString& interface, 221 const QString &name, const QStringList &argumentMatch, const QString &signature, 222 QObject *receiver, const char *slot); 223 bool disconnectSignal(const QString &service, const QString &path, const QString& interface, 224 const QString &name, const QStringList &argumentMatch, const QString &signature, 225 QObject *receiver, const char *slot); 226 bool connectSignal(const QString &service, const QString &path, const QString& interface, 227 const QString &name, const ArgMatchRules &argumentMatch, const QString &signature, 228 QObject *receiver, const char *slot); 229 bool disconnectSignal(const QString &service, const QString &path, const QString& interface, 230 const QString &name, const ArgMatchRules &argumentMatch, const QString &signature, 231 QObject *receiver, const char *slot); 232 void registerObject(const ObjectTreeNode *node); 233 void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode); 234 void connectRelay(const QString &service, 235 const QString &path, const QString &interface, 236 QDBusAbstractInterface *receiver, const QMetaMethod &signal); 237 void disconnectRelay(const QString &service, 238 const QString &path, const QString &interface, 239 QDBusAbstractInterface *receiver, const QMetaMethod &signal); 240 void registerService(const QString &serviceName); 241 void unregisterService(const QString &serviceName); 242 243 bool handleMessage(const QDBusMessage &msg); 244 245 QDBusMetaObject *findMetaObject(const QString &service, const QString &path, 246 const QString &interface, QDBusError &error); 247 248 void postEventToThread(int action, QObject *target, QEvent *event); 249 250 private: 251 void checkThread(); 252 bool handleError(const QDBusErrorInternal &error); 253 254 void handleSignal(const QString &key, const QDBusMessage &msg); 255 void handleSignal(const QDBusMessage &msg); 256 void handleObjectCall(const QDBusMessage &message); 257 258 void activateSignal(const SignalHook& hook, const QDBusMessage &msg); 259 void activateObject(ObjectTreeNode &node, const QDBusMessage &msg, int pathStartPos); 260 bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg); 261 bool activateCall(QObject *object, int flags, const QDBusMessage &msg); 262 263 void sendInternal(QDBusPendingCallPrivate *pcall, void *msg, int timeout); 264 void sendError(const QDBusMessage &msg, QDBusError::ErrorType code); 265 void deliverCall(QObject *object, int flags, const QDBusMessage &msg, 266 const QVector<int> &metaTypes, int slotIdx); 267 268 SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it); 269 void collectAllObjects(ObjectTreeNode &node, QSet<QObject *> &set); 270 271 bool isServiceRegisteredByThread(const QString &serviceName); 272 273 QString getNameOwnerNoCache(const QString &service); 274 275 void watchForDBusDisconnection(); 276 277 void _q_newConnection(QDBusConnectionPrivate *newConnection); 278 279 void handleAuthentication(); 280 281 protected: 282 void timerEvent(QTimerEvent *e) override; 283 284 public slots: 285 // public slots 286 void setDispatchEnabled(bool enable); 287 void doDispatch(); 288 void socketRead(qintptr); 289 void socketWrite(qintptr); 290 void objectDestroyed(QObject *o); 291 void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args); 292 bool addSignalHook(const QString &key, const SignalHook &hook); 293 bool removeSignalHook(const QString &key, const SignalHook &hook); 294 295 private slots: 296 void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner); 297 void registerServiceNoLock(const QString &serviceName); 298 void unregisterServiceNoLock(const QString &serviceName); 299 void handleDBusDisconnection(); 300 301 signals: 302 void dispatchStatusChanged(); 303 void spyHooksFinished(const QDBusMessage &msg); 304 void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1); 305 bool signalNeedsConnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook); 306 bool signalNeedsDisconnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook); 307 void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); 308 void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); 309 void newServerConnection(QDBusConnectionPrivate *newConnection); 310 311 public: 312 QAtomicInt ref; 313 QAtomicInt capabilities; connectionCapabilities()314 QDBusConnection::ConnectionCapabilities connectionCapabilities() const 315 { 316 return (QDBusConnection::ConnectionCapabilities)capabilities.loadRelaxed(); 317 } 318 QString name; // this connection's name 319 QString baseService; // this connection's base service 320 QStringList serverConnectionNames; 321 322 ConnectionMode mode; 323 union { 324 QDBusConnectionInterface *busService; 325 QDBusServer *serverObject; 326 }; 327 328 union { 329 DBusConnection *connection; 330 DBusServer *server; 331 }; 332 WatcherHash watchers; 333 TimeoutHash timeouts; 334 PendingMessageList pendingMessages; 335 336 // the master lock protects our own internal state 337 QReadWriteLock lock; 338 QDBusError lastError; 339 340 QStringList serviceNames; 341 WatchedServicesHash watchedServices; 342 SignalHookHash signalHooks; 343 MatchRefCountHash matchRefCounts; 344 ObjectTreeNode rootNode; 345 MetaObjectHash cachedMetaObjects; 346 PendingCallList pendingCalls; 347 348 bool anonymousAuthenticationAllowed; 349 bool dispatchEnabled; // protected by the dispatch lock, not the main lock 350 bool isAuthenticated; 351 352 public: 353 // static methods 354 static int findSlot(QObject *obj, const QByteArray &normalizedName, QVector<int> ¶ms); 355 static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, 356 const QString &service, 357 const QString &path, const QString &interface, const QString &name, 358 const ArgMatchRules &argMatch, 359 QObject *receiver, const char *signal, int minMIdx, 360 bool buildSignature); 361 static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *); 362 static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object, 363 int idx, const QVector<int> &metaTypes, 364 const QDBusMessage &msg); 365 static void processFinishedCall(QDBusPendingCallPrivate *call); 366 d(const QDBusConnection & q)367 static QDBusConnectionPrivate *d(const QDBusConnection& q) { return q.d; } q(QDBusConnectionPrivate * connection)368 static QDBusConnection q(QDBusConnectionPrivate *connection) { return QDBusConnection(connection); } 369 370 friend class QDBusActivateObjectEvent; 371 friend class QDBusCallDeliveryEvent; 372 friend class QDBusServer; 373 }; 374 375 // in qdbusmisc.cpp 376 extern int qDBusParametersForMethod(const QMetaMethod &mm, QVector<int> &metaTypes, QString &errorMsg); 377 #endif // QT_BOOTSTRAPPED 378 extern Q_DBUS_EXPORT int qDBusParametersForMethod(const QList<QByteArray> ¶meters, QVector<int>& metaTypes, QString &errorMsg); 379 extern Q_DBUS_EXPORT bool qDBusCheckAsyncTag(const char *tag); 380 #ifndef QT_BOOTSTRAPPED 381 extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name); 382 extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo); 383 384 // in qdbusinternalfilters.cpp 385 extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node, const QString &path); 386 extern QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node, 387 const QDBusMessage &msg); 388 extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node, 389 const QDBusMessage &msg); 390 extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node, 391 const QDBusMessage &msg); 392 393 // can be replaced with a lambda in Qt 5.7 394 class QDBusConnectionDispatchEnabler : public QObject 395 { 396 Q_OBJECT 397 QDBusConnectionPrivate *con; 398 public: QDBusConnectionDispatchEnabler(QDBusConnectionPrivate * con)399 QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {} 400 401 public slots: execute()402 void execute() 403 { 404 // This call cannot race with something disabling dispatch only because dispatch is 405 // never re-disabled from Qt code on an in-use connection once it has been enabled. 406 QMetaObject::invokeMethod(con, "setDispatchEnabled", Qt::QueuedConnection, Q_ARG(bool, true)); 407 if (!con->ref.deref()) 408 con->deleteLater(); 409 deleteLater(); 410 } 411 }; 412 413 #endif // QT_BOOTSTRAPPED 414 415 QT_END_NAMESPACE 416 417 #endif // QT_NO_DBUS 418 #endif 419