summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/network/network.pro3
-rw-r--r--examples/network/secureudpclient/addressdialog.cpp118
-rw-r--r--examples/network/secureudpclient/addressdialog.h87
-rw-r--r--examples/network/secureudpclient/addressdialog.ui132
-rw-r--r--examples/network/secureudpclient/association.cpp158
-rw-r--r--examples/network/secureudpclient/association.h98
-rw-r--r--examples/network/secureudpclient/main.cpp64
-rw-r--r--examples/network/secureudpclient/mainwindow.cpp181
-rw-r--r--examples/network/secureudpclient/mainwindow.h113
-rw-r--r--examples/network/secureudpclient/mainwindow.ui198
-rw-r--r--examples/network/secureudpclient/secureudpclient.pro22
11 files changed, 1173 insertions, 1 deletions
diff --git a/examples/network/network.pro b/examples/network/network.pro
index 3187c1d43e..93049014eb 100644
--- a/examples/network/network.pro
+++ b/examples/network/network.pro
@@ -32,7 +32,8 @@ qtHaveModule(widgets) {
qtConfig(openssl) {
SUBDIRS += \
securesocketclient \
- secureudpserver
+ secureudpserver \
+ secureudpclient
}
qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient
}
diff --git a/examples/network/secureudpclient/addressdialog.cpp b/examples/network/secureudpclient/addressdialog.cpp
new file mode 100644
index 0000000000..ccb58c853c
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "addressdialog.h"
+#include "ui_addressdialog.h"
+
+#include <QtCore>
+#include <QtNetwork>
+#include <QtWidgets>
+
+#include <limits>
+
+AddressDialog::AddressDialog(QWidget *parent)
+ : QDialog(parent),
+ ui(new Ui::AddressDialog)
+{
+ ui->setupUi(this);
+ setupHostSelector();
+ setupPortSelector();
+}
+
+AddressDialog::~AddressDialog()
+{
+ delete ui;
+}
+
+QString AddressDialog::remoteName() const
+{
+ if (ui->addressSelector->count())
+ return ui->addressSelector->currentText();
+ return {};
+}
+
+quint16 AddressDialog::remotePort() const
+{
+ return quint16(ui->portSelector->text().toUInt());
+}
+
+void AddressDialog::setupHostSelector()
+{
+ QString name(QHostInfo::localHostName());
+ if (!name.isEmpty()) {
+ ui->addressSelector->addItem(name);
+ const QString domain = QHostInfo::localDomainName();
+ if (!domain.isEmpty())
+ ui->addressSelector->addItem(name + QChar('.') + domain);
+ }
+
+ if (name != QStringLiteral("localhost"))
+ ui->addressSelector->addItem(QStringLiteral("localhost"));
+
+ const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
+ for (const QHostAddress &ipAddress : ipAddressesList) {
+ if (!ipAddress.isLoopback())
+ ui->addressSelector->addItem(ipAddress.toString());
+ }
+
+ ui->addressSelector->insertSeparator(ui->addressSelector->count());
+
+ for (const QHostAddress &ipAddress : ipAddressesList) {
+ if (ipAddress.isLoopback())
+ ui->addressSelector->addItem(ipAddress.toString());
+ }
+}
+
+void AddressDialog::setupPortSelector()
+{
+ ui->portSelector->setValidator(new QIntValidator(0, std::numeric_limits<quint16>::max(),
+ ui->portSelector));
+ ui->portSelector->setText(QStringLiteral("22334"));
+}
diff --git a/examples/network/secureudpclient/addressdialog.h b/examples/network/secureudpclient/addressdialog.h
new file mode 100644
index 0000000000..7c5e2e03e8
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef ADDRESSDIALOG_H
+#define ADDRESSDIALOG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+
+class AddressDialog;
+
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class AddressDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+
+ explicit AddressDialog(QWidget *parent = nullptr);
+ ~AddressDialog();
+
+ QString remoteName() const;
+ quint16 remotePort() const;
+
+private:
+
+ void setupHostSelector();
+ void setupPortSelector();
+
+ Ui::AddressDialog *ui = nullptr;
+};
+
+#endif // ADDRESSDIALOG_H
diff --git a/examples/network/secureudpclient/addressdialog.ui b/examples/network/secureudpclient/addressdialog.ui
new file mode 100644
index 0000000000..a7d9bdc253
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddressDialog</class>
+ <widget class="QDialog" name="AddressDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>143</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Host info</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Host name (server's address):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="addressSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>320</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>320</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="frame">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Server port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="portSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>320</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>320</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AddressDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AddressDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/network/secureudpclient/association.cpp b/examples/network/secureudpclient/association.cpp
new file mode 100644
index 0000000000..11f52ba96c
--- /dev/null
+++ b/examples/network/secureudpclient/association.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "association.h"
+
+QT_BEGIN_NAMESPACE
+
+DtlsAssociation::DtlsAssociation(const QHostAddress &address, quint16 port,
+ const QString &connectionName)
+ : name(connectionName),
+ crypto(QSslSocket::SslClientMode)
+{
+ auto configuration = QSslConfiguration::defaultDtlsConfiguration();
+ configuration.setPeerVerifyMode(QSslSocket::VerifyNone);
+ crypto.setRemote(address, port);
+ crypto.setDtlsConfiguration(configuration);
+
+ connect(&crypto, &QDtls::handshakeTimeout, this, &DtlsAssociation::handshakeTimeout);
+ connect(&crypto, &QDtls::pskRequired, this, &DtlsAssociation::pskRequired);
+
+ connect(&socket, &QUdpSocket::readyRead, this, &DtlsAssociation::readyRead);
+
+ pingTimer.setInterval(5000);
+ connect(&pingTimer, &QTimer::timeout, this, &DtlsAssociation::pingTimeout);
+}
+
+DtlsAssociation::~DtlsAssociation()
+{
+ if (crypto.connectionEncrypted())
+ crypto.sendShutdownAlert(&socket);
+}
+
+void DtlsAssociation::startHandshake()
+{
+ if (!crypto.doHandshake(&socket, {}))
+ emit errorMessage(name + tr(": failed to start a handshake - ") + crypto.dtlsErrorString());
+ else
+ emit infoMessage(name + tr(": starting a handshake"));
+}
+
+void DtlsAssociation::readyRead()
+{
+ QByteArray dgram(socket.pendingDatagramSize(), '\0');
+ const qint64 bytesRead = socket.readDatagram(dgram.data(), dgram.size());
+ if (bytesRead <= 0) {
+ emit warningMessage(name + tr(": spurious read notification?"));
+ return;
+ }
+
+ dgram.resize(bytesRead);
+ if (crypto.connectionEncrypted()) {
+ const QByteArray plainText = crypto.decryptDatagram(&socket, dgram);
+ if (plainText.size()) {
+ emit serverResponse(name, dgram, plainText);
+ pingTimer.start();
+ return;
+ }
+
+ if (crypto.dtlsError() == QDtlsError::RemoteClosedConnectionError) {
+ emit errorMessage(name + tr(": shutdown alert received"));
+ socket.close();
+ pingTimer.stop();
+ return;
+ }
+
+ emit warningMessage(name + tr(": zero-length datagram received?"));
+ } else {
+ if (!crypto.doHandshake(&socket, dgram)) {
+ emit errorMessage(name + tr(": handshake error - ") + crypto.dtlsErrorString());
+ return;
+ }
+ if (crypto.connectionEncrypted()) {
+ emit infoMessage(name + tr(": encrypted connection established!"));
+ pingTimer.start();
+ pingTimeout();
+ } else {
+ emit infoMessage(name + tr(": continuing with handshake ..."));
+ }
+ }
+}
+
+void DtlsAssociation::handshakeTimeout()
+{
+ emit warningMessage(name + tr(": handshake timeout, trying to re-transmit"));
+ if (!crypto.handleTimeout(&socket))
+ emit errorMessage(name + tr(": failed to re-transmit - ") + crypto.dtlsErrorString());
+}
+
+void DtlsAssociation::pskRequired(QSslPreSharedKeyAuthenticator *auth)
+{
+ Q_ASSERT(auth);
+
+ emit infoMessage(name + tr(": providing pre-shared key ..."));
+ auth->setIdentity(name.toLatin1());
+ auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
+}
+
+void DtlsAssociation::pingTimeout()
+{
+ static const QString message = QStringLiteral("I am %1, please, accept our ping %2");
+ const qint64 written = crypto.writeDatagramEncrypted(&socket, message.arg(name).arg(ping).toLatin1());
+ if (written <= 0) {
+ emit errorMessage(name + tr(": failed to send a ping - ") + crypto.dtlsErrorString());
+ pingTimer.stop();
+ return;
+ }
+
+ ++ping;
+}
+
+QT_END_NAMESPACE
diff --git a/examples/network/secureudpclient/association.h b/examples/network/secureudpclient/association.h
new file mode 100644
index 0000000000..08fc28e3ed
--- /dev/null
+++ b/examples/network/secureudpclient/association.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef ASSOCIATION_H
+#define ASSOCIATION_H
+
+#include <QtNetwork>
+#include <QtCore>
+
+QT_BEGIN_NAMESPACE
+
+class DtlsAssociation : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ DtlsAssociation(const QHostAddress &address, quint16 port,
+ const QString &connectionName);
+ ~DtlsAssociation();
+ void startHandshake();
+
+signals:
+
+ void errorMessage(const QString &message);
+ void warningMessage(const QString &message);
+ void infoMessage(const QString &message);
+ void serverResponse(const QString &clientInfo, const QByteArray &datagraam,
+ const QByteArray &plainText);
+
+private slots:
+
+ void readyRead();
+ void handshakeTimeout();
+ void pskRequired(QSslPreSharedKeyAuthenticator *auth);
+ void pingTimeout();
+
+private:
+
+ QString name;
+ QUdpSocket socket;
+ QDtls crypto;
+
+ QTimer pingTimer;
+ unsigned ping = 0;
+
+ Q_DISABLE_COPY(DtlsAssociation)
+};
+
+QT_END_NAMESPACE
+
+#endif // ASSOCIATION_H
diff --git a/examples/network/secureudpclient/main.cpp b/examples/network/secureudpclient/main.cpp
new file mode 100644
index 0000000000..2cf35878f2
--- /dev/null
+++ b/examples/network/secureudpclient/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QT_USE_NAMESPACE
+
+ QApplication app(argc, argv);
+ MainWindow window;
+ window.show();
+
+ return app.exec();
+}
diff --git a/examples/network/secureudpclient/mainwindow.cpp b/examples/network/secureudpclient/mainwindow.cpp
new file mode 100644
index 0000000000..07c614cf3a
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtNetwork>
+
+#include "addressdialog.h"
+#include "association.h"
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include <utility>
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ ui(new Ui::MainWindow),
+ nameTemplate(QStringLiteral("Alice (clone number %1)"))
+{
+ ui->setupUi(this);
+ updateUi();
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+const QString colorizer(QStringLiteral("<font color=\"%1\">%2</font><br>"));
+
+void MainWindow::addErrorMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("Crimson"), message));
+}
+
+void MainWindow::addWarningMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("DarkOrange"), message));
+}
+
+void MainWindow::addInfoMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("DarkBlue"), message));
+}
+
+void MainWindow::addServerResponse(const QString &clientInfo, const QByteArray &datagram,
+ const QByteArray &plainText)
+{
+ static const QString messageColor = QStringLiteral("DarkMagenta");
+ static const QString formatter = QStringLiteral("<br>---------------"
+ "<br>%1 received a DTLS datagram:<br> %2"
+ "<br>As plain text:<br> %3");
+
+ const QString html = formatter.arg(clientInfo, QString::fromUtf8(datagram.toHex(' ')),
+ QString::fromUtf8(plainText));
+ ui->serverMessages->insertHtml(colorizer.arg(messageColor, html));
+}
+
+void MainWindow::on_connectButton_clicked()
+{
+ if (lookupId != -1) {
+ QHostInfo::abortHostLookup(lookupId);
+ lookupId = -1;
+ port = 0;
+ updateUi();
+ return;
+ }
+
+ AddressDialog dialog;
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+
+ const QString hostName = dialog.remoteName();
+ if (hostName.isEmpty())
+ return addWarningMessage(tr("Host name or address required to connect"));
+
+ port = dialog.remotePort();
+ QHostAddress remoteAddress;
+ if (remoteAddress.setAddress(hostName))
+ return startNewConnection(remoteAddress);
+
+ addInfoMessage(tr("Looking up the host ..."));
+ lookupId = QHostInfo::lookupHost(hostName, this, SLOT(lookupFinished(QHostInfo)));
+ updateUi();
+}
+
+void MainWindow::updateUi()
+{
+ ui->connectButton->setText(lookupId == -1 ? tr("Connect ...") : tr("Cancel lookup"));
+ ui->shutdownButton->setEnabled(connections.size() != 0);
+}
+
+void MainWindow::lookupFinished(const QHostInfo &hostInfo)
+{
+ if (hostInfo.lookupId() != lookupId)
+ return;
+
+ lookupId = -1;
+ updateUi();
+
+ if (hostInfo.error() != QHostInfo::NoError) {
+ addErrorMessage(hostInfo.errorString());
+ return;
+ }
+
+ const QList<QHostAddress> foundAddresses = hostInfo.addresses();
+ if (foundAddresses.empty()) {
+ addWarningMessage(tr("Host not found"));
+ return;
+ }
+
+ const auto remoteAddress = foundAddresses.at(0);
+ addInfoMessage(tr("Connecting to: %1").arg(remoteAddress.toString()));
+ startNewConnection(remoteAddress);
+}
+
+void MainWindow::startNewConnection(const QHostAddress &address)
+{
+ AssocPtr newConnection(new DtlsAssociation(address, port, nameTemplate.arg(nextId)));
+ connect(newConnection.data(), &DtlsAssociation::errorMessage, this, &MainWindow::addErrorMessage);
+ connect(newConnection.data(), &DtlsAssociation::warningMessage, this, &MainWindow::addWarningMessage);
+ connect(newConnection.data(), &DtlsAssociation::infoMessage, this, &MainWindow::addInfoMessage);
+ connect(newConnection.data(), &DtlsAssociation::serverResponse, this, &MainWindow::addServerResponse);
+ connections.push_back(std::move(newConnection));
+ connections.back()->startHandshake();
+ updateUi();
+
+ ++nextId;
+}
+
+void MainWindow::on_shutdownButton_clicked()
+{
+ connections.clear();
+ updateUi();
+}
diff --git a/examples/network/secureudpclient/mainwindow.h b/examples/network/secureudpclient/mainwindow.h
new file mode 100644
index 0000000000..b231b44627
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QSharedPointer>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+
+class MainWindow;
+
+}
+
+class QHostAddress;
+class QHostInfo;
+
+class DtlsAssociation;
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+
+ explicit MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+
+private slots:
+
+ void addErrorMessage(const QString &message);
+ void addWarningMessage(const QString &message);
+ void addInfoMessage(const QString &message);
+ void addServerResponse(const QString &clientInfo, const QByteArray &datagram,
+ const QByteArray &plainText);
+
+ void on_connectButton_clicked();
+ void on_shutdownButton_clicked();
+
+ void lookupFinished(const QHostInfo &hostInfo);
+
+private:
+
+ void updateUi();
+ void startNewConnection(const QHostAddress &address);
+
+ Ui::MainWindow *ui = nullptr;
+
+ using AssocPtr = QSharedPointer<DtlsAssociation>;
+ QVector<AssocPtr> connections;
+
+ QString nameTemplate;
+ unsigned nextId = 0;
+
+ quint16 port = 0;
+ int lookupId = -1;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/network/secureudpclient/mainwindow.ui b/examples/network/secureudpclient/mainwindow.ui
new file mode 100644
index 0000000000..59a31974ee
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1200</width>
+ <height>550</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>1200</width>
+ <height>550</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>1200</width>
+ <height>550</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>DTLS client</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>590</width>
+ <height>400</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>DTLS info messages:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="clientMessages">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>570</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>570</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>570</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="connectButton">
+ <property name="text">
+ <string>Connect ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="shutdownButton">
+ <property name="text">
+ <string>Shutdown connections</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="minimumSize">
+ <size>
+ <width>580</width>
+ <height>490</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>580</width>
+ <height>490</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Received datagrams:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="serverMessages">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>560</width>
+ <height>450</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>560</width>
+ <height>450</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>560</width>
+ <height>450</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1200</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/network/secureudpclient/secureudpclient.pro b/examples/network/secureudpclient/secureudpclient.pro
new file mode 100644
index 0000000000..44e4200994
--- /dev/null
+++ b/examples/network/secureudpclient/secureudpclient.pro
@@ -0,0 +1,22 @@
+QT += widgets network
+
+TARGET = secureudpclient
+TEMPLATE = app
+
+SOURCES += \
+ main.cpp \
+ association.cpp \
+ mainwindow.cpp \
+ addressdialog.cpp
+
+HEADERS += \
+ association.h \
+ mainwindow.h \
+ addressdialog.h
+
+FORMS += \
+ mainwindow.ui \
+ addressdialog.ui
+
+target.path = $$[QT_INSTALL_EXAMPLES]/network/secureudpclient
+INSTALLS += target