/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \example quicksecureclient
    \title Quick Secure CoAP Client Example
    \ingroup qtcoap-examples
    \brief Securing the CoAP client and using it with a Qt Quick user interface.

    \image quicksecureclient.png

    \e {Quick Secure CoAP Client} demonstrates how to create a secure CoAP client
    and use it in a Qt Quick application.

    \note Qt CoAP does not provide a QML API in its current version. However, you can
    make the C++ classes of the module available to QML as it is shown in the example.

    \section1 Running the Example

    To run the example application, you first need to set up a secure CoAP server.
    You can run the example with any secure CoAP server supporting one of the
    \e {pre-shared key (PSK)} or \e certificate authentication modes. For more
    information about setting up a secure CoAP server, see
    \l {Setting Up a Secure CoAP Server}.

    \section1 Creating a Client and Linking It with QML

    \c QmlCoapSecureClient wraps the functionality of QCoapClient to make it
    available to QML. It also holds the selected security mode and security
    configuration parameters.

    \quotefromfile quicksecureclient/qmlcoapsecureclient.h
    \skipto class QmlCoapSecureClient
    \printuntil /^\}/

    In the main.cpp file, we register the \c QmlCoapSecureClient class as a QML type:

    \quotefromfile quicksecureclient/main.cpp
    \skipto qmlRegisterType
    \printline qmlRegisterType

    We also register the QtCoap namespace, to be able to use it in QML code:

    \skipto qmlRegisterUncreatableMetaObject
    \printto const QUrl

    The instance of QCoapClient is created when the user selects or changes the
    security mode in the UI. The \c {QmlCoapSecureClient::setSecurityMode()} method
    is invoked from the QML code,  when one of the security modes is selected:

    \quotefromfile quicksecureclient/main.qml
    \skipto ButtonGroup
    \printto RowLayout

    And in the \c .cpp file:

    \quotefromfile quicksecureclient/qmlcoapsecureclient.cpp
    \skipto QmlCoapSecureClient::setSecurityMode
    \printto connect
    \dots

    Then we connect the signals of the client, to get notified when a CoAP reply is
    received or a request has failed:

    \dots
    \skipto connect
    \printuntil });
    \printuntil });
    \dots

    The \c {QmlCoapSecureClient::finished()} signal triggers the \c onFinished signal
    handler of \c CoapSecureClient, which handles the output:

    \quotefromfile quicksecureclient/main.qml
    \skipto CoapSecureClient {
    \printto GridLayout
    \dots

    \section1 Sending a Request

    When the user clicks on the \uicontrol {Send Request} button, we set the security
    configuration based on the selected security mode and send a \c GET request:

    \dots
    \skipto FilePicker {
    \skipto Button {
    \printuntil sendGetRequest
    \dots

    There are two overloads for the \c setSecurityConfiguration method. For the PSK
    mode we simply set the client identity and the pre-shared key:

    \quotefromfile quicksecureclient/qmlcoapsecureclient.cpp
    \skipto QmlCoapSecureClient::setSecurityConfiguration
    \printuntil }

    And for X.509 certificates, we read the certificate files and the private key,
    and set the security configuration:

    \skipto QmlCoapSecureClient::setSecurityConfiguration
    \printto QmlCoapSecureClient::disconnect

    After setting the security configuration, the \c sendGetRequest method sets the
    request URL and sends a \c GET request:

    \quotefromfile quicksecureclient/qmlcoapsecureclient.cpp
    \skipto QmlCoapSecureClient::sendGetRequest
    \printuntil }

    When sending the first request, a handshake with the CoAP server is performed.
    After the handshake is successfully done, all the subsequent messages are encrypted,
    and changing the security configuration after a successful handshake won't have any
    effect. If you want to change it, or change the host, you need to disconnect first.

    \skipto QmlCoapSecureClient::disconnect
    \printuntil

    This will abort the handshake and close the open sockets.

    For the authentication using X.509 certificates, we need to specify the certificate
    files. The \c FilePicker component is used for this purpose. It combines a text
    field and a button for opening a file dialog when the button is pressed:

    \quotefromfile quicksecureclient/FilePicker.qml
    \skipto Item {
    \printuntil

    In the \c main.qml file \c FilePicker is instantiated several times for creating
    input fields for certificates and the private key:

    \quotefromfile quicksecureclient/main.qml
    \dots
    \skipto FilePicker
    \printto Button {
    \dots

    \section1 Setting Up a Secure CoAP Server

    To run this example, you need to have a secure CoAP server supporting either PSK
    or Certificate modes (or both). You have the following options:

    \list
        \li Manually build and run a secure CoAP server using, for example,
        \l {https://github.com/obgm/libcoap} {libcoap},
        \l {https://github.com/eclipse/californium} {Californium},
        \l {https://github.com/keith-cullen/FreeCoAP} {FreeCoAP},
        or any other CoAP library which supports DTLS.
        \li Use the ready Docker images available at Docker Hub, which build and run
        the secure CoAP servers suitable for our example. The steps required for using
        the docker-based CoAP servers are described below.
    \endlist

   \section2 Setting Up a Server For PSK Mode

    The following command pulls the docker container for a secure CoAP server based on
    \l {https://github.com/eclipse/californium/tree/master/demo-apps/cf-plugtest-server}
    {Californium plugtest} (which is not secure by default) from the Docker Hub and
    starts it:

    \badcode
    docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp sokurazy/coap-secure-test-server:californium.1.1.0
    \endcode

    The CoAP test server will be reachable on ports \e 5683 (non-secure) and
    \e 5684 (secure). For instructions on retrieving the IP address see
    \l {Getting The IP Address}.

    To run the example with this server, you need to set the pre-shared key to
    \c secretPSK and the identity to \c Client_identity.

    \section2 Setting Up a Server For Certificate Mode

    The docker image of the secure server using authentication with X.509 certificates
    is based on the
    \l {https://github.com/keith-cullen/FreeCoAP/tree/master/sample/time_server}
    {time server} example from the FreeCoAP library. The following command pulls
    the container from Docker Hub and starts it:

    \badcode
    docker run --name coap-time-server -d --rm -p 5684:5684/udp sokurazy/coap-secure-time-sever:freecoap
    \endcode

    For instructions on retrieving the IP address see \l {Getting The IP Address}.
    The CoAP test server will be reachable by the retrieved IP address on port
    \e 5684 and resource path \c /time.

    To run the example with this server, you need to specify the certificate files
    required by the server. They are located in the docker container, under
    \c {/root/certs} directory. To copy them to a local directory, use the following
    command:

    \badcode
    docker cp <container_id>:/root/certs <local_directory_path>
    \endcode

    For example:

    \badcode
    $ docker cp 5e46502df88f:/root/certs ~/
    \endcode

    The instructions for getting the container ID are described below.

    \section2 Getting The IP Address

    To find out the IP address of a docker container, first retrieve the container ID
    by running the \c {docker ps} command, which will output something like:

    \badcode
    $ docker ps
    CONTAINER ID        IMAGE
    5e46502df88f        sokurazy/coap-secure-test-server:californium.1.1.0
    \endcode

    Then you can obtain the IP address with the following command:

    \badcode
    docker inspect <container_id> | grep IPAddress
    \endcode

    For example:

    \badcode
    $ docker inspect 5e46502df88f | grep IPAddress
    ...
    "IPAddress": "172.17.0.2",
    ...
    \endcode
*/
