Document DTLS examples
Task-number: QTBUG-68070 Change-Id: I2b08322049005b02f1ed680bee21992ade16813a Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
4c089601d7
commit
5b8d5c7493
BIN
examples/network/doc/images/secureudpclient-example.png
Normal file
BIN
examples/network/doc/images/secureudpclient-example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
examples/network/doc/images/secureudpserver-example.png
Normal file
BIN
examples/network/doc/images/secureudpserver-example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
@ -29,9 +29,96 @@
|
||||
\example secureudpclient
|
||||
\title DTLS client
|
||||
\ingroup examples-network
|
||||
\brief Demonstrates how to implement a simple DTLS client
|
||||
\brief This example demonstrates how to implement client-side DTLS connections.
|
||||
|
||||
This example uses QUdpSocket, QDtlsClientVerifier, and QDtls to securely
|
||||
communicate over the User Datagram Protocol with DTLS servers.
|
||||
\image secureudpclient-example.png Screenshot of the DTLS client example.
|
||||
|
||||
\note The DTLS client example is intended to be run alongside the \l{secureudpserver}{DTLS server} example.
|
||||
|
||||
The example DTLS client can establish several DTLS connections to one
|
||||
or many DTLS servers. A client-side DTLS connection is implemented by the
|
||||
DtlsAssociation class. This class uses QUdpSocket to read and write datagrams
|
||||
and QDtls for encryption:
|
||||
|
||||
\snippet secureudpclient/association.h 0
|
||||
|
||||
The constructor sets the minimal TLS configuration for the new DTLS connection,
|
||||
and sets the address and the port of the server:
|
||||
|
||||
\dots
|
||||
\snippet secureudpclient/association.cpp 1
|
||||
\dots
|
||||
|
||||
The QDtls::handshakeTimeout() signal is connected to the handleTimeout() slot
|
||||
to deal with packet loss and retransmission during the handshake phase:
|
||||
|
||||
\dots
|
||||
\snippet secureudpclient/association.cpp 2
|
||||
\dots
|
||||
|
||||
To ensure we receive only the datagrams from the server, we connect our UDP socket to the server:
|
||||
|
||||
\dots
|
||||
\snippet secureudpclient/association.cpp 3
|
||||
\dots
|
||||
|
||||
The QUdpSocket::readyRead() signal is connected to the readyRead() slot:
|
||||
|
||||
\dots
|
||||
\snippet secureudpclient/association.cpp 13
|
||||
\dots
|
||||
|
||||
When a secure connection to a server is established, a DtlsAssociation object
|
||||
will be sending short ping messages to the server, using a timer:
|
||||
|
||||
\snippet secureudpclient/association.cpp 4
|
||||
|
||||
startHandshake() starts a handshake with the server:
|
||||
|
||||
\snippet secureudpclient/association.cpp 5
|
||||
|
||||
The readyRead() slot reads a datagram sent by the server:
|
||||
|
||||
\snippet secureudpclient/association.cpp 6
|
||||
|
||||
If the handshake was already completed, this datagram is decrypted:
|
||||
|
||||
\snippet secureudpclient/association.cpp 7
|
||||
|
||||
otherwise, we try to continue the handshake:
|
||||
|
||||
\snippet secureudpclient/association.cpp 8
|
||||
|
||||
When the handshake has completed, we send our first ping message:
|
||||
|
||||
\snippet secureudpclient/association.cpp 9
|
||||
|
||||
The pskRequired() slot provides the Pre-Shared Key (PSK) needed during the handshake
|
||||
phase:
|
||||
|
||||
\snippet secureudpclient/association.cpp 14
|
||||
|
||||
\note For the sake of brevity, the definition of pskRequired() is oversimplified.
|
||||
The documentation for the QSslPreSharedKeyAuthenticator class explains in detail
|
||||
how this slot can be properly implemented.
|
||||
|
||||
pingTimeout() sends an encrypted message to the server:
|
||||
|
||||
\snippet secureudpclient/association.cpp 10
|
||||
|
||||
During the handshake phase the client must handle possible timeouts, which
|
||||
can happen due to packet loss. The handshakeTimeout() slot retransmits
|
||||
the handshake messages:
|
||||
|
||||
\snippet secureudpclient/association.cpp 11
|
||||
|
||||
Before a client connection is destroyed, its DTLS connection must be shut down:
|
||||
|
||||
\snippet secureudpclient/association.cpp 12
|
||||
|
||||
Error messages, informational messages, and decrypted responses from servers
|
||||
are displayed by the UI:
|
||||
|
||||
\snippet secureudpclient/mainwindow.cpp 0
|
||||
*/
|
||||
|
||||
|
@ -29,8 +29,103 @@
|
||||
\example secureudpserver
|
||||
\title DTLS server
|
||||
\ingroup examples-network
|
||||
\brief Demonstrates how to implement a simple DTLS server
|
||||
\brief This examples demonstrates how to implement a simple DTLS server.
|
||||
|
||||
This example uses QUdpSocket, QDtlsClientVerifier, and QDtls to securely respond
|
||||
to DTLS client requests over the User Datagram Protocol.
|
||||
\image secureudpserver-example.png Screenshot of the DTLS server example.
|
||||
|
||||
\note The DTLS server example is intended to be run alongside the \l{secureudpclient}{DTLS client} example.
|
||||
|
||||
The server is implemented by the DtlsServer class. It uses QUdpSocket,
|
||||
QDtlsClientVerifier, and QDtls to test each client's reachability, complete a handshake,
|
||||
and read and write encrypted messages.
|
||||
|
||||
\snippet secureudpserver/server.h 0
|
||||
|
||||
The constructor connects the QUdpSocket::readyRead() signal to its
|
||||
readyRead() slot and sets the minimal needed TLS configuration:
|
||||
|
||||
\snippet secureudpserver/server.cpp 1
|
||||
|
||||
\note The server is not using a certificate and is relying on Pre-Shared
|
||||
Key (PSK) handshake.
|
||||
|
||||
listen() binds QUdpSocket:
|
||||
|
||||
\snippet secureudpserver/server.cpp 2
|
||||
|
||||
The readyRead() slot processes incoming datagrams:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 3
|
||||
\dots
|
||||
|
||||
After extracting an address and a port number, the server first tests
|
||||
if it's a datagram from an already known peer:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 4
|
||||
\dots
|
||||
|
||||
If it is a new, unknown address and port, the datagram is processed as a
|
||||
potential ClientHello message, sent by a DTLS client:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 5
|
||||
\dots
|
||||
|
||||
If it's a known DTLS client, the server either decrypts the datagram:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 6
|
||||
\dots
|
||||
|
||||
or continues a handshake with this peer:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 7
|
||||
\dots
|
||||
|
||||
handleNewConnection() verifies it's a reachable DTLS client, or sends a
|
||||
HelloVerifyRequest:
|
||||
|
||||
\snippet secureudpserver/server.cpp 8
|
||||
\dots
|
||||
|
||||
If the new client was verified to be a reachable DTLS client, the server creates
|
||||
and configures a new QDtls object, and starts a server-side handshake:
|
||||
|
||||
\dots
|
||||
\snippet secureudpserver/server.cpp 9
|
||||
\dots
|
||||
|
||||
doHandshake() progresses through the handshake phase:
|
||||
|
||||
\snippet secureudpserver/server.cpp 11
|
||||
|
||||
During the handshake phase, the QDtls::pskRequired() signal is emitted and
|
||||
the pskRequired() slot provides the preshared key:
|
||||
|
||||
\snippet secureudpserver/server.cpp 13
|
||||
|
||||
\note For the sake of brevity, the definition of pskRequired() is oversimplified.
|
||||
The documentation for the QSslPreSharedKeyAuthenticator class explains in detail
|
||||
how this slot can be properly implemented.
|
||||
|
||||
After the handshake is completed for the network peer, an encrypted DTLS
|
||||
connection is considered to be established and the server decrypts subsequent
|
||||
datagrams, sent by the peer, by calling decryptDatagram(). The server also
|
||||
sends an encrypted response to the peer:
|
||||
|
||||
\snippet secureudpserver/server.cpp 12
|
||||
|
||||
The server closes its DTLS connections by calling QDtls::shutdown():
|
||||
|
||||
\snippet secureudpserver/server.cpp 14
|
||||
|
||||
During its operation, the server reports errors, informational messages, and
|
||||
decrypted datagrams, by emitting signals errorMessage(), warningMessage(),
|
||||
infoMessage(), and datagramReceived(). These messages are logged by the server's
|
||||
UI:
|
||||
|
||||
\snippet secureudpserver/mainwindow.cpp 0
|
||||
*/
|
||||
|
@ -69,7 +69,6 @@ class AddressDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit AddressDialog(QWidget *parent = nullptr);
|
||||
~AddressDialog();
|
||||
|
||||
@ -77,7 +76,6 @@ public:
|
||||
quint16 remotePort() const;
|
||||
|
||||
private:
|
||||
|
||||
void setupHostSelector();
|
||||
void setupPortSelector();
|
||||
|
||||
|
@ -57,27 +57,38 @@ DtlsAssociation::DtlsAssociation(const QHostAddress &address, quint16 port,
|
||||
: 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) {
|
||||
@ -86,11 +97,12 @@ void DtlsAssociation::startHandshake()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crypto.doHandshake(&socket, {}))
|
||||
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()
|
||||
{
|
||||
@ -100,7 +112,8 @@ void DtlsAssociation::udpSocketConnected()
|
||||
|
||||
void DtlsAssociation::readyRead()
|
||||
{
|
||||
QByteArray dgram(socket.pendingDatagramSize(), '\0');
|
||||
//! [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));
|
||||
@ -108,6 +121,8 @@ void DtlsAssociation::readyRead()
|
||||
}
|
||||
|
||||
dgram.resize(bytesRead);
|
||||
//! [6]
|
||||
//! [7]
|
||||
if (crypto.isConnectionEncrypted()) {
|
||||
const QByteArray plainText = crypto.decryptDatagram(&socket, dgram);
|
||||
if (plainText.size()) {
|
||||
@ -124,27 +139,36 @@ void DtlsAssociation::readyRead()
|
||||
|
||||
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);
|
||||
@ -153,7 +177,9 @@ void DtlsAssociation::pskRequired(QSslPreSharedKeyAuthenticator *auth)
|
||||
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");
|
||||
@ -166,5 +192,6 @@ void DtlsAssociation::pingTimeout()
|
||||
|
||||
++ping;
|
||||
}
|
||||
//! [10]
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -55,19 +55,18 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//! [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);
|
||||
@ -75,7 +74,6 @@ signals:
|
||||
const QByteArray &plainText);
|
||||
|
||||
private slots:
|
||||
|
||||
void udpSocketConnected();
|
||||
void readyRead();
|
||||
void handshakeTimeout();
|
||||
@ -83,7 +81,6 @@ private slots:
|
||||
void pingTimeout();
|
||||
|
||||
private:
|
||||
|
||||
QString name;
|
||||
QUdpSocket socket;
|
||||
QDtls crypto;
|
||||
@ -93,6 +90,7 @@ private:
|
||||
|
||||
Q_DISABLE_COPY(DtlsAssociation)
|
||||
};
|
||||
//! [0]
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -72,6 +72,8 @@ MainWindow::~MainWindow()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
||||
const QString colorizer(QStringLiteral("<font color=\"%1\">%2</font><br>"));
|
||||
|
||||
void MainWindow::addErrorMessage(const QString &message)
|
||||
@ -102,6 +104,8 @@ void MainWindow::addServerResponse(const QString &clientInfo, const QByteArray &
|
||||
ui->serverMessages->insertHtml(colorizer.arg(messageColor, html));
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
||||
void MainWindow::on_connectButton_clicked()
|
||||
{
|
||||
if (lookupId != -1) {
|
||||
|
@ -76,7 +76,6 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
@ -94,7 +93,6 @@ private slots:
|
||||
void lookupFinished(const QHostInfo &hostInfo);
|
||||
|
||||
private:
|
||||
|
||||
void updateUi();
|
||||
void startNewConnection(const QHostAddress &address);
|
||||
|
||||
|
@ -104,6 +104,7 @@ void MainWindow::updateUi()
|
||||
: ui->startButton->setText(tr("Start listening"));
|
||||
}
|
||||
|
||||
//! [0]
|
||||
const QString colorizer(QStringLiteral("<font color=\"%1\">%2</font><br>"));
|
||||
|
||||
void MainWindow::addErrorMessage(const QString &message)
|
||||
@ -134,3 +135,4 @@ void MainWindow::addClientMessage(const QString &peerInfo, const QByteArray &dat
|
||||
QString::fromUtf8(plainText));
|
||||
ui->messages->insertHtml(colorizer.arg(messageColor, html));
|
||||
}
|
||||
//! [0]
|
||||
|
@ -69,12 +69,10 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
MainWindow();
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
|
||||
void addErrorMessage(const QString &message);
|
||||
void addWarningMessage(const QString &message);
|
||||
void addInfoMessage(const QString &message);
|
||||
@ -85,7 +83,6 @@ private slots:
|
||||
void on_quitButton_clicked();
|
||||
|
||||
private:
|
||||
|
||||
void updateUi();
|
||||
|
||||
Ui::MainWindow *ui = nullptr;
|
||||
|
@ -87,6 +87,7 @@ QString connection_info(QSharedPointer<QDtls> connection)
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
//! [1]
|
||||
DtlsServer::DtlsServer()
|
||||
{
|
||||
connect(&serverSocket, &QAbstractSocket::readyRead, this, &DtlsServer::readyRead);
|
||||
@ -94,12 +95,14 @@ DtlsServer::DtlsServer()
|
||||
serverConfiguration.setPreSharedKeyIdentityHint("Qt DTLS example server");
|
||||
serverConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
}
|
||||
//! [1]
|
||||
|
||||
DtlsServer::~DtlsServer()
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
|
||||
//! [2]
|
||||
bool DtlsServer::listen(const QHostAddress &address, quint16 port)
|
||||
{
|
||||
if (address != serverSocket.localAddress() || port != serverSocket.localPort()) {
|
||||
@ -113,6 +116,7 @@ bool DtlsServer::listen(const QHostAddress &address, quint16 port)
|
||||
|
||||
return listening;
|
||||
}
|
||||
//! [2]
|
||||
|
||||
bool DtlsServer::isListening() const
|
||||
{
|
||||
@ -126,6 +130,7 @@ void DtlsServer::close()
|
||||
|
||||
void DtlsServer::readyRead()
|
||||
{
|
||||
//! [3]
|
||||
const qint64 bytesToRead = serverSocket.pendingDatagramSize();
|
||||
if (bytesToRead <= 0) {
|
||||
emit warningMessage(tr("A spurious read notification"));
|
||||
@ -143,7 +148,8 @@ void DtlsServer::readyRead()
|
||||
}
|
||||
|
||||
dgram.resize(bytesRead);
|
||||
|
||||
//! [3]
|
||||
//! [4]
|
||||
if (peerAddress.isNull() || !peerPort) {
|
||||
emit warningMessage(tr("Failed to extract peer info (address, port)"));
|
||||
return;
|
||||
@ -154,20 +160,28 @@ void DtlsServer::readyRead()
|
||||
return connection->peerAddress() == peerAddress
|
||||
&& connection->peerPort() == peerPort;
|
||||
});
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
if (client == knownClients.end())
|
||||
return handleNewConnection(peerAddress, peerPort, dgram);
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
if ((*client)->isConnectionEncrypted()) {
|
||||
decryptDatagram(*client, dgram);
|
||||
if ((*client)->dtlsError() == QDtlsError::RemoteClosedConnectionError)
|
||||
knownClients.erase(client);
|
||||
return;
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
doHandshake(*client, dgram);
|
||||
//! [7]
|
||||
}
|
||||
|
||||
//! [13]
|
||||
void DtlsServer::pskRequired(QSslPreSharedKeyAuthenticator *auth)
|
||||
{
|
||||
Q_ASSERT(auth);
|
||||
@ -176,7 +190,9 @@ void DtlsServer::pskRequired(QSslPreSharedKeyAuthenticator *auth)
|
||||
.arg(QString::fromLatin1(auth->identity())));
|
||||
auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
|
||||
}
|
||||
//! [13]
|
||||
|
||||
//! [8]
|
||||
void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
|
||||
quint16 peerPort, const QByteArray &clientHello)
|
||||
{
|
||||
@ -186,7 +202,8 @@ void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
|
||||
const QString peerInfo = peer_info(peerAddress, peerPort);
|
||||
if (cookieSender.verifyClient(&serverSocket, clientHello, peerAddress, peerPort)) {
|
||||
emit infoMessage(peerInfo + tr(": verified, starting a handshake"));
|
||||
|
||||
//! [8]
|
||||
//! [9]
|
||||
DtlsConnection newConnection(new QDtls(QSslSocket::SslServerMode));
|
||||
newConnection->setDtlsConfiguration(serverConfiguration);
|
||||
newConnection->setPeer(peerAddress, peerPort);
|
||||
@ -194,6 +211,7 @@ void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
|
||||
this, &DtlsServer::pskRequired);
|
||||
knownClients.push_back(newConnection);
|
||||
doHandshake(newConnection, clientHello);
|
||||
//! [9]
|
||||
} else if (cookieSender.dtlsError() != QDtlsError::NoError) {
|
||||
emit errorMessage(tr("DTLS error: ") + cookieSender.dtlsErrorString());
|
||||
} else {
|
||||
@ -201,6 +219,7 @@ void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
|
||||
}
|
||||
}
|
||||
|
||||
//! [11]
|
||||
void DtlsServer::doHandshake(DtlsConnection newConnection, const QByteArray &clientHello)
|
||||
{
|
||||
const bool result = newConnection->doHandshake(&serverSocket, clientHello);
|
||||
@ -223,7 +242,9 @@ void DtlsServer::doHandshake(DtlsConnection newConnection, const QByteArray &cli
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
//! [11]
|
||||
|
||||
//! [12]
|
||||
void DtlsServer::decryptDatagram(DtlsConnection connection, const QByteArray &clientMessage)
|
||||
{
|
||||
Q_ASSERT(connection->isConnectionEncrypted());
|
||||
@ -239,7 +260,9 @@ void DtlsServer::decryptDatagram(DtlsConnection connection, const QByteArray &cl
|
||||
emit errorMessage(peerInfo + ": " + connection->dtlsErrorString());
|
||||
}
|
||||
}
|
||||
//! [12]
|
||||
|
||||
//! [14]
|
||||
void DtlsServer::shutdown()
|
||||
{
|
||||
for (DtlsConnection &connection : knownClients)
|
||||
@ -248,5 +271,6 @@ void DtlsServer::shutdown()
|
||||
knownClients.clear();
|
||||
serverSocket.close();
|
||||
}
|
||||
//! [14]
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -57,12 +57,12 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//! [0]
|
||||
class DtlsServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
DtlsServer();
|
||||
~DtlsServer();
|
||||
|
||||
@ -71,7 +71,6 @@ public:
|
||||
void close();
|
||||
|
||||
signals:
|
||||
|
||||
void errorMessage(const QString &message);
|
||||
void warningMessage(const QString &message);
|
||||
void infoMessage(const QString &message);
|
||||
@ -80,12 +79,10 @@ signals:
|
||||
const QByteArray &plainText);
|
||||
|
||||
private slots:
|
||||
|
||||
void readyRead();
|
||||
void pskRequired(QSslPreSharedKeyAuthenticator *auth);
|
||||
|
||||
private:
|
||||
|
||||
void handleNewConnection(const QHostAddress &peerAddress, quint16 peerPort,
|
||||
const QByteArray &clientHello);
|
||||
|
||||
@ -103,6 +100,7 @@ private:
|
||||
|
||||
Q_DISABLE_COPY(DtlsServer)
|
||||
};
|
||||
//! [0]
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user