diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-05-18 08:44:14 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-05-18 08:44:14 +0200 |
commit | 51ef71daac2133961ea517dd1fdadc0adb1444ee (patch) | |
tree | 3de13f9682dd8be09e1cb2ab8e34655b244bdd48 | |
parent | e37ad0585120f9419429f523016d4b8ede69930a (diff) | |
parent | e6c2ddfc2a01c0cc4e3b5790b0de2a7dc3947581 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I5e3459f90c8131cf8b00a1a7aed301f6d3d0e8f7
-rw-r--r-- | src/mqtt/qmqttconnection.cpp | 69 | ||||
-rw-r--r-- | src/mqtt/qmqttglobal.h | 1 | ||||
-rw-r--r-- | src/mqtt/qmqttsubscription.cpp | 1 | ||||
-rw-r--r-- | src/mqtt/qmqtttype.cpp | 2 |
4 files changed, 56 insertions, 17 deletions
diff --git a/src/mqtt/qmqttconnection.cpp b/src/mqtt/qmqttconnection.cpp index 10e028e..8eb0c65 100644 --- a/src/mqtt/qmqttconnection.cpp +++ b/src/mqtt/qmqttconnection.cpp @@ -466,6 +466,17 @@ QMqttSubscription *QMqttConnection::sendControlSubscribe(const QMqttTopicFilter { qCDebug(lcMqttConnection) << Q_FUNC_INFO << " Topic:" << topic << " qos:" << qos; + // Overflow protection + if (Q_UNLIKELY(!topic.isValid())) { + qCWarning(lcMqttConnection) << "Invalid subscription topic filter."; + return nullptr; + } + + if (Q_UNLIKELY(qos > 2)) { + qCWarning(lcMqttConnection) << "Invalid subscription QoS."; + return nullptr; + } + if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) { const QString sharedSubscriptionName = topic.sharedSubscriptionName(); if (!sharedSubscriptionName.isEmpty()) { @@ -497,20 +508,8 @@ QMqttSubscription *QMqttConnection::sendControlSubscribe(const QMqttTopicFilter if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) packet.appendRaw(writeSubscriptionProperties(properties)); - // Overflow protection - if (!topic.isValid()) { - qCDebug(lcMqttConnection) << "Invalid subscription topic filter."; - return nullptr; - } - packet.append(topic.filter().toUtf8()); - - switch (qos) { - case 0: packet.append(char(0x0)); break; - case 1: packet.append(char(0x1)); break; - case 2: packet.append(char(0x2)); break; - default: return nullptr; - } + packet.append(char(qos)); auto result = new QMqttSubscription(this); result->setTopic(topic); @@ -1521,7 +1520,9 @@ void QMqttConnection::finalize_suback() if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) readSubscriptionProperties(sub); - while (m_missingData > 0) { + // 3.9.3 - The Payload contains a list of Reason Codes. Each Reason Code corresponds to a Topic Filter in the SUBSCRIBE packet being acknowledged. + // Whereas 3.8.3 states "The Payload MUST contain at least one Topic Filter and Subscription Options pair. A SUBSCRIBE packet with no Payload is a Protocol Error." + do { quint8 reason = readBufferTyped<quint8>(&m_missingData); sub->d_func()->m_reasonCode = QMqtt::ReasonCode(reason); @@ -1563,7 +1564,7 @@ void QMqttConnection::finalize_suback() closeConnection(QMqttClient::ProtocolViolation); break; } - } + } while (m_missingData > 0); } void QMqttConnection::finalize_unsuback() @@ -1577,8 +1578,44 @@ void QMqttConnection::finalize_unsuback() return; } - sub->setState(QMqttSubscription::Unsubscribed); m_activeSubscriptions.remove(sub->topic()); + + if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) { + readSubscriptionProperties(sub); + } else { + // 3.11.3 - The UNSUBACK Packet has no payload. + // emulate successful unsubscription + sub->d_func()->m_reasonCode = QMqtt::ReasonCode::Success; + sub->setState(QMqttSubscription::Unsubscribed); + return; + } + + // 3.1.3 - The Payload contains a list of Reason Codes. Each Reason Code corresponds to a Topic Filter in the UNSUBSCRIBE packet being acknowledged. + // Whereas 3.10.3 states "The Payload of an UNSUBSCRIBE packet MUST contain at least one Topic Filter. An UNSUBSCRIBE packet with no Payload is a Protocol Error." + do { + const quint8 reasonCode = readBufferTyped<quint8>(&m_missingData); + sub->d_func()->m_reasonCode = QMqtt::ReasonCode(reasonCode); + + // 3.11.3 + switch (QMqtt::ReasonCode(reasonCode)) { + case QMqtt::ReasonCode::Success: + sub->setState(QMqttSubscription::Unsubscribed); + break; + case QMqtt::ReasonCode::NoSubscriptionExisted: + case QMqtt::ReasonCode::ImplementationSpecificError: + case QMqtt::ReasonCode::NotAuthorized: + case QMqtt::ReasonCode::InvalidTopicFilter: + case QMqtt::ReasonCode::MessageIdInUse: + case QMqtt::ReasonCode::UnspecifiedError: + qCWarning(lcMqttConnection) << "Unsubscription for id " << id << " failed. Reason Code:" << reasonCode; + sub->setState(QMqttSubscription::Error); + break; + default: + qCWarning(lcMqttConnection) << "Received illegal UNSUBACK reason code:" << reasonCode; + closeConnection(QMqttClient::ProtocolViolation); + break; + } + } while (m_missingData > 0); } void QMqttConnection::finalize_publish() diff --git a/src/mqtt/qmqttglobal.h b/src/mqtt/qmqttglobal.h index 922f345..411236a 100644 --- a/src/mqtt/qmqttglobal.h +++ b/src/mqtt/qmqttglobal.h @@ -66,6 +66,7 @@ enum class ReasonCode : quint8 { SubscriptionQoSLevel1 = 0x01, SubscriptionQoSLevel2 = 0x02, NoMatchingSubscriber = 0x10, + NoSubscriptionExisted = 0x11, ContinueAuthentication = 0x18, ReAuthenticate = 0x19, UnspecifiedError = 0x80, diff --git a/src/mqtt/qmqttsubscription.cpp b/src/mqtt/qmqttsubscription.cpp index 2b526a9..cf9d555 100644 --- a/src/mqtt/qmqttsubscription.cpp +++ b/src/mqtt/qmqttsubscription.cpp @@ -209,7 +209,6 @@ void QMqttSubscription::unsubscribe() { Q_D(QMqttSubscription); d->m_client->unsubscribe(d->m_topic); - setState(Unsubscribed); } void QMqttSubscription::setTopic(const QMqttTopicFilter &topic) diff --git a/src/mqtt/qmqtttype.cpp b/src/mqtt/qmqtttype.cpp index 23d60b4..5b8cdaf 100644 --- a/src/mqtt/qmqtttype.cpp +++ b/src/mqtt/qmqtttype.cpp @@ -136,6 +136,8 @@ QT_BEGIN_NAMESPACE The message has been accepted by the server, but there are no subscribers to receive this message. A broker may send this reason code instead of \l Success. + \value [since 5.15] NoSubscriptionExisted + No matching Topic Filter is being used by the Client. \value [since 5.15] ContinueAuthentication Continue the authentication with another step. \value [since 5.15] ReAuthenticate |