diff options
author | Øystein Heskestad <oystein.heskestad@qt.io> | 2023-07-31 17:40:29 +0200 |
---|---|---|
committer | Øystein Heskestad <oystein.heskestad@qt.io> | 2023-09-11 10:21:35 +0200 |
commit | 8ddef5b073e86eb474eb5c28f09ae1d497d03593 (patch) | |
tree | bb3ce63af1a1dcae6311a6a13f82b4832181cdf5 | |
parent | 2bdde103158b4c0220584816653eb64e5d456b0f (diff) |
Add a static method setLocalServerOptions to QRemoteObjectHost
This method must be called before a QRemoteObjectHost object using
the QLocalServer backend starts listening for it to have an effect.
It starts listening during construction when the address argument
is non-empty, otherwise when the address is set via setHostUrl().
Also added another error code QRemoteObjectNode::SocketAccessError
for when the QRemoteobjectNode is not allowed to connect to the
QRemoteObjectHost.
Fixes: QTBUG-72921
Change-Id: I4303b25dbc37d9f4d4eb2bdaeff1ef02089e6b5d
Reviewed-by: Brett Stottlemyer <bstottle@ford.com>
-rw-r--r-- | src/remoteobjects/qconnection_local_backend.cpp | 8 | ||||
-rw-r--r-- | src/remoteobjects/qconnection_local_backend_p.h | 1 | ||||
-rw-r--r-- | src/remoteobjects/qconnectionfactories.h | 3 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectnode.cpp | 31 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectnode.h | 5 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectsourceio.cpp | 14 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectsourceio_p.h | 2 | ||||
-rw-r--r-- | tests/auto/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/localserveroption/CMakeLists.txt | 14 | ||||
-rw-r--r-- | tests/auto/localserveroption/tst_localserveroption.cpp | 72 |
10 files changed, 149 insertions, 2 deletions
diff --git a/src/remoteobjects/qconnection_local_backend.cpp b/src/remoteobjects/qconnection_local_backend.cpp index 337af69..887e288 100644 --- a/src/remoteobjects/qconnection_local_backend.cpp +++ b/src/remoteobjects/qconnection_local_backend.cpp @@ -73,6 +73,9 @@ void LocalClientIo::onError(QLocalSocket::LocalSocketError error) emit shouldReconnect(this); #endif break; + case QLocalSocket::SocketAccessError: + emit setError(QRemoteObjectNode::SocketAccessError); + break; default: break; } @@ -167,6 +170,11 @@ void LocalServerImpl::close() m_server.close(); } +void LocalServerImpl::setSocketOptions(QLocalServer::SocketOptions options) +{ + m_server.setSocketOptions(options); +} + #ifdef Q_OS_LINUX AbstractLocalClientIo::AbstractLocalClientIo(QObject *parent) diff --git a/src/remoteobjects/qconnection_local_backend_p.h b/src/remoteobjects/qconnection_local_backend_p.h index 3a2cbc4..cf1a5ba 100644 --- a/src/remoteobjects/qconnection_local_backend_p.h +++ b/src/remoteobjects/qconnection_local_backend_p.h @@ -85,6 +85,7 @@ public: bool listen(const QUrl &address) override; QAbstractSocket::SocketError serverError() const override; void close() override; + void setSocketOptions(QLocalServer::SocketOptions options); protected: QLocalServer m_server; diff --git a/src/remoteobjects/qconnectionfactories.h b/src/remoteobjects/qconnectionfactories.h index b56a34f..7eabfd6 100644 --- a/src/remoteobjects/qconnectionfactories.h +++ b/src/remoteobjects/qconnectionfactories.h @@ -18,7 +18,7 @@ #include <QtNetwork/qabstractsocket.h> #include <QtRemoteObjects/qtremoteobjectglobal.h> - +#include <QtRemoteObjects/qremoteobjectnode.h> QT_BEGIN_NAMESPACE @@ -116,6 +116,7 @@ public: Q_SIGNALS: void shouldReconnect(QtROClientIoDevice*); + void setError(QRemoteObjectNode::ErrorCode); protected: virtual void doDisconnectFromServer() = 0; diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp index 3c214a8..89f1a3a 100644 --- a/src/remoteobjects/qremoteobjectnode.cpp +++ b/src/remoteobjects/qremoteobjectnode.cpp @@ -44,6 +44,7 @@ struct ManagedGadgetTypeEntry static QMutex s_managedTypesMutex; static QHash<int, ManagedGadgetTypeEntry> s_managedTypes; static QHash<int, QSet<QtROIoDeviceBase*>> s_trackedConnections; +static QLocalServer::SocketOptions s_localServerOptions = QLocalServer::NoOptions; static void GadgetsStaticMetacallFunction(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { @@ -1192,6 +1193,8 @@ bool QRemoteObjectNodePrivate::initConnection(const QUrl &address) QObject::connect(connection, &QtROIoDeviceBase::readyRead, q, [this, connection]() { onClientRead(connection); }); + connect(connection, &QtROClientIoDevice::setError, this, + &QRemoteObjectNodePrivate::setLastError); connection->connectToServer(); return true; @@ -1676,6 +1679,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj) \value HostUrlInvalid The given url has an invalid or unrecognized scheme. \value ProtocolMismatch The client and the server have different protocol versions. \value ListenFailed Can't listen on the specified host port. + \value SocketAccessError The client isn't allowed to connect to the server. Ensure that QRemoteObjectHost::setLocalServerOptions is set appropriately. */ /*! @@ -1966,6 +1970,13 @@ bool QRemoteObjectHostBasePrivate::setHostUrlBaseImpl( return false; } remoteObjectIo = new QRemoteObjectSourceIo(hostAddress, q); + QLocalServer::SocketOptions socketOptions; + { + QMutexLocker lock(&s_managedTypesMutex); + socketOptions = s_localServerOptions; + } + if (socketOptions != QLocalServer::NoOptions) + remoteObjectIo->setSocketOptions(socketOptions); if (allowedSchemas == QRemoteObjectHostBase::AllowedSchemas::BuiltInSchemasOnly && !remoteObjectIo->startListening()) { setLastError(QRemoteObjectHostBase::ListenFailed); @@ -1987,6 +1998,26 @@ bool QRemoteObjectHostBasePrivate::setHostUrlBaseImpl( } /*! + \brief Sets the socket options for QLocalServer backends to \a options. + \since 6.7 + + It must be set before the QRemoteObjectHost object starts listening. + It has no consequence for already listening QRemoteObjectHost + objects or QRemoteObjectHost objects that use different + backends than QLocalServer. QRemoteObjectHost objects start to + listen during construction if the \l address argument is + non-empty, otherwise when the address is set via setHostUrl(). + + \sa setHostUrl(), QRemoteObjectHost() + +*/ +void QRemoteObjectHost::setLocalServerOptions(QLocalServer::SocketOptions options) +{ + QMutexLocker lock(&s_managedTypesMutex); + s_localServerOptions = options; +} + +/*! \qmlproperty url Host::hostUrl The host address for the node. diff --git a/src/remoteobjects/qremoteobjectnode.h b/src/remoteobjects/qremoteobjectnode.h index 18f75bc..13e2540 100644 --- a/src/remoteobjects/qremoteobjectnode.h +++ b/src/remoteobjects/qremoteobjectnode.h @@ -6,6 +6,7 @@ #include <QtCore/qsharedpointer.h> #include <QtCore/qmetaobject.h> +#include <QtNetwork/qlocalserver.h> #include <QtRemoteObjects/qtremoteobjectglobal.h> #include <QtRemoteObjects/qremoteobjectregistry.h> #include <QtRemoteObjects/qremoteobjectdynamicreplica.h> @@ -61,7 +62,8 @@ public: MissingObjectName, HostUrlInvalid, ProtocolMismatch, - ListenFailed + ListenFailed, + SocketAccessError }; Q_ENUM(ErrorCode) @@ -181,6 +183,7 @@ public: ~QRemoteObjectHost() override; QUrl hostUrl() const override; bool setHostUrl(const QUrl &hostAddress, AllowedSchemas allowedSchemas=BuiltInSchemasOnly) override; + static void setLocalServerOptions(QLocalServer::SocketOptions options); Q_SIGNALS: void hostUrlChanged(); diff --git a/src/remoteobjects/qremoteobjectsourceio.cpp b/src/remoteobjects/qremoteobjectsourceio.cpp index 0b14999..ebc4654 100644 --- a/src/remoteobjects/qremoteobjectsourceio.cpp +++ b/src/remoteobjects/qremoteobjectsourceio.cpp @@ -8,6 +8,7 @@ #include "qremoteobjectnode_p.h" #include "qremoteobjectpendingcall.h" #include "qtremoteobjectglobal.h" +#include "qconnection_local_backend_p.h" #include <QtCore/qstringlist.h> @@ -86,6 +87,19 @@ bool QRemoteObjectSourceIo::disableRemoting(QObject *object) return true; } +void QRemoteObjectSourceIo::setSocketOptions(QLocalServer::SocketOptions options) +{ + if (!m_server.isNull()) { + LocalServerImpl *server = qobject_cast<LocalServerImpl *>(m_server.get()); + if (server != nullptr) { + server->setSocketOptions(options); + } else { + qROWarning(this) + << "Attempting to set socket options to a backend that is non-localserver"; + } + } +} + void QRemoteObjectSourceIo::registerSource(QRemoteObjectSourceBase *source) { Q_ASSERT(source); diff --git a/src/remoteobjects/qremoteobjectsourceio_p.h b/src/remoteobjects/qremoteobjectsourceio_p.h index 454579f..68ab468 100644 --- a/src/remoteobjects/qremoteobjectsourceio_p.h +++ b/src/remoteobjects/qremoteobjectsourceio_p.h @@ -21,6 +21,7 @@ #include <QtCore/qiodevice.h> #include <QtCore/qscopedpointer.h> +#include <QtNetwork/qlocalserver.h> QT_BEGIN_NAMESPACE @@ -43,6 +44,7 @@ public: bool enableRemoting(QObject *object, const SourceApiMap *api, QObject *adapter = nullptr); bool disableRemoting(QObject *object); void newConnection(QtROIoDeviceBase *conn); + void setSocketOptions(QLocalServer::SocketOptions options); QUrl serverAddress() const; diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index 720cf12..6df3e89 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -30,3 +30,4 @@ if(QT_FEATURE_process) endif() add_subdirectory(localsockettestserver) add_subdirectory(integration) +add_subdirectory(localserveroption) diff --git a/tests/auto/localserveroption/CMakeLists.txt b/tests/auto/localserveroption/CMakeLists.txt new file mode 100644 index 0000000..565f89f --- /dev/null +++ b/tests/auto/localserveroption/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +##################################################################### +## tst_localserveroption Test: +##################################################################### + +qt_internal_add_test(tst_localserveroption + SOURCES + tst_localserveroption.cpp + LIBRARIES + Qt::RemoteObjects + Qt::Core +) diff --git a/tests/auto/localserveroption/tst_localserveroption.cpp b/tests/auto/localserveroption/tst_localserveroption.cpp new file mode 100644 index 0000000..895213e --- /dev/null +++ b/tests/auto/localserveroption/tst_localserveroption.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QLocalServer> +#include <QRemoteObjectDynamicReplica> +#include <QRemoteObjectHost> +#include <QRemoteObjectNode> +#include <QTest> + +class tst_LocalServerOption : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testLocalServerOption_data(); + void testLocalServerOption(); +}; + +void tst_LocalServerOption::testLocalServerOption_data() +{ + QTest::addColumn<QLocalServer::SocketOptions>("options"); + QTest::addColumn<bool>("successExpected"); + + QTest::newRow("UserAccessOption") + << QLocalServer::SocketOptions(QLocalServer::UserAccessOption) << true; + QTest::newRow("GroupAccessOption") + << QLocalServer::SocketOptions(QLocalServer::GroupAccessOption) << false; + QTest::newRow("UserAndGroupAccessOption") << QLocalServer::SocketOptions( + QLocalServer::UserAccessOption | QLocalServer::GroupAccessOption) + << true; + QTest::newRow("OtherAccessOption") + << QLocalServer::SocketOptions(QLocalServer::OtherAccessOption) << false; + QTest::newRow("OtherAndGroupAccessOption") << QLocalServer::SocketOptions( + QLocalServer::OtherAccessOption | QLocalServer::GroupAccessOption) + << false; + QTest::newRow("UserAndGroupAndOtherAccessOption") << QLocalServer::SocketOptions( + QLocalServer::UserAccessOption | QLocalServer::GroupAccessOption + | QLocalServer::GroupAccessOption) << true; + QTest::newRow("WorldAccessOption") + << QLocalServer::SocketOptions(QLocalServer::WorldAccessOption) << true; +} + +void tst_LocalServerOption::testLocalServerOption() +{ +#ifdef Q_OS_LINUX + using namespace Qt::Literals; + QFETCH(QLocalServer::SocketOptions, options); + QFETCH(bool, successExpected); + + // Server side setup + std::unique_ptr<QObject> sourceModel = std::make_unique<QObject>(); + QRemoteObjectHost::setLocalServerOptions(options); + QRemoteObjectHost srcNode(QUrl("local:replica"_L1)); + srcNode.enableRemoting(sourceModel.get(), "RemoteModel"_L1); + + // Client side setup + QRemoteObjectNode repNode; + repNode.connectToNode(QUrl("local:replica"_L1)); + std::unique_ptr<QRemoteObjectDynamicReplica> replicaModel( + repNode.acquireDynamic("RemoteModel"_L1)); + + // Verification + QCOMPARE(replicaModel->waitForSource(1000), successExpected); + QCOMPARE(repNode.lastError(), + successExpected ? QRemoteObjectNode::NoError : QRemoteObjectNode::SocketAccessError); +#else + QSKIP("This test is only useful on Linux"); +#endif +} + +QTEST_MAIN(tst_LocalServerOption) + +#include "tst_localserveroption.moc" |