Revision control
++ // Copyright (C) 2018 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example secureudpclient
++ \title DTLS client
++ \examplecategory {Networking}
++ \ingroup examples-network
++ \brief This example demonstrates how to implement client-side DTLS connections.
++
++ \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
++ */
++