From 5b8d5c7493259544f853eb2732cca2829c0f67ca Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 6 Aug 2018 12:05:26 +0200 Subject: Document DTLS examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-68070 Change-Id: I2b08322049005b02f1ed680bee21992ade16813a Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Paul Wicking Reviewed-by: Edward Welbourne --- examples/network/doc/src/secureudpclient.qdoc | 93 +++++++++++++++++++++++- examples/network/doc/src/secureudpserver.qdoc | 101 +++++++++++++++++++++++++- 2 files changed, 188 insertions(+), 6 deletions(-) (limited to 'examples/network/doc/src') diff --git a/examples/network/doc/src/secureudpclient.qdoc b/examples/network/doc/src/secureudpclient.qdoc index 587689ac47..dc8538cf85 100644 --- a/examples/network/doc/src/secureudpclient.qdoc +++ b/examples/network/doc/src/secureudpclient.qdoc @@ -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 */ diff --git a/examples/network/doc/src/secureudpserver.qdoc b/examples/network/doc/src/secureudpserver.qdoc index a00d65773b..0857f7065f 100644 --- a/examples/network/doc/src/secureudpserver.qdoc +++ b/examples/network/doc/src/secureudpserver.qdoc @@ -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 */ -- cgit v1.2.3