// 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 */