summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-05-18 08:44:14 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-05-18 08:44:14 +0200
commit51ef71daac2133961ea517dd1fdadc0adb1444ee (patch)
tree3de13f9682dd8be09e1cb2ab8e34655b244bdd48
parente37ad0585120f9419429f523016d4b8ede69930a (diff)
parente6c2ddfc2a01c0cc4e3b5790b0de2a7dc3947581 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
-rw-r--r--src/mqtt/qmqttconnection.cpp69
-rw-r--r--src/mqtt/qmqttglobal.h1
-rw-r--r--src/mqtt/qmqttsubscription.cpp1
-rw-r--r--src/mqtt/qmqtttype.cpp2
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