summaryrefslogtreecommitdiffstats
path: root/examples/remoteobjects
diff options
context:
space:
mode:
authorØystein Heskestad <oystein.heskestad@qt.io>2023-05-22 16:41:35 +0200
committerØystein Heskestad <oystein.heskestad@qt.io>2023-06-06 07:35:51 +0000
commit743de69538696ea14e299c32056d40851bb9fdcd (patch)
treebbe4b9197043614d8d13700afa383257ed75f081 /examples/remoteobjects
parent98522adc399e4fcd97808a0ae4c3a231d6c67739 (diff)
Revamp SSL example
The example did not work because the two applications used different rep-files to generate the remote objects. Use the same file in both applications, fix usage of case in naming, expand the documentation, and add a picture. Remove unused PresetData from rep-file. Task-number: QTBUG-112850 Pick-to: 6.5 6.6 Change-Id: Ia7aafc52d647bca9ffec12b8dd548377f20b6ce4 Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'examples/remoteobjects')
-rw-r--r--examples/remoteobjects/ssl/doc/src/ssl.qdoc69
-rw-r--r--examples/remoteobjects/ssl/sslcppclient/CMakeLists.txt33
-rw-r--r--examples/remoteobjects/ssl/sslcppclient/main.cpp33
-rw-r--r--examples/remoteobjects/ssl/sslcppclient/sslcppclient.pro7
-rw-r--r--examples/remoteobjects/ssl/sslcppclient/timemodel.rep12
-rw-r--r--examples/remoteobjects/ssl/sslserver/CMakeLists.txt23
-rw-r--r--examples/remoteobjects/ssl/sslserver/main.cpp52
-rw-r--r--examples/remoteobjects/ssl/sslserver/sslserver.cpp32
-rw-r--r--examples/remoteobjects/ssl/sslserver/sslserver.h24
-rw-r--r--examples/remoteobjects/ssl/sslserver/sslserver.pro6
-rw-r--r--examples/remoteobjects/timemodel.rep1
11 files changed, 150 insertions, 142 deletions
diff --git a/examples/remoteobjects/ssl/doc/src/ssl.qdoc b/examples/remoteobjects/ssl/doc/src/ssl.qdoc
index 90b6725..3ceeece 100644
--- a/examples/remoteobjects/ssl/doc/src/ssl.qdoc
+++ b/examples/remoteobjects/ssl/doc/src/ssl.qdoc
@@ -3,10 +3,75 @@
/*!
\example ssl
- \title QtRemoteObjects SSL Example
+ \title SSL Server and Client
\brief Setting up a secure Remote Object network using QSslSockets.
+ \examplecategory {Input/Output}
+ \meta tag {rpc,network,tls}
\ingroup qtremoteobjects-examples
Encrypting communication is critical when you need to pass data
- through a network you don't have full control over.
+ through a network you don't have full control over. The two applications
+ in this example show how to share remote objects over an SSL connection,
+ and how to access them.
+
+ \image ssl-example.webp
+
+ Both \e sslserver and \e sslcppclient use a custom root CA certificate to
+ validate each other's certificates all located in sslserver/cert.
+
+ \section1 SSL Server
+
+ The \e sslserver is configured with certificates and a private key.
+
+ \snippet ssl/sslserver/main.cpp 0
+
+ Then it creates a QRemoteObjectHost object and a QSslServer object.
+ The QSslServer object listens on port 65511. Then setHostUrl is called
+ on the QRemoteObjectHost object with the URL of the QSslServer object.
+
+ \snippet ssl/sslserver/main.cpp 1
+
+ A lambda is used to handle the errorOccurred signal by outputting the
+ error to the terminal. A second lambda is connected to the
+ pendingConnectionAvailable signal, which connects an error handler,
+ and calls addHostSideConnection on the QRemoteObjectHost object with
+ the incoming socket as argument to make the host object use the socket
+ for communication.
+
+ \snippet ssl/sslserver/main.cpp 2
+
+ Finally, a MinuteTimer object is created and enableRemoting is called on
+ the QRemoteObjectHost object with the MinuteTimer object as argument to
+ enable it to be shared.
+
+ \snippet ssl/sslserver/main.cpp 3
+
+ \section1 SSL Client
+
+ The \e sslcppclient sets the root CA certificate and then creates a
+ Tester object.
+
+ \snippet ssl/sslcppclient/main.cpp 3
+
+ In the Tester constructor a temporary QRemoteObjectNode object is
+ created, and setupConnection is used to create and configure a
+ QSslSocket object. An error handler is connected, and the QSslSocket is
+ used by the QRemoteObjectNode object by calling addClientSideConnection
+ on it.
+
+ \snippet ssl/sslcppclient/main.cpp 0
+
+ Then three QScopedPointer that are members of the Tester class are
+ connected to three replicas of MinuteTimer by using acquire on the
+ QRemoteObjectNode object. Finally QTimer::singleShot is used four times
+ to call reset after a delay.
+
+ \snippet ssl/sslcppclient/main.cpp 1
+
+ When Tester::clear is called for the first three times, one pointer is
+ checked that it is bound and then reset, for a different pointer each
+ time. When it is called for the fourth time it causes the application
+ to quit.
+
+ \snippet ssl/sslcppclient/main.cpp 2
*/
diff --git a/examples/remoteobjects/ssl/sslcppclient/CMakeLists.txt b/examples/remoteobjects/ssl/sslcppclient/CMakeLists.txt
index db39fd6..d46747d 100644
--- a/examples/remoteobjects/ssl/sslcppclient/CMakeLists.txt
+++ b/examples/remoteobjects/ssl/sslcppclient/CMakeLists.txt
@@ -2,33 +2,26 @@
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
-project(SslCppClient LANGUAGES CXX)
+project(sslcppclient LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(CMAKE_AUTOMOC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/remoteobjects/ssl/sslcppclient")
find_package(Qt6 REQUIRED COMPONENTS Core RemoteObjects)
-qt_add_executable(SslCppClient
+qt_standard_project_setup()
+
+qt_add_executable(sslcppclient
main.cpp
)
-set_target_properties(SslCppClient PROPERTIES
+set_target_properties(sslcppclient PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE FALSE
)
-target_link_libraries(SslCppClient PUBLIC
- # Remove: gui
+target_link_libraries(sslcppclient PRIVATE
Qt::Core
Qt::RemoteObjects
- Qt::RemoteObjectsPrivate
)
# Resources:
@@ -38,11 +31,9 @@ set(cert_resource_files
"../sslserver/cert/rootCA.key"
"../sslserver/cert/rootCA.pem"
"../sslserver/cert/rootCA.srl"
- "../sslserver/cert/server.crt"
- "../sslserver/cert/server.key"
)
-qt6_add_resources(SslCppClient "cert"
+qt6_add_resources(sslcppclient "cert"
PREFIX
"/sslcert"
BASE
@@ -51,12 +42,6 @@ qt6_add_resources(SslCppClient "cert"
${cert_resource_files}
)
-qt6_add_repc_replicas(SslCppClient
- timemodel.rep
-)
-
-install(TARGETS SslCppClient
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+qt6_add_repc_replicas(sslcppclient
+ ../../timemodel.rep
)
diff --git a/examples/remoteobjects/ssl/sslcppclient/main.cpp b/examples/remoteobjects/ssl/sslcppclient/main.cpp
index 9d49a12..33a3437 100644
--- a/examples/remoteobjects/ssl/sslcppclient/main.cpp
+++ b/examples/remoteobjects/ssl/sslcppclient/main.cpp
@@ -11,12 +11,13 @@
#include <QRemoteObjectNode>
-class tester : public QObject
+class Tester : public QObject
{
Q_OBJECT
public:
- tester() : QObject(nullptr)
+ Tester() : QObject(nullptr)
{
+ //! [0]
QRemoteObjectNode m_client;
auto socket = setupConnection();
connect(socket, &QSslSocket::errorOccurred,
@@ -24,35 +25,49 @@ public:
qDebug() << "QSslSocket::error" << error;
}) ;
m_client.addClientSideConnection(socket);
+ //! [0]
+ //! [1]
ptr1.reset(m_client.acquire< MinuteTimerReplica >());
ptr2.reset(m_client.acquire< MinuteTimerReplica >());
ptr3.reset(m_client.acquire< MinuteTimerReplica >());
- QTimer::singleShot(0, this, &tester::clear);
- QTimer::singleShot(1, this, &tester::clear);
- QTimer::singleShot(10000, this, &tester::clear);
- QTimer::singleShot(11000, this, &tester::clear);
+ QTimer::singleShot(0, this, &Tester::clear);
+ QTimer::singleShot(1, this, &Tester::clear);
+ QTimer::singleShot(10000, this, &Tester::clear);
+ QTimer::singleShot(11000, this, &Tester::clear);
+ //! [1]
}
public slots:
+
+ //! [2]
void clear()
{
static int i = 0;
if (i == 0) {
i++;
+ if (ptr1.isNull())
+ qCritical() << "Pointer 1 was not set";
ptr1.reset();
} else if (i == 1) {
i++;
+ if (ptr2.isNull())
+ qCritical() << "Pointer 2 was not set";
ptr2.reset();
} else if (i == 2) {
i++;
+ if (ptr3.isNull())
+ qCritical() << "Pointer 3 was not set";
ptr3.reset();
} else {
qApp->quit();
}
}
+ //! [2]
private:
- QScopedPointer<MinuteTimerReplica> ptr1, ptr2, ptr3;
+ QScopedPointer<MinuteTimerReplica> ptr1;
+ QScopedPointer<MinuteTimerReplica> ptr2;
+ QScopedPointer<MinuteTimerReplica> ptr3;
QSslSocket *setupConnection()
{
@@ -70,6 +85,7 @@ private:
}
};
+//! [3]
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
@@ -78,8 +94,9 @@ int main(int argc, char *argv[])
config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
QSslConfiguration::setDefaultConfiguration(config);
- tester t;
+ Tester t;
return a.exec();
}
+//! [3]
#include "main.moc"
diff --git a/examples/remoteobjects/ssl/sslcppclient/sslcppclient.pro b/examples/remoteobjects/ssl/sslcppclient/sslcppclient.pro
index 07fb8da..c616441 100644
--- a/examples/remoteobjects/ssl/sslcppclient/sslcppclient.pro
+++ b/examples/remoteobjects/ssl/sslcppclient/sslcppclient.pro
@@ -1,21 +1,18 @@
QT_FOR_CONFIG += network
requires(qtConfig(ssl))
-REPC_REPLICA += timemodel.rep
+REPC_REPLICA += ../../timemodel.rep
QT = remoteobjects remoteobjects-private core
QT -= gui
-TARGET = SslCppClient
+TARGET = sslcppclient
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
-OTHER_FILES += \
- timemodel.rep
-
RESOURCES += \
../sslserver/cert/cert.qrc
diff --git a/examples/remoteobjects/ssl/sslcppclient/timemodel.rep b/examples/remoteobjects/ssl/sslcppclient/timemodel.rep
deleted file mode 100644
index cbfaf24..0000000
--- a/examples/remoteobjects/ssl/sslcppclient/timemodel.rep
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <QtCore>
-
-POD PresetInfo(int presetNumber, float frequency, QString stationName)
-class MinuteTimer
-{
- PROP(int hour=1);
- PROP(int minute=51);
- SIGNAL(timeChanged());
- SIGNAL(timeChanged2(QTime t));
- SIGNAL(sendCustom(PresetInfo info));
- SLOT(void SetTimeZone(int zn));
-};
diff --git a/examples/remoteobjects/ssl/sslserver/CMakeLists.txt b/examples/remoteobjects/ssl/sslserver/CMakeLists.txt
index 4296a12..18bb7bb 100644
--- a/examples/remoteobjects/ssl/sslserver/CMakeLists.txt
+++ b/examples/remoteobjects/ssl/sslserver/CMakeLists.txt
@@ -5,37 +5,28 @@ cmake_minimum_required(VERSION 3.16)
project(sslserver LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(CMAKE_AUTOMOC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/remoteobjects/ssl/sslserver")
find_package(Qt6 REQUIRED COMPONENTS Core RemoteObjects)
+qt_standard_project_setup()
+
qt_add_executable(sslserver
main.cpp
- sslserver.cpp sslserver.h
timemodel.cpp timemodel.h
)
set_target_properties(sslserver PROPERTIES
WIN32_EXECUTABLE FALSE
- MACOSX_BUNDLE TRUE
+ MACOSX_BUNDLE FALSE
)
-target_link_libraries(sslserver PUBLIC
+target_link_libraries(sslserver PRIVATE
Qt::Core
Qt::RemoteObjects
- Qt::RemoteObjectsPrivate
)
# Resources:
set(cert_resource_files
- "cert/client.crt"
- "cert/client.key"
"cert/rootCA.key"
"cert/rootCA.pem"
"cert/rootCA.srl"
@@ -55,9 +46,3 @@ qt6_add_resources(sslserver "cert"
qt6_add_repc_sources(sslserver
../../timemodel.rep
)
-
-install(TARGETS sslserver
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/remoteobjects/ssl/sslserver/main.cpp b/examples/remoteobjects/ssl/sslserver/main.cpp
index d882d9c..8c7b593 100644
--- a/examples/remoteobjects/ssl/sslserver/main.cpp
+++ b/examples/remoteobjects/ssl/sslserver/main.cpp
@@ -5,8 +5,8 @@
#include <QCoreApplication>
#include <QSslConfiguration>
-
-#include "sslserver.h"
+#include <QSslKey>
+#include <QSslServer>
#include <QRemoteObjectHost>
/*
@@ -37,9 +37,9 @@ BOOL WINAPI WinHandler(DWORD CEvent)
{
case CTRL_C_EVENT:
SigIntHandler();
- break;
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
#endif
@@ -47,31 +47,61 @@ int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
+ //! [0]
auto config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
+ QFile certificateFile(QStringLiteral(":/sslcert/server.crt"));
+ if (certificateFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ config.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem));
+ else
+ qFatal("Could not open certificate file");
+ QFile keyFile(QStringLiteral(":/sslcert/server.key"));
+ if (keyFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ if (key.isNull())
+ qFatal("Key is not valid");
+ config.setPrivateKey(key);
+ } else {
+ qFatal("Could not open key file");
+ }
+ config.setPeerVerifyMode(QSslSocket::VerifyPeer);
QSslConfiguration::setDefaultConfiguration(config);
+ //! [0]
#if defined(Q_OS_UNIX) || defined(Q_OS_LINUX) || defined(Q_OS_QNX)
signal(SIGINT, &unix_handler);
#elif defined(Q_OS_WIN32)
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinHandler, TRUE);
#endif
+ //! [1]
QRemoteObjectHost host;
- SslServer server;
+ QSslServer server;
server.listen(QHostAddress::Any, 65511);
-
host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);
-
- QObject::connect(&server, &SslServer::encryptedSocketReady, &server, [&host](QSslSocket *socket) {
+ //! [1]
+
+ //! [2]
+ QObject::connect(&server, &QSslServer::errorOccurred,
+ [](QSslSocket *socket, QAbstractSocket::SocketError error) {
+ Q_UNUSED(socket);
+ qDebug() << "QSslServer::errorOccurred" << error;
+ });
+ QObject::connect(&server, &QSslServer::pendingConnectionAvailable, [&server, &host]() {
+ qDebug() << "New connection available";
+ QSslSocket *socket = qobject_cast<QSslSocket *>(server.nextPendingConnection());
+ Q_ASSERT(socket);
QObject::connect(socket, &QSslSocket::errorOccurred,
- socket, [](QAbstractSocket::SocketError error){
- qDebug() << "QSslSocket::error" << error;
- }) ;
+ [](QAbstractSocket::SocketError error) {
+ qDebug() << "QSslSocket::error" << error;
+ });
host.addHostSideConnection(socket);
});
+ //! [2]
+ //! [3]
MinuteTimer timer;
host.enableRemoting(&timer);
+ //! [3]
Q_UNUSED(timer)
return app.exec();
diff --git a/examples/remoteobjects/ssl/sslserver/sslserver.cpp b/examples/remoteobjects/ssl/sslserver/sslserver.cpp
deleted file mode 100644
index 98c0402..0000000
--- a/examples/remoteobjects/ssl/sslserver/sslserver.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2018 Ford Motor Company
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "sslserver.h"
-#include <QSslSocket>
-
-SslServer::SslServer(QObject *parent)
- : QTcpServer(parent)
-{}
-
-
-void SslServer::incomingConnection(qintptr socketDescriptor)
-{
- auto serverSocket = new QSslSocket;
- if (serverSocket->setSocketDescriptor(socketDescriptor)) {
- addPendingConnection(serverSocket);
- connect(serverSocket, &QSslSocket::encrypted, this, [this, serverSocket] {
- Q_EMIT encryptedSocketReady(serverSocket);
- });
- connect(serverSocket, static_cast<void (QSslSocket::*)(const QList<QSslError>&)>(&QSslSocket::sslErrors),
- this, [serverSocket](const QList<QSslError>& errors){
- qWarning() << "Error:" << serverSocket << errors;
- delete serverSocket;
- });
- serverSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
- serverSocket->setLocalCertificate(QStringLiteral(":/sslcert/server.crt"));
- serverSocket->setPrivateKey(QStringLiteral(":/sslcert/server.key"));
- serverSocket->startServerEncryption();
- } else {
- delete serverSocket;
- }
-}
diff --git a/examples/remoteobjects/ssl/sslserver/sslserver.h b/examples/remoteobjects/ssl/sslserver/sslserver.h
deleted file mode 100644
index c3ffbca..0000000
--- a/examples/remoteobjects/ssl/sslserver/sslserver.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2018 Ford Motor Company
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef SSLSERVER_H
-#define SSLSERVER_H
-
-#include <QTcpServer>
-
-QT_BEGIN_NAMESPACE
-class QSslSocket;
-QT_END_NAMESPACE
-
-class SslServer : public QTcpServer
-{
- Q_OBJECT
-public:
- SslServer(QObject *parent=nullptr);
- void incomingConnection(qintptr socketDescriptor) override;
-
-signals:
- void encryptedSocketReady(QSslSocket *socket);
-};
-
-#endif // SSLSERVER_H
diff --git a/examples/remoteobjects/ssl/sslserver/sslserver.pro b/examples/remoteobjects/ssl/sslserver/sslserver.pro
index b8081d2..7e93815 100644
--- a/examples/remoteobjects/ssl/sslserver/sslserver.pro
+++ b/examples/remoteobjects/ssl/sslserver/sslserver.pro
@@ -7,10 +7,8 @@ CONFIG += console
REPC_SOURCE += ../../timemodel.rep
QT = remoteobjects remoteobjects-private core
-SOURCES += timemodel.cpp main.cpp \
- sslserver.cpp
-HEADERS += timemodel.h \
- sslserver.h
+SOURCES += timemodel.cpp main.cpp
+HEADERS += timemodel.h
contains(QT_CONFIG, c++11): CONFIG += c++11
diff --git a/examples/remoteobjects/timemodel.rep b/examples/remoteobjects/timemodel.rep
index c07ee2c..045be06 100644
--- a/examples/remoteobjects/timemodel.rep
+++ b/examples/remoteobjects/timemodel.rep
@@ -1,7 +1,6 @@
#include <QtCore>
POD PresetInfo(int presetNumber, float frequency, QString stationName)
-POD PresetData(QList<QString> bla)
class MinuteTimer
{
PROP(int hour=1);