aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-04-27 03:02:26 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-04-27 03:02:26 +0200
commit2050395003076fea84a8bdcc3948e8b50262a39c (patch)
tree477a35cae6dcdb69786cd7bcd08ab76b371a8d92
parent3cf3afbe59c8d6e6cf8d49a7155345bad1257def (diff)
parente8b9f3c8a91a0071afd315c2455772652b976f48 (diff)
Merge remote-tracking branch 'origin/5.13' into dev
-rw-r--r--examples/coap/doc/images/quickmulticastclient.pngbin0 -> 17289 bytes
-rw-r--r--examples/coap/doc/quickmulticastclient.qdoc127
-rw-r--r--src/coap/coap.pro1
-rw-r--r--src/coap/doc/src/external-resources.qdoc5
-rw-r--r--src/coap/qcoapclient.cpp11
-rw-r--r--src/coap/qcoapclient.h3
-rw-r--r--src/coap/qcoapconnection.cpp41
-rw-r--r--src/coap/qcoapconnection.h2
-rw-r--r--src/coap/qcoapdiscoveryreply_p.h2
-rw-r--r--src/coap/qcoapinternalmessage.h74
-rw-r--r--src/coap/qcoapinternalmessage_p.h34
-rw-r--r--src/coap/qcoapinternalreply_p.h3
-rw-r--r--src/coap/qcoapinternalrequest_p.h5
-rw-r--r--src/coap/qcoapmessage.cpp10
-rw-r--r--src/coap/qcoapmessage.h4
-rw-r--r--src/coap/qcoapprotocol.h2
-rw-r--r--src/coap/qcoapqudpconnection.cpp28
-rw-r--r--src/coap/qcoapqudpconnection.h1
-rw-r--r--src/coap/qcoapreply.h4
-rw-r--r--src/coap/qcoapresource.cpp10
-rw-r--r--tests/auto/qcoapclient/tst_qcoapclient.cpp2
-rw-r--r--tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp24
22 files changed, 290 insertions, 103 deletions
diff --git a/examples/coap/doc/images/quickmulticastclient.png b/examples/coap/doc/images/quickmulticastclient.png
new file mode 100644
index 0000000..3339db1
--- /dev/null
+++ b/examples/coap/doc/images/quickmulticastclient.png
Binary files differ
diff --git a/examples/coap/doc/quickmulticastclient.qdoc b/examples/coap/doc/quickmulticastclient.qdoc
index c3295c5..25d86b6 100644
--- a/examples/coap/doc/quickmulticastclient.qdoc
+++ b/examples/coap/doc/quickmulticastclient.qdoc
@@ -31,4 +31,131 @@
\ingroup qtcoap-examples
\brief Using the CoAP client for a multicast resource discovery with a Qt Quick
user interface.
+
+ \image quickmulticastclient.png
+
+ The \e {Quick CoAP Multicast Discovery Example} demonstrates how to register
+ QCoapClient as a QML type and use it in a Qt Quick application for CoAP multicast
+ resource discovery.
+
+ \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 shown in this example.
+
+ \section1 Running the Example
+
+ To run the example application, you first need to set up and start at least one CoAP
+ server supporting multicast resource discovery. You have the following options:
+
+ \list
+ \li Manually build and run CoAP servers using
+ \l {https://github.com/obgm/libcoap} {libcoap},
+ \l {https://github.com/eclipse/californium/} {Californium}, or any
+ other CoAP server implementation, which supports multicast and resource
+ discovery features.
+ \li Use the ready Docker image available at Docker Hub, which builds and starts
+ CoAP server based on Californium's
+ \l {https://github.com/eclipse/californium/tree/2.0.x/demo-apps/cf-helloworld-server}
+ {multicast server example}.
+ \endlist
+
+ \section2 Using the Docker-based Test Server
+
+ The following command pulls the docker container for the CoAP server from the
+ Docker Hub and starts it:
+
+ \badcode
+ docker run --name coap-multicast-server -d --rm --net=host sokurazy/coap-multicast-test-server:californium.2.0.x
+ \endcode
+
+ \note You can run more than one multicast CoAP servers (on the same host or other
+ hosts in the network) by passing a different \c{--name} to the command above.
+
+ \section1 Creating a Client and Using It with QML
+
+ We create the \c QmlCoapMulticastClient class with the QCoapClient class as a
+ base class:
+
+ \quotefromfile quickmulticastclient/qmlcoapmulticastclient.h
+ \skipto QmlCoapMulticastClient
+ \printuntil };
+
+ In the main.cpp file, we register the \c QmlCoapMulticastClient class as a QML
+ type:
+
+ \quotefromfile quickmulticastclient/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
+
+ Now in the QML code, we can import and use these types:
+
+ \quotefromfile quickmulticastclient/main.qml
+ \dots
+ \skipto CoapMulticastClient
+ \printuntil qtcoap.example.namespace
+ \dots
+ \skipto CoapMulticastClient
+ \printto GridLayout
+ \dots
+
+ The \c {QCoapClient::error()} signal triggers the \c onError signal handler of
+ \c CoapMulticastClient, and the \c {QmlCoapMulticastClient::finished()} signal
+ triggers the \c onFinished signal handler, to show the request's status in the UI.
+ Note that we are not using the \c {QCoapClient::finished()} signal directly,
+ because it takes a \c {QCoapReply} as a parameter (which is not a QML type), and
+ we are interested only in the error code.
+
+ In the \c QmlCoapMulticastClient's constructor, we arrange for the
+ \c {QCoapClient::finished()} signal to be forwarded to the
+ \c {QmlCoapMulticastClient::finished()} signal:
+
+ \quotefromfile quickmulticastclient/qmlcoapmulticastclient.cpp
+ \skipto QmlCoapMulticastClient::QmlCoapMulticastClient
+ \printto QmlCoapMulticastClient::discover
+
+ When the \uicontrol Discover button is pressed, we invoke one of the overloaded
+ \c {discover()} methods, based on the selected multicast group:
+
+ \quotefromfile quickmulticastclient/main.qml
+ \skipto Button {
+ \dots
+ \printto ListModel {
+ \dots
+
+ This overload is called when a custom multicast group or a host address is selected:
+
+ \quotefromfile quickmulticastclient/qmlcoapmulticastclient.cpp
+ \skipto QmlCoapMulticastClient::discover
+ \printto QmlCoapMulticastClient::discover(QtCoap::MulticastGroup
+
+ And this overload is called when one of the suggested multicast groups is selected
+ in the UI:
+
+ \printto void QmlCoapMulticastClient::onDiscovered
+
+ The \c {QCoapClient::discovered()} signal delivers a list of \c {QCoapResources},
+ which is not a QML type. To make the resources available in QML, we forward each
+ resource in the list to the \c {QmlCoapMulticastClient::discovered()} signal, which
+ takes a \c QmlCoapResource instead:
+
+ \printuntil
+
+ \c QmlCoapResource is a wrapper around QCoapResource, to make some of its
+ properties available in QML:
+
+ \quotefromfile quickmulticastclient/qmlcoapmulticastclient.h
+ \skipto class QmlCoapResource
+ \printuntil };
+
+ The discovered resources are added to the \c resourceModel of the list view in the UI:
+
+ \quotefromfile quickmulticastclient/main.qml
+ \skipto addResource
+ \dots
+ \printto CoapMulticastClient {
+ \dots
*/
diff --git a/src/coap/coap.pro b/src/coap/coap.pro
index 571b746..024de15 100644
--- a/src/coap/coap.pro
+++ b/src/coap/coap.pro
@@ -10,7 +10,6 @@ PUBLIC_HEADERS += \
qcoapconnection.h \
qcoapdiscoveryreply.h \
qcoapglobal.h \
- qcoapinternalmessage.h \
qcoapmessage.h \
qcoapnamespace.h \
qcoapoption.h \
diff --git a/src/coap/doc/src/external-resources.qdoc b/src/coap/doc/src/external-resources.qdoc
index 8cbbf9f..f018c94 100644
--- a/src/coap/doc/src/external-resources.qdoc
+++ b/src/coap/doc/src/external-resources.qdoc
@@ -59,3 +59,8 @@
\externalpage https://tools.ietf.org/html/rfc7252#section-4.2
\title RFC 7252 - Section 4.2
*/
+
+/*!
+ \externalpage https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats
+ \title CoAP Content-Formats Registry
+*/
diff --git a/src/coap/qcoapclient.cpp b/src/coap/qcoapclient.cpp
index b438ba6..dced30e 100644
--- a/src/coap/qcoapclient.cpp
+++ b/src/coap/qcoapclient.cpp
@@ -127,7 +127,7 @@ QCoapClientPrivate::~QCoapClientPrivate()
/*!
\fn void QCoapClient::responseToMulticastReceived(QCoapReply *reply,
- const QCoapMessage& message,
+ const QCoapMessage &message,
const QHostAddress &sender)
This signal is emitted when a unicast response to a multicast request
@@ -508,6 +508,15 @@ void QCoapClient::cancelObserve(const QUrl &url)
}
/*!
+ Closes the open sockets and connections to free the transport.
+*/
+void QCoapClient::disconnect()
+{
+ Q_D(QCoapClient);
+ QMetaObject::invokeMethod(d->connection, "disconnect", Qt::QueuedConnection);
+}
+
+/*!
\internal
Sends the CoAP \a request to its own URL and returns a new QCoapReply
diff --git a/src/coap/qcoapclient.h b/src/coap/qcoapclient.h
index 5795191..4645c4c 100644
--- a/src/coap/qcoapclient.h
+++ b/src/coap/qcoapclient.h
@@ -72,6 +72,7 @@ public:
QCoapReply *observe(const QUrl &request);
void cancelObserve(QCoapReply *notifiedReply);
void cancelObserve(const QUrl &url);
+ void disconnect();
QCoapDiscoveryReply *discover(QtCoap::MulticastGroup group = QtCoap::AllCoapNodesIPv4,
int port = QtCoap::DefaultPort,
@@ -89,7 +90,7 @@ public:
Q_SIGNALS:
void finished(QCoapReply *reply);
- void responseToMulticastReceived(QCoapReply *reply, const QCoapMessage& message,
+ void responseToMulticastReceived(QCoapReply *reply, const QCoapMessage &message,
const QHostAddress &sender);
void error(QCoapReply *reply, QtCoap::Error error);
diff --git a/src/coap/qcoapconnection.cpp b/src/coap/qcoapconnection.cpp
index 0263618..7ee529a 100644
--- a/src/coap/qcoapconnection.cpp
+++ b/src/coap/qcoapconnection.cpp
@@ -98,7 +98,16 @@ Q_LOGGING_CATEGORY(lcCoapConnection, "qt.coap.connection")
This is a pure virtual method.
- \sa bound()
+ \sa bound(), close()
+*/
+
+/*!
+ \fn void QCoapConnection::close()
+
+ Closes the open sockets and connections to free the underlying transport.
+ This is a pure virtual method.
+
+ \sa bind()
*/
/*!
@@ -133,6 +142,12 @@ QCoapConnection::QCoapConnection(QtCoap::SecurityMode securityMode, QObject *par
QCoapConnection::QCoapConnection(QObjectPrivate &dd, QObject *parent)
: QObject(dd, parent)
{
+ connect(this, &QCoapConnection::bound, this,
+ [this]() {
+ Q_D(QCoapConnection);
+ d->state = QCoapConnection::Bound;
+ startToSendRequest();
+ });
}
/*!
@@ -160,16 +175,10 @@ QCoapConnectionPrivate::sendRequest(const QByteArray &request, const QString &ho
CoapFrame frame(request, host, port);
framesToSend.enqueue(frame);
- if (state == QCoapConnection::ConnectionState::Unconnected) {
- q->connect(q, &QCoapConnection::bound, q,
- [this, q]() {
- state = QCoapConnection::ConnectionState::Bound;
- q->startToSendRequest();
- });
+ if (state == QCoapConnection::ConnectionState::Unconnected)
q->bind(host, port);
- } else {
+ else
q->startToSendRequest();
- }
}
/*!
@@ -242,4 +251,18 @@ QCoapSecurityConfiguration QCoapConnection::securityConfiguration() const
return d->securityConfiguration;
}
+/*!
+ Closes the open sockets and connections to free the transport and clears
+ the connection state.
+*/
+void QCoapConnection::disconnect()
+{
+ Q_D(QCoapConnection);
+
+ close();
+
+ d->framesToSend.clear();
+ d->state = QCoapConnection::Unconnected;
+}
+
QT_END_NAMESPACE
diff --git a/src/coap/qcoapconnection.h b/src/coap/qcoapconnection.h
index 017a0bd..017053b 100644
--- a/src/coap/qcoapconnection.h
+++ b/src/coap/qcoapconnection.h
@@ -58,6 +58,7 @@ public:
QCoapSecurityConfiguration securityConfiguration() const;
Q_INVOKABLE void setSecurityConfiguration(const QCoapSecurityConfiguration &configuration);
+ Q_INVOKABLE void disconnect();
Q_SIGNALS:
void error(QAbstractSocket::SocketError error);
@@ -73,6 +74,7 @@ protected:
virtual void bind(const QString &host, quint16 port) = 0;
virtual void writeData(const QByteArray &data, const QString &host, quint16 port) = 0;
+ virtual void close() = 0;
private:
friend class QCoapProtocolPrivate;
diff --git a/src/coap/qcoapdiscoveryreply_p.h b/src/coap/qcoapdiscoveryreply_p.h
index ccd5d72..5f4856e 100644
--- a/src/coap/qcoapdiscoveryreply_p.h
+++ b/src/coap/qcoapdiscoveryreply_p.h
@@ -54,7 +54,7 @@ class Q_AUTOTEST_EXPORT QCoapDiscoveryReplyPrivate : public QCoapReplyPrivate
public:
QCoapDiscoveryReplyPrivate(const QCoapRequest &request);
- void _q_setContent(const QHostAddress &sender, const QCoapMessage &, QtCoap::ResponseCode) Q_DECL_OVERRIDE;
+ void _q_setContent(const QHostAddress &sender, const QCoapMessage &, QtCoap::ResponseCode) override;
QVector<QCoapResource> resources;
diff --git a/src/coap/qcoapinternalmessage.h b/src/coap/qcoapinternalmessage.h
deleted file mode 100644
index af858bf..0000000
--- a/src/coap/qcoapinternalmessage.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Witekio.
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCoap module.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** 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 General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QCOAPINTERNALMESSAGE_H
-#define QCOAPINTERNALMESSAGE_H
-
-#include <QtCoap/qcoapmessage.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QCoapInternalMessagePrivate;
-class Q_AUTOTEST_EXPORT QCoapInternalMessage : public QObject
-{
- Q_OBJECT
-public:
- explicit QCoapInternalMessage(QObject *parent = nullptr);
- explicit QCoapInternalMessage(const QCoapMessage &message, QObject *parent = nullptr);
- QCoapInternalMessage(const QCoapInternalMessage &other, QObject *parent = nullptr);
- virtual ~QCoapInternalMessage() {}
-
- void addOption(QCoapOption::OptionName name, const QByteArray &value);
- void addOption(QCoapOption::OptionName name, quint32 value);
- virtual void addOption(const QCoapOption &option);
- void removeOption(QCoapOption::OptionName name);
-
- QCoapMessage *message();
- const QCoapMessage *message() const;
-
- uint currentBlockNumber() const;
- bool hasMoreBlocksToReceive() const;
- uint blockSize() const;
-
- virtual bool isValid() const;
- static bool isUrlValid(const QUrl &url);
-
-protected:
- explicit QCoapInternalMessage(QCoapInternalMessagePrivate &dd, QObject *parent = nullptr);
-
- void setFromDescriptiveBlockOption(const QCoapOption &option);
-
- Q_DECLARE_PRIVATE(QCoapInternalMessage)
-};
-
-QT_END_NAMESPACE
-
-#endif // QCOAPINTERNALMESSAGE_H
diff --git a/src/coap/qcoapinternalmessage_p.h b/src/coap/qcoapinternalmessage_p.h
index b239ca6..8ed1309 100644
--- a/src/coap/qcoapinternalmessage_p.h
+++ b/src/coap/qcoapinternalmessage_p.h
@@ -31,7 +31,6 @@
#ifndef QCOAPINTERNALMESSAGE_P_H
#define QCOAPINTERNALMESSAGE_P_H
-#include <QtCoap/qcoapinternalmessage.h>
#include <private/qcoapmessage_p.h>
#include <private/qobject_p.h>
@@ -48,6 +47,39 @@
QT_BEGIN_NAMESPACE
+class QCoapInternalMessagePrivate;
+class Q_AUTOTEST_EXPORT QCoapInternalMessage : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QCoapInternalMessage(QObject *parent = nullptr);
+ explicit QCoapInternalMessage(const QCoapMessage &message, QObject *parent = nullptr);
+ QCoapInternalMessage(const QCoapInternalMessage &other, QObject *parent = nullptr);
+ virtual ~QCoapInternalMessage() {}
+
+ void addOption(QCoapOption::OptionName name, const QByteArray &value);
+ void addOption(QCoapOption::OptionName name, quint32 value);
+ virtual void addOption(const QCoapOption &option);
+ void removeOption(QCoapOption::OptionName name);
+
+ QCoapMessage *message();
+ const QCoapMessage *message() const;
+
+ uint currentBlockNumber() const;
+ bool hasMoreBlocksToReceive() const;
+ uint blockSize() const;
+
+ virtual bool isValid() const;
+ static bool isUrlValid(const QUrl &url);
+
+protected:
+ explicit QCoapInternalMessage(QCoapInternalMessagePrivate &dd, QObject *parent = nullptr);
+
+ void setFromDescriptiveBlockOption(const QCoapOption &option);
+
+ Q_DECLARE_PRIVATE(QCoapInternalMessage)
+};
+
class Q_AUTOTEST_EXPORT QCoapInternalMessagePrivate : public QObjectPrivate
{
public:
diff --git a/src/coap/qcoapinternalreply_p.h b/src/coap/qcoapinternalreply_p.h
index cd24b87..db9a052 100644
--- a/src/coap/qcoapinternalreply_p.h
+++ b/src/coap/qcoapinternalreply_p.h
@@ -33,7 +33,6 @@
#include <QtCoap/qcoapglobal.h>
#include <QtCoap/qcoapnamespace.h>
-#include <QtCoap/qcoapinternalmessage.h>
#include <private/qcoapinternalmessage_p.h>
#include <QtNetwork/qhostaddress.h>
@@ -64,7 +63,7 @@ public:
int nextBlockToSend() const;
using QCoapInternalMessage::addOption;
- void addOption(const QCoapOption &option);
+ void addOption(const QCoapOption &option) override;
void setSenderAddress(const QHostAddress &address);
QtCoap::ResponseCode responseCode() const;
diff --git a/src/coap/qcoapinternalrequest_p.h b/src/coap/qcoapinternalrequest_p.h
index df22736..1b50aae 100644
--- a/src/coap/qcoapinternalrequest_p.h
+++ b/src/coap/qcoapinternalrequest_p.h
@@ -35,7 +35,6 @@
#include <QtCoap/qcoapglobal.h>
#include <QtCoap/qcoapnamespace.h>
-#include <QtCoap/qcoapinternalmessage.h>
#include <QtCoap/qcoapconnection.h>
#include <QtCore/qglobal.h>
@@ -64,7 +63,7 @@ public:
explicit QCoapInternalRequest(QObject *parent = nullptr);
explicit QCoapInternalRequest(const QCoapRequest &request, QObject *parent = nullptr);
- bool isValid() const Q_DECL_OVERRIDE;
+ bool isValid() const override;
void initForAcknowledgment(quint16 messageId, const QByteArray &token);
void initForReset(quint16 messageId);
@@ -77,7 +76,7 @@ public:
bool checkBlockNumber(uint blockNumber);
using QCoapInternalMessage::addOption;
- void addOption(const QCoapOption &option) Q_DECL_OVERRIDE;
+ void addOption(const QCoapOption &option) override;
bool addUriOptions(QUrl uri, const QUrl &proxyUri = QUrl());
QCoapToken token() const;
diff --git a/src/coap/qcoapmessage.cpp b/src/coap/qcoapmessage.cpp
index 49e8030..d07611c 100644
--- a/src/coap/qcoapmessage.cpp
+++ b/src/coap/qcoapmessage.cpp
@@ -371,9 +371,15 @@ void QCoapMessage::setMessageId(quint16 id)
}
/*!
- Sets the message payload to \a payload.
+ Sets the message payload to \a payload. The payload can be represented in
+ one of the content formats defined in \l {CoAP Content-Formats Registry}.
- \sa payload()
+ \note CoAP supports common content formats such as XML, JSON, and so on, but
+ these are text based and consequently heavy both in payload and in processing.
+ One of the recommended content formats to use with CoAP is CBOR, which is
+ designed to be used in such contexts.
+
+ \sa payload(), QCborStreamWriter, QCborStreamReader
*/
void QCoapMessage::setPayload(const QByteArray &payload)
{
diff --git a/src/coap/qcoapmessage.h b/src/coap/qcoapmessage.h
index 769c613..550ff88 100644
--- a/src/coap/qcoapmessage.h
+++ b/src/coap/qcoapmessage.h
@@ -53,7 +53,7 @@ public:
QCoapMessage();
QCoapMessage(const QCoapMessage &other);
- virtual ~QCoapMessage();
+ ~QCoapMessage();
void swap(QCoapMessage &other) Q_DECL_NOTHROW;
QCoapMessage &operator=(const QCoapMessage &other);
@@ -79,7 +79,7 @@ public:
QVector<QCoapOption> options(QCoapOption::OptionName name) const;
int optionCount() const;
void addOption(QCoapOption::OptionName name, const QByteArray &value = QByteArray());
- virtual void addOption(const QCoapOption &option);
+ void addOption(const QCoapOption &option);
void removeOption(const QCoapOption &option);
void removeOption(QCoapOption::OptionName name);
void removeAllOptions();
diff --git a/src/coap/qcoapprotocol.h b/src/coap/qcoapprotocol.h
index e7763d9..0c91443 100644
--- a/src/coap/qcoapprotocol.h
+++ b/src/coap/qcoapprotocol.h
@@ -67,7 +67,7 @@ public:
Q_SIGNALS:
void finished(QCoapReply *reply);
- void responseToMulticastReceived(QCoapReply *reply, const QCoapMessage& message,
+ void responseToMulticastReceived(QCoapReply *reply, const QCoapMessage &message,
const QHostAddress &sender);
void error(QCoapReply *reply, QtCoap::Error error);
diff --git a/src/coap/qcoapqudpconnection.cpp b/src/coap/qcoapqudpconnection.cpp
index 636554c..831b23d 100644
--- a/src/coap/qcoapqudpconnection.cpp
+++ b/src/coap/qcoapqudpconnection.cpp
@@ -242,6 +242,30 @@ void QCoapQUdpConnection::writeData(const QByteArray &data, const QString &host,
}
/*!
+ \internal
+
+ \brief Close the UDP socket
+
+ In the case of a secure connection, this also interrupts any ongoing
+ hand-shake and shuts down the DTLS connection.
+*/
+void QCoapQUdpConnection::close()
+{
+ Q_D(QCoapQUdpConnection);
+
+#if QT_CONFIG(dtls)
+ if (isSecure()) {
+ if (d->dtls->handshakeState() == QDtls::HandshakeInProgress)
+ d->dtls->abortHandshake(d->socket());
+
+ if (d->dtls->isConnectionEncrypted())
+ d->dtls->shutdown(d->socket());
+ }
+#endif
+ d->socket()->close();
+}
+
+/*!
Sets the QUdpSocket socket \a option to \a value.
*/
void QCoapQUdpConnection::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
@@ -393,8 +417,10 @@ void QCoapQUdpConnection::handshakeTimeout()
Q_D(QCoapQUdpConnection);
qCWarning(lcCoapConnection, "Handshake timeout, trying to re-transmit");
- if (!d->dtls->handleTimeout(d->udpSocket))
+ if (d->dtls->handshakeState() == QDtls::HandshakeInProgress &&
+ !d->dtls->handleTimeout(d->udpSocket)) {
qCWarning(lcCoapConnection) << "Failed to re-transmit" << d->dtls->dtlsErrorString();
+ }
}
/*!
diff --git a/src/coap/qcoapqudpconnection.h b/src/coap/qcoapqudpconnection.h
index b070d1d..76c5abf 100644
--- a/src/coap/qcoapqudpconnection.h
+++ b/src/coap/qcoapqudpconnection.h
@@ -69,6 +69,7 @@ protected:
void bind(const QString &host, quint16 port) override;
void writeData(const QByteArray &data, const QString &host, quint16 port) override;
+ void close() override;
void createSocket();
diff --git a/src/coap/qcoapreply.h b/src/coap/qcoapreply.h
index 648dc3b..afdd5ea 100644
--- a/src/coap/qcoapreply.h
+++ b/src/coap/qcoapreply.h
@@ -73,8 +73,8 @@ protected:
explicit QCoapReply(QCoapReplyPrivate &dd, QObject *parent = nullptr);
- qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
- qint64 writeData(const char *data, qint64 maxSize) Q_DECL_OVERRIDE;
+ qint64 readData(char *data, qint64 maxSize) override;
+ qint64 writeData(const char *data, qint64 maxSize) override;
Q_DECLARE_PRIVATE(QCoapReply)
Q_PRIVATE_SLOT(d_func(), void _q_setRunning(const QCoapToken &, QCoapMessageId))
diff --git a/src/coap/qcoapresource.cpp b/src/coap/qcoapresource.cpp
index c24950e..7e20209 100644
--- a/src/coap/qcoapresource.cpp
+++ b/src/coap/qcoapresource.cpp
@@ -255,9 +255,15 @@ void QCoapResource::setMaximumSize(int maximumSize)
}
/*!
- Sets the content format of the resource to \a contentFormat.
+ Sets the content format of the resource to \a contentFormat. The content
+ format can be one of the content formats defined in \l {CoAP Content-Formats Registry}.
- \sa contentFormat()
+ \note CoAP supports common content formats such as XML, JSON, and so on, but
+ these are text based and consequently heavy both in payload and in processing.
+ One of the recommended content formats to use with CoAP is CBOR, which is
+ designed to be used in such contexts.
+
+ \sa contentFormat(), QCborStreamWriter, QCborStreamReader
*/
void QCoapResource::setContentFormat(uint contentFormat)
{
diff --git a/tests/auto/qcoapclient/tst_qcoapclient.cpp b/tests/auto/qcoapclient/tst_qcoapclient.cpp
index ee61f70..04db9f4 100644
--- a/tests/auto/qcoapclient/tst_qcoapclient.cpp
+++ b/tests/auto/qcoapclient/tst_qcoapclient.cpp
@@ -154,6 +154,8 @@ public:
Q_UNUSED(port);
// Do nothing
}
+
+ void close() override {}
};
class QCoapClientForMulticastTests : public QCoapClient
diff --git a/tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp b/tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp
index 6b3f0e9..898466d 100644
--- a/tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp
+++ b/tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp
@@ -58,6 +58,7 @@ class tst_QCoapQUdpConnection : public QObject
private Q_SLOTS:
void ctor();
void connectToHost();
+ void reconnect();
void sendRequest_data();
void sendRequest();
};
@@ -105,6 +106,29 @@ void tst_QCoapQUdpConnection::connectToHost()
#endif
}
+void tst_QCoapQUdpConnection::reconnect()
+{
+#ifdef QT_BUILD_INTERNAL
+ QCoapQUdpConnectionForTest connection;
+
+ // This will trigger connection.bind()
+ QSignalSpy connectionBoundSpy(&connection, SIGNAL(bound()));
+ connection.sendRequest(QByteArray(), QString(), 0);
+ QTRY_COMPARE(connectionBoundSpy.count(), 1);
+ QCOMPARE(connection.state(), QCoapQUdpConnection::Bound);
+
+ connection.disconnect();
+ QCOMPARE(connection.state(), QCoapQUdpConnection::Unconnected);
+
+ // Make sure that we are able to connect again
+ connection.sendRequest(QByteArray(), QString(), 0);
+ QTRY_COMPARE(connectionBoundSpy.count(), 2);
+ QCOMPARE(connection.state(), QCoapQUdpConnection::Bound);
+#else
+ QSKIP("Not an internal build, skipping this test");
+#endif
+}
+
void tst_QCoapQUdpConnection::sendRequest_data()
{
QTest::addColumn<QString>("protocol");