qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

@ -0,0 +1,40 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(secureudpclient LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/network/secureudpclient")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Network Widgets)
qt_standard_project_setup()
qt_add_executable(secureudpclient
addressdialog.cpp addressdialog.h addressdialog.ui
association.cpp association.h
main.cpp
mainwindow.cpp mainwindow.h mainwindow.ui
)
set_target_properties(secureudpclient PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(secureudpclient PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Network
Qt6::Widgets
)
install(TARGETS secureudpclient
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,71 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#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"));
}

View File

@ -0,0 +1,32 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef ADDRESSDIALOG_H
#define ADDRESSDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui {
class AddressDialog;
}
QT_END_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

View File

@ -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>

View File

@ -0,0 +1,151 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "association.h"
DtlsAssociation::DtlsAssociation(const QHostAddress &address, quint16 port,
const QString &connectionName)
: name(connectionName),
crypto(QSslSocket::SslClientMode)
{
//! [1]
auto configuration = QSslConfiguration::defaultDtlsConfiguration();
configuration.setPeerVerifyMode(QSslSocket::VerifyNone);
crypto.setPeer(address, port);
crypto.setDtlsConfiguration(configuration);
//! [1]
//! [2]
connect(&crypto, &QDtls::handshakeTimeout, this, &DtlsAssociation::handshakeTimeout);
//! [2]
connect(&crypto, &QDtls::pskRequired, this, &DtlsAssociation::pskRequired);
//! [3]
socket.connectToHost(address.toString(), port);
//! [3]
//! [13]
connect(&socket, &QUdpSocket::readyRead, this, &DtlsAssociation::readyRead);
//! [13]
//! [4]
pingTimer.setInterval(5000);
connect(&pingTimer, &QTimer::timeout, this, &DtlsAssociation::pingTimeout);
//! [4]
}
//! [12]
DtlsAssociation::~DtlsAssociation()
{
if (crypto.isConnectionEncrypted())
crypto.shutdown(&socket);
}
//! [12]
//! [5]
void DtlsAssociation::startHandshake()
{
if (socket.state() != QAbstractSocket::ConnectedState) {
emit infoMessage(tr("%1: connecting UDP socket first ...").arg(name));
connect(&socket, &QAbstractSocket::connected, this, &DtlsAssociation::udpSocketConnected);
return;
}
if (!crypto.doHandshake(&socket))
emit errorMessage(tr("%1: failed to start a handshake - %2").arg(name, crypto.dtlsErrorString()));
else
emit infoMessage(tr("%1: starting a handshake").arg(name));
}
//! [5]
void DtlsAssociation::udpSocketConnected()
{
emit infoMessage(tr("%1: UDP socket is now in ConnectedState, continue with handshake ...").arg(name));
startHandshake();
}
void DtlsAssociation::readyRead()
{
if (socket.pendingDatagramSize() <= 0) {
emit warningMessage(tr("%1: spurious read notification?").arg(name));
return;
}
//! [6]
QByteArray dgram(socket.pendingDatagramSize(), Qt::Uninitialized);
const qint64 bytesRead = socket.readDatagram(dgram.data(), dgram.size());
if (bytesRead <= 0) {
emit warningMessage(tr("%1: spurious read notification?").arg(name));
return;
}
dgram.resize(bytesRead);
//! [6]
//! [7]
if (crypto.isConnectionEncrypted()) {
const QByteArray plainText = crypto.decryptDatagram(&socket, dgram);
if (plainText.size()) {
emit serverResponse(name, dgram, plainText);
return;
}
if (crypto.dtlsError() == QDtlsError::RemoteClosedConnectionError) {
emit errorMessage(tr("%1: shutdown alert received").arg(name));
socket.close();
pingTimer.stop();
return;
}
emit warningMessage(tr("%1: zero-length datagram received?").arg(name));
} else {
//! [7]
//! [8]
if (!crypto.doHandshake(&socket, dgram)) {
emit errorMessage(tr("%1: handshake error - %2").arg(name, crypto.dtlsErrorString()));
return;
}
//! [8]
//! [9]
if (crypto.isConnectionEncrypted()) {
emit infoMessage(tr("%1: encrypted connection established!").arg(name));
pingTimer.start();
pingTimeout();
} else {
//! [9]
emit infoMessage(tr("%1: continuing with handshake ...").arg(name));
}
}
}
//! [11]
void DtlsAssociation::handshakeTimeout()
{
emit warningMessage(tr("%1: handshake timeout, trying to re-transmit").arg(name));
if (!crypto.handleTimeout(&socket))
emit errorMessage(tr("%1: failed to re-transmit - %2").arg(name, crypto.dtlsErrorString()));
}
//! [11]
//! [14]
void DtlsAssociation::pskRequired(QSslPreSharedKeyAuthenticator *auth)
{
Q_ASSERT(auth);
emit infoMessage(tr("%1: providing pre-shared key ...").arg(name));
auth->setIdentity(name.toLatin1());
auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
}
//! [14]
//! [10]
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(tr("%1: failed to send a ping - %2").arg(name, crypto.dtlsErrorString()));
pingTimer.stop();
return;
}
++ping;
}
//! [10]

View File

@ -0,0 +1,46 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef ASSOCIATION_H
#define ASSOCIATION_H
#include <QtNetwork>
#include <QtCore>
//! [0]
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 udpSocketConnected();
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)
};
//! [0]
#endif // ASSOCIATION_H

View File

@ -0,0 +1,15 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}

View File

@ -0,0 +1,138 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#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;
}
//! [0]
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));
}
//! [0]
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();
}

View File

@ -0,0 +1,58 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSharedPointer>
#include <QList>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
class QHostAddress;
class QHostInfo;
QT_END_NAMESPACE
class DtlsAssociation;
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>;
QList<AssocPtr> connections;
QString nameTemplate;
unsigned nextId = 0;
quint16 port = 0;
int lookupId = -1;
};
#endif // MAINWINDOW_H

View File

@ -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>

View File

@ -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