summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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
commit8ddef5b073e86eb474eb5c28f09ae1d497d03593 (patch)
treebb3ce63af1a1dcae6311a6a13f82b4832181cdf5
parent2bdde103158b4c0220584816653eb64e5d456b0f (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.cpp8
-rw-r--r--src/remoteobjects/qconnection_local_backend_p.h1
-rw-r--r--src/remoteobjects/qconnectionfactories.h3
-rw-r--r--src/remoteobjects/qremoteobjectnode.cpp31
-rw-r--r--src/remoteobjects/qremoteobjectnode.h5
-rw-r--r--src/remoteobjects/qremoteobjectsourceio.cpp14
-rw-r--r--src/remoteobjects/qremoteobjectsourceio_p.h2
-rw-r--r--tests/auto/CMakeLists.txt1
-rw-r--r--tests/auto/localserveroption/CMakeLists.txt14
-rw-r--r--tests/auto/localserveroption/tst_localserveroption.cpp72
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"