aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2019-03-28 11:23:41 +0100
committerSona Kurazyan <sona.kurazyan@qt.io>2019-04-17 08:05:25 +0000
commit637b228a380d9f5a4a2a2f85fb487b32127076cb (patch)
tree114928d309969ff3cd7ebf9e1cf450fd6cefa568
parentf633087e26592c0b5e4a10d3895e03c267823a4f (diff)
Add secure CoAP client example
This example demonstrates sending secure CoAP GET requests in PreSharedKey and Certificate modes. Change-Id: I90ea8c77232bfca1ca86bdd7a73223b6ba8b0c9b Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--examples/coap/coap.pro1
-rw-r--r--examples/coap/quicksecureclient/FilePicker.qml88
-rw-r--r--examples/coap/quicksecureclient/main.cpp97
-rw-r--r--examples/coap/quicksecureclient/main.qml220
-rw-r--r--examples/coap/quicksecureclient/qml.qrc6
-rw-r--r--examples/coap/quicksecureclient/qmlcoapsecureclient.cpp161
-rw-r--r--examples/coap/quicksecureclient/qmlcoapsecureclient.h81
-rw-r--r--examples/coap/quicksecureclient/quicksecureclient.pro21
8 files changed, 675 insertions, 0 deletions
diff --git a/examples/coap/coap.pro b/examples/coap/coap.pro
index dcac089..ba1d57a 100644
--- a/examples/coap/coap.pro
+++ b/examples/coap/coap.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
+ quicksecureclient \
quickmulticastclient \
simplecoapclient \
consolecoapclient
diff --git a/examples/coap/quicksecureclient/FilePicker.qml b/examples/coap/quicksecureclient/FilePicker.qml
new file mode 100644
index 0000000..a7cd641
--- /dev/null
+++ b/examples/coap/quicksecureclient/FilePicker.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtCoap module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.13
+import QtQuick.Controls 2.13
+import QtQuick.Layouts 1.13
+import Qt.labs.platform 1.0
+
+Item {
+ id: filePicker
+
+ property string dialogText
+ property alias selectedFile: filePathField.text
+
+ height: addFileButton.height
+
+ FileDialog {
+ id: fileDialog
+ title: qsTr("Please Choose %1").arg(dialogText)
+ folder: StandardPaths.writableLocation(StandardPaths.HomeLocation)
+ fileMode: FileDialog.OpenFile
+ onAccepted: filePathField.text = fileDialog.file
+ }
+
+ RowLayout {
+ anchors.fill: parent
+ TextField {
+ id: filePathField
+ placeholderText: qsTr("<%1>").arg(dialogText)
+ inputMethodHints: Qt.ImhUrlCharactersOnly
+ selectByMouse: true
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: addFileButton
+ text: qsTr("Add %1").arg(dialogText)
+ onClicked: fileDialog.open()
+ }
+ }
+}
diff --git a/examples/coap/quicksecureclient/main.cpp b/examples/coap/quicksecureclient/main.cpp
new file mode 100644
index 0000000..2bfeff5
--- /dev/null
+++ b/examples/coap/quicksecureclient/main.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtCoap module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcoapsecureclient.h"
+
+#include <QGuiApplication>
+#include <QNetworkInterface>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+
+static QStringList availableHosts()
+{
+ QStringList hosts;
+
+ const auto networkInterfaces = QNetworkInterface::allInterfaces();
+ for (const auto &interface : networkInterfaces)
+ for (const auto &address : interface.addressEntries())
+ hosts.push_back(address.ip().toString());
+
+ return hosts;
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QCoreApplication::setOrganizationName("Qt CoAP Example");
+
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+
+ qmlRegisterType<QmlCoapSecureClient>("CoapSecureClient", 1, 0, "CoapSecureClient");
+
+ // Register the QtCoap namespace
+ qmlRegisterUncreatableMetaObject(QtCoap::staticMetaObject, "qtcoap.example.namespace", 1, 0,
+ "QtCoap", "Access to enums is read-only");
+
+ const QUrl url(QStringLiteral("qrc:/main.qml"));
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ // Exit with error, if the object for main.qml could not be loaded.
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+
+ engine.rootContext()->setContextProperty("hostsModel", availableHosts());
+
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/examples/coap/quicksecureclient/main.qml b/examples/coap/quicksecureclient/main.qml
new file mode 100644
index 0000000..8b637db
--- /dev/null
+++ b/examples/coap/quicksecureclient/main.qml
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtCoap module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.13
+import QtQuick.Layouts 1.13
+import QtQuick.Controls 2.13
+import QtQuick.Window 2.13
+import CoapSecureClient 1.0
+import qtcoap.example.namespace 1.0
+
+Window {
+ visible: true
+ width: 480
+ height: 640
+ title: qsTr("Qt Quick Secure CoAP Client")
+
+ CoapSecureClient {
+ id: client
+ onFinished: {
+ outputView.text = result
+ statusLabel.text = ""
+ }
+ }
+
+ GridLayout {
+ anchors.fill: parent
+ anchors.margins: 10
+ columns: 2
+
+ Label {
+ text: qsTr("Host:")
+ }
+ ComboBox {
+ id: hostComboBox
+ editable: true
+ model: hostsModel
+ Layout.fillWidth: true
+ }
+
+ Label {
+ text: qsTr("Port:")
+ }
+ TextField {
+ id: portField
+ text: "5684"
+ placeholderText: qsTr("<Port>")
+ inputMethodHints: Qt.ImhDigitsOnly
+ Layout.preferredWidth: 80
+ }
+
+ Label {
+ text: qsTr("Resource:")
+ }
+ TextField {
+ id: resourceField
+ placeholderText: qsTr("<Resource Path>")
+ inputMethodHints: Qt.ImhUrlCharactersOnly
+ selectByMouse: true
+ Layout.fillWidth: true
+ }
+
+ Label {
+ text: qsTr("Security Mode:")
+ }
+ ButtonGroup {
+ id: securityModeGroup
+ onClicked: {
+ if (securityModeGroup.checkedButton === preSharedMode)
+ client.setSecurityMode(QtCoap.PreSharedKey);
+ else
+ client.setSecurityMode(QtCoap.Certificate);
+ }
+ }
+ RowLayout {
+ RadioButton {
+ id: preSharedMode
+ text: qsTr("Pre-shared Key")
+ ButtonGroup.group: securityModeGroup
+ }
+ RadioButton {
+ id: certificateMode
+ text: qsTr("X.509 Certificate")
+ ButtonGroup.group: securityModeGroup
+ }
+ }
+
+ RowLayout {
+ enabled: securityModeGroup.checkedButton === preSharedMode
+ Layout.columnSpan: 2
+
+ Label {
+ text: qsTr("Key")
+ }
+ TextField {
+ id: pskField
+ placeholderText: qsTr("<Pre-shared Key>")
+ Layout.fillWidth: true
+ }
+
+ Label {
+ text: qsTr("Identity")
+ }
+ TextField {
+ id: identityField
+ placeholderText: qsTr("<Identity>")
+ Layout.fillWidth: true
+ }
+ }
+
+ FilePicker {
+ id: localCertificatePicker
+ dialogText: "Local Certificate"
+ enabled: securityModeGroup.checkedButton === certificateMode
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ }
+
+ FilePicker {
+ id: caCertificatePicker
+ dialogText: "CA Certificate"
+ enabled: securityModeGroup.checkedButton === certificateMode
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ }
+
+ FilePicker {
+ id: privateKeyPicker
+ dialogText: "Private Key"
+ enabled: securityModeGroup.checkedButton === certificateMode
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: requestButton
+ text: qsTr("Send Request")
+ enabled: securityModeGroup.checkState !== Qt.Unchecked
+ Layout.columnSpan: 2
+
+ onClicked: {
+ outputView.text = "";
+ if (securityModeGroup.checkedButton === preSharedMode)
+ client.setSecurityConfiguration(pskField.text, identityField.text);
+ else
+ client.setSecurityConfiguration(localCertificatePicker.selectedFile,
+ caCertificatePicker.selectedFile,
+ privateKeyPicker.selectedFile);
+
+ client.sendGetRequest(hostComboBox.editText, resourceField.text,
+ parseInt(portField.text));
+
+ statusLabel.text = qsTr("Sending request to %1%2...").arg(hostComboBox.editText)
+ .arg(resourceField.text);
+ }
+ }
+
+ TextArea {
+ id: outputView
+ placeholderText: qsTr("<Client Output>")
+ background: Rectangle {
+ border.color: "gray"
+ }
+ Layout.columnSpan: 2
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ Label {
+ id: statusLabel
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ }
+ }
+}
diff --git a/examples/coap/quicksecureclient/qml.qrc b/examples/coap/quicksecureclient/qml.qrc
new file mode 100644
index 0000000..7f8ea45
--- /dev/null
+++ b/examples/coap/quicksecureclient/qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>FilePicker.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/coap/quicksecureclient/qmlcoapsecureclient.cpp b/examples/coap/quicksecureclient/qmlcoapsecureclient.cpp
new file mode 100644
index 0000000..f73af8e
--- /dev/null
+++ b/examples/coap/quicksecureclient/qmlcoapsecureclient.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtCoap module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcoapsecureclient.h"
+
+#include <QCoapReply>
+#include <QFile>
+#include <QLoggingCategory>
+#include <QMetaEnum>
+#include <QUrl>
+
+Q_LOGGING_CATEGORY(lcCoapClient, "qt.coap.client")
+
+QmlCoapSecureClient::QmlCoapSecureClient(QObject *parent)
+ : QObject(parent)
+ , m_coapClient(nullptr)
+ , m_securityMode(QtCoap::NoSec)
+{
+}
+
+QmlCoapSecureClient::~QmlCoapSecureClient()
+{
+ if (m_coapClient) {
+ delete m_coapClient;
+ m_coapClient = nullptr;
+ }
+}
+
+static QString errorMessage(QtCoap::Error errorCode)
+{
+ const auto error = QMetaEnum::fromType<QtCoap::Error>().valueToKey(errorCode);
+ return QString("Request failed with error: %1\n").arg(error);
+}
+
+void QmlCoapSecureClient::setSecurityMode(QtCoap::SecurityMode mode)
+{
+ // Create a new client, if the security mode has changed
+ if (m_coapClient && mode != m_securityMode) {
+ delete m_coapClient;
+ m_coapClient = nullptr;
+ }
+
+ if (!m_coapClient) {
+ m_coapClient = new QCoapClient(mode);
+ m_securityMode = mode;
+
+ connect(m_coapClient, &QCoapClient::finished, this,
+ [this](QCoapReply *reply) {
+ if (!reply)
+ emit finished("Something went wrong, received a null reply");
+ else if (reply->errorReceived() != QtCoap::NoError)
+ emit finished(errorMessage(reply->errorReceived()));
+ else
+ emit finished(reply->message().payload());
+ });
+
+ connect(m_coapClient, &QCoapClient::error, this,
+ [this](QCoapReply *, QtCoap::Error errorCode) {
+ emit finished(errorMessage(errorCode));
+ });
+ }
+}
+
+void QmlCoapSecureClient::sendGetRequest(const QString &host, const QString &path, int port)
+{
+ if (!m_coapClient)
+ return;
+
+ m_coapClient->setSecurityConfiguration(m_configuration);
+
+ QUrl url;
+ url.setHost(host);
+ url.setPath(path);
+ url.setPort(port);
+ m_coapClient->get(url);
+}
+
+void
+QmlCoapSecureClient::setSecurityConfiguration(const QString &preSharedKey, const QString &identity)
+{
+ QCoapSecurityConfiguration configuration;
+ configuration.setPreSharedKey(preSharedKey.toUtf8());
+ configuration.setIdentity(identity.toUtf8());
+ m_configuration = configuration;
+}
+
+void QmlCoapSecureClient::setSecurityConfiguration(const QString &localCertificatePath,
+ const QString &caCertificatePath,
+ const QString &privateKeyPath)
+{
+ QCoapSecurityConfiguration configuration;
+
+ const auto localCerts = QSslCertificate::fromPath(QUrl(localCertificatePath).toLocalFile());
+ if (localCerts.isEmpty())
+ qCWarning(lcCoapClient, "The specified local certificate file is not valid.");
+ else
+ configuration.setLocalCertificateChain(localCerts.toVector());
+
+ const auto caCerts = QSslCertificate::fromPath(QUrl(caCertificatePath).toLocalFile());
+ if (caCerts.isEmpty())
+ qCWarning(lcCoapClient, "The specified CA certificate file is not valid.");
+ else
+ configuration.setCaCertificates(caCerts.toVector());
+
+ QFile privateKey(QUrl(privateKeyPath).toLocalFile());
+ if (privateKey.open(QIODevice::ReadOnly)) {
+ QCoapPrivateKey key(privateKey.readAll(), QSsl::Ec);
+ configuration.setPrivateKey(key);
+ } else {
+ qCWarning(lcCoapClient) << "Unable to read the specified private key file"
+ << privateKeyPath;
+ }
+ m_configuration = configuration;
+}
diff --git a/examples/coap/quicksecureclient/qmlcoapsecureclient.h b/examples/coap/quicksecureclient/qmlcoapsecureclient.h
new file mode 100644
index 0000000..1451d32
--- /dev/null
+++ b/examples/coap/quicksecureclient/qmlcoapsecureclient.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtCoap module.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOAPSECURECLIENT_H
+#define QMLCOAPSECURECLIENT_H
+
+#include <QCoapClient>
+#include <QCoapSecurityConfiguration>
+
+class QmlCoapSecureClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ QmlCoapSecureClient(QObject *parent = nullptr);
+ ~QmlCoapSecureClient() override;
+
+ Q_INVOKABLE void setSecurityMode(QtCoap::SecurityMode mode);
+ Q_INVOKABLE void sendGetRequest(const QString &host, const QString &path, int port);
+ Q_INVOKABLE void setSecurityConfiguration(const QString &preSharedKey, const QString &identity);
+ Q_INVOKABLE void setSecurityConfiguration(const QString &localCertificatePath,
+ const QString &caCertificatePath,
+ const QString &privateKeyPath);
+
+Q_SIGNALS:
+ void finished(const QString &result);
+
+private:
+ QCoapClient *m_coapClient;
+ QCoapSecurityConfiguration m_configuration;
+ QtCoap::SecurityMode m_securityMode;
+};
+
+#endif // QMLCOAPSECURECLIENT_H
diff --git a/examples/coap/quicksecureclient/quicksecureclient.pro b/examples/coap/quicksecureclient/quicksecureclient.pro
new file mode 100644
index 0000000..52fcea9
--- /dev/null
+++ b/examples/coap/quicksecureclient/quicksecureclient.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+
+QT += qml quick coap
+CONFIG += c++11
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+HEADERS += \
+ qmlcoapsecureclient.h
+
+SOURCES += \
+ main.cpp \
+ qmlcoapsecureclient.cpp
+
+DISTFILES += \
+ FilePicker.qml
+
+RESOURCES += qml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/coap/quicksecureclient
+INSTALLS += target