diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-04-27 03:02:26 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-04-27 03:02:26 +0200 |
commit | 2050395003076fea84a8bdcc3948e8b50262a39c (patch) | |
tree | 477a35cae6dcdb69786cd7bcd08ab76b371a8d92 | |
parent | 3cf3afbe59c8d6e6cf8d49a7155345bad1257def (diff) | |
parent | e8b9f3c8a91a0071afd315c2455772652b976f48 (diff) |
Merge remote-tracking branch 'origin/5.13' into dev
Change-Id: If912f4f8c24075c6947f5c22bb70bdba57d1e8ae
-rw-r--r-- | examples/coap/doc/images/quickmulticastclient.png | bin | 0 -> 17289 bytes | |||
-rw-r--r-- | examples/coap/doc/quickmulticastclient.qdoc | 127 | ||||
-rw-r--r-- | src/coap/coap.pro | 1 | ||||
-rw-r--r-- | src/coap/doc/src/external-resources.qdoc | 5 | ||||
-rw-r--r-- | src/coap/qcoapclient.cpp | 11 | ||||
-rw-r--r-- | src/coap/qcoapclient.h | 3 | ||||
-rw-r--r-- | src/coap/qcoapconnection.cpp | 41 | ||||
-rw-r--r-- | src/coap/qcoapconnection.h | 2 | ||||
-rw-r--r-- | src/coap/qcoapdiscoveryreply_p.h | 2 | ||||
-rw-r--r-- | src/coap/qcoapinternalmessage.h | 74 | ||||
-rw-r--r-- | src/coap/qcoapinternalmessage_p.h | 34 | ||||
-rw-r--r-- | src/coap/qcoapinternalreply_p.h | 3 | ||||
-rw-r--r-- | src/coap/qcoapinternalrequest_p.h | 5 | ||||
-rw-r--r-- | src/coap/qcoapmessage.cpp | 10 | ||||
-rw-r--r-- | src/coap/qcoapmessage.h | 4 | ||||
-rw-r--r-- | src/coap/qcoapprotocol.h | 2 | ||||
-rw-r--r-- | src/coap/qcoapqudpconnection.cpp | 28 | ||||
-rw-r--r-- | src/coap/qcoapqudpconnection.h | 1 | ||||
-rw-r--r-- | src/coap/qcoapreply.h | 4 | ||||
-rw-r--r-- | src/coap/qcoapresource.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qcoapclient/tst_qcoapclient.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qcoapqudpconnection/tst_qcoapqudpconnection.cpp | 24 |
22 files changed, 290 insertions, 103 deletions
diff --git a/examples/coap/doc/images/quickmulticastclient.png b/examples/coap/doc/images/quickmulticastclient.png Binary files differnew file mode 100644 index 0000000..3339db1 --- /dev/null +++ b/examples/coap/doc/images/quickmulticastclient.png 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"); |