diff options
author | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2018-08-09 11:19:26 +0200 |
---|---|---|
committer | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2018-08-14 03:47:11 +0000 |
commit | c4edb58edcfeea89cf4bb68d72138594a912de40 (patch) | |
tree | 3017ce94478b0d1f130c77f83bc4e148dcfb31ef | |
parent | 5ef7e409fb3b4a5f44a424b5f1998437478ccccc (diff) |
Add support for reading reason codes during connection
Connection aknowledgement contains reason codes, which should be
reflected to the user. As QMqttServerConnectionProperties already might
store the reason string, it is best to combine them.
Change-Id: I363be54216204cc695309ddd658996d350ea3f09
Reviewed-by: hjk <hjk@qt.io>
-rw-r--r-- | src/mqtt/qmqttclient.h | 3 | ||||
-rw-r--r-- | src/mqtt/qmqttconnection.cpp | 89 | ||||
-rw-r--r-- | src/mqtt/qmqttconnection_p.h | 2 | ||||
-rw-r--r-- | src/mqtt/qmqttconnectionproperties.cpp | 8 | ||||
-rw-r--r-- | src/mqtt/qmqttconnectionproperties.h | 1 | ||||
-rw-r--r-- | src/mqtt/qmqttconnectionproperties_p.h | 1 | ||||
-rw-r--r-- | src/mqtt/qmqttglobal.h | 17 |
7 files changed, 73 insertions, 48 deletions
diff --git a/src/mqtt/qmqttclient.h b/src/mqtt/qmqttclient.h index f818c3c..92e114b 100644 --- a/src/mqtt/qmqttclient.h +++ b/src/mqtt/qmqttclient.h @@ -71,7 +71,8 @@ public: // Qt states TransportInvalid = 256, ProtocolViolation, - UnknownError + UnknownError, + Mqtt5SpecificError }; enum ProtocolVersion { MQTT_3_1 = 3, diff --git a/src/mqtt/qmqttconnection.cpp b/src/mqtt/qmqttconnection.cpp index d86e8ca..a93a727 100644 --- a/src/mqtt/qmqttconnection.cpp +++ b/src/mqtt/qmqttconnection.cpp @@ -770,119 +770,118 @@ void QMqttConnection::readAuthProperties(QMqttAuthenticationProperties &properti properties.setUserProperties(userProperties); } -void QMqttConnection::readConnackProperties() +void QMqttConnection::readConnackProperties(QMqttServerConnectionProperties &properties) { qint64 propertyLength = readVariableByteInteger(); m_missingData = 0; - QMqttServerConnectionProperties serverProperties; - serverProperties.serverData->valid = true; + properties.serverData->valid = true; while (propertyLength > 0) { quint8 propertyId = readBufferTyped<quint8>(&propertyLength); switch (propertyId) { case 0x11: { // 3.2.2.3.2 Session Expiry Interval const quint32 expiryInterval = readBufferTyped<quint32>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::SessionExpiryInterval; - serverProperties.setSessionExpiryInterval(expiryInterval); + properties.serverData->details |= QMqttServerConnectionProperties::SessionExpiryInterval; + properties.setSessionExpiryInterval(expiryInterval); break; } case 0x21: { // 3.2.2.3.3 Receive Maximum const quint16 receiveMaximum = readBufferTyped<quint16>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::MaximumReceive; - serverProperties.setMaximumReceive(receiveMaximum); + properties.serverData->details |= QMqttServerConnectionProperties::MaximumReceive; + properties.setMaximumReceive(receiveMaximum); break; } case 0x24: { // 3.2.2.3.4 Maximum QoS Level const quint8 maxQoS = readBufferTyped<quint8>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::MaximumQoS; - serverProperties.serverData->maximumQoS = maxQoS; + properties.serverData->details |= QMqttServerConnectionProperties::MaximumQoS; + properties.serverData->maximumQoS = maxQoS; break; } case 0x25: { // 3.2.2.3.5 Retain available const quint8 retainAvailable = readBufferTyped<quint8>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::RetainAvailable; - serverProperties.serverData->retainAvailable = retainAvailable == 1; + properties.serverData->details |= QMqttServerConnectionProperties::RetainAvailable; + properties.serverData->retainAvailable = retainAvailable == 1; break; } case 0x27: { // 3.2.2.3.6 Maximum packet size const quint32 maxPacketSize = readBufferTyped<quint32>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::MaximumPacketSize; - serverProperties.setMaximumPacketSize(maxPacketSize); + properties.serverData->details |= QMqttServerConnectionProperties::MaximumPacketSize; + properties.setMaximumPacketSize(maxPacketSize); break; } case 0x12: { // 3.2.2.3.7 Assigned clientId const QString assignedClientId = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::AssignedClientId; + properties.serverData->details |= QMqttServerConnectionProperties::AssignedClientId; m_clientPrivate->setClientId(assignedClientId); break; } case 0x22: { // 3.2.2.3.8 Topic Alias Maximum const quint16 topicAliasMaximum = readBufferTyped<quint16>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::MaximumTopicAlias; - serverProperties.setMaximumTopicAlias(topicAliasMaximum); + properties.serverData->details |= QMqttServerConnectionProperties::MaximumTopicAlias; + properties.setMaximumTopicAlias(topicAliasMaximum); break; } case 0x1F: { // 3.2.2.3.9 Reason String const QString reasonString = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::ReasonString; - serverProperties.serverData->reasonString = reasonString; + properties.serverData->details |= QMqttServerConnectionProperties::ReasonString; + properties.serverData->reasonString = reasonString; break; } case 0x26: { // 3.2.2.3.10 User property const QString propertyName = readBufferTyped<QString>(&propertyLength); const QString propertyValue = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::UserProperty; - serverProperties.data->userProperties.append(QMqttStringPair(propertyName, propertyValue)); + properties.serverData->details |= QMqttServerConnectionProperties::UserProperty; + properties.data->userProperties.append(QMqttStringPair(propertyName, propertyValue)); break; } case 0x28: { // 3.2.2.3.11 Wildcard subscriptions available const quint8 available = readBufferTyped<quint8>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::WildCardSupported; - serverProperties.serverData->wildcardSupported = available == 1; + properties.serverData->details |= QMqttServerConnectionProperties::WildCardSupported; + properties.serverData->wildcardSupported = available == 1; break; } case 0x29: { // 3.2.2.3.12 Subscription identifiers available const quint8 available = readBufferTyped<quint8>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::SubscriptionIdentifierSupport; - serverProperties.serverData->subscriptionIdentifierSupported = available == 1; + properties.serverData->details |= QMqttServerConnectionProperties::SubscriptionIdentifierSupport; + properties.serverData->subscriptionIdentifierSupported = available == 1; break; } case 0x2A: { // 3.2.2.3.13 Shared subscriptions available const quint8 available = readBufferTyped<quint8>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::SharedSubscriptionSupport; - serverProperties.serverData->sharedSubscriptionSupported = available == 1; + properties.serverData->details |= QMqttServerConnectionProperties::SharedSubscriptionSupport; + properties.serverData->sharedSubscriptionSupported = available == 1; break; } case 0x13: { // 3.2.2.3.14 Server Keep Alive const quint16 serverKeepAlive = readBufferTyped<quint16>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::ServerKeepAlive; + properties.serverData->details |= QMqttServerConnectionProperties::ServerKeepAlive; m_clientPrivate->m_client->setKeepAlive(serverKeepAlive); break; } case 0x1A: { // 3.2.2.3.15 Response information const QString responseInfo = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::ResponseInformation; - serverProperties.serverData->responseInformation = responseInfo; + properties.serverData->details |= QMqttServerConnectionProperties::ResponseInformation; + properties.serverData->responseInformation = responseInfo; break; } case 0x1C: { // 3.2.2.3.16 Server reference const QString serverReference = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::ServerReference; - serverProperties.serverData->serverReference = serverReference; + properties.serverData->details |= QMqttServerConnectionProperties::ServerReference; + properties.serverData->serverReference = serverReference; break; } case 0x15: { // 3.2.2.3.17 Authentication method const QString method = readBufferTyped<QString>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::AuthenticationMethod; - serverProperties.data->authenticationMethod = method; + properties.serverData->details |= QMqttServerConnectionProperties::AuthenticationMethod; + properties.data->authenticationMethod = method; break; } case 0x16: { // 3.2.2.3.18 Authentication data const QByteArray data = readBufferTyped<QByteArray>(&propertyLength); - serverProperties.serverData->details |= QMqttServerConnectionProperties::AuthenticationData; - serverProperties.data->authenticationData = data; + properties.serverData->details |= QMqttServerConnectionProperties::AuthenticationData; + properties.data->authenticationData = data; break; } default: @@ -890,7 +889,6 @@ void QMqttConnection::readConnackProperties() break; } } - m_clientPrivate->m_serverConnectionProperties = serverProperties; } void QMqttConnection::readMessageStatusProperties(QMqttMessageStatusProperties &properties) @@ -1400,23 +1398,24 @@ void QMqttConnection::finalize_connack() } quint8 connectResultValue = readBufferTyped<quint8>(&m_missingData); - if (connectResultValue != 0) { + QMqttServerConnectionProperties serverProp; + serverProp.serverData->reasonCode = QMqtt::ReasonCode(connectResultValue); + if (connectResultValue != 0 && m_clientPrivate->m_protocolVersion != QMqttClient::MQTT_5_0) { qCDebug(lcMqttConnection) << "Connection has been rejected."; - // MQTT-3.2.2-5 - m_readBuffer.clear(); - m_readPosition = 0; - m_transport->close(); - m_internalState = BrokerDisconnected; - // Table 3.1, values 1-5 - m_clientPrivate->setStateAndError(QMqttClient::Disconnected, static_cast<QMqttClient::ClientError>(connectResultValue)); + closeConnection(static_cast<QMqttClient::ClientError>(connectResultValue)); return; } // MQTT 5.0 has variable part != 2 in the header if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) { - readConnackProperties(); + readConnackProperties(serverProp); + m_clientPrivate->m_serverConnectionProperties = serverProp; m_receiveAliases.resize(m_clientPrivate->m_serverConnectionProperties.maximumTopicAlias()); m_publishAliases.resize(m_clientPrivate->m_connectionProperties.maximumTopicAlias()); + if (connectResultValue != 0) { + closeConnection(QMqttClient::Mqtt5SpecificError); + return; + } } m_internalState = BrokerConnected; diff --git a/src/mqtt/qmqttconnection_p.h b/src/mqtt/qmqttconnection_p.h index f703599..cfe1641 100644 --- a/src/mqtt/qmqttconnection_p.h +++ b/src/mqtt/qmqttconnection_p.h @@ -121,7 +121,7 @@ private: void readBuffer(char *data, quint64 size); qint32 readVariableByteInteger(qint32 *byteCount = nullptr); void readAuthProperties(QMqttAuthenticationProperties &properties); - void readConnackProperties(); + void readConnackProperties(QMqttServerConnectionProperties &properties); void readMessageStatusProperties(QMqttMessageStatusProperties &properties); void readPublishProperties(QMqttPublishProperties &properties); void readSubscriptionProperties(QMqttSubscription *sub); diff --git a/src/mqtt/qmqttconnectionproperties.cpp b/src/mqtt/qmqttconnectionproperties.cpp index 68647ec..aae5b58 100644 --- a/src/mqtt/qmqttconnectionproperties.cpp +++ b/src/mqtt/qmqttconnectionproperties.cpp @@ -579,6 +579,14 @@ QString QMqttServerConnectionProperties::reason() const } /*! + Returns the reason code associated with this response. +*/ +QMqtt::ReasonCode QMqttServerConnectionProperties::reasonCode() const +{ + return serverData->reasonCode; +} + +/*! Returns \c true if the server accepts subscriptions including wildcards. The default value is \c true. */ diff --git a/src/mqtt/qmqttconnectionproperties.h b/src/mqtt/qmqttconnectionproperties.h index 61ded91..8741f76 100644 --- a/src/mqtt/qmqttconnectionproperties.h +++ b/src/mqtt/qmqttconnectionproperties.h @@ -145,6 +145,7 @@ public: bool retainAvailable() const; bool clientIdAssigned() const; QString reason() const; + QMqtt::ReasonCode reasonCode() const; bool wildcardSupported() const; bool subscriptionIdentifierSupported() const; bool sharedSubscriptionSupported() const; diff --git a/src/mqtt/qmqttconnectionproperties_p.h b/src/mqtt/qmqttconnectionproperties_p.h index ab2012b..561fdb3 100644 --- a/src/mqtt/qmqttconnectionproperties_p.h +++ b/src/mqtt/qmqttconnectionproperties_p.h @@ -80,6 +80,7 @@ public: QString serverReference; quint16 serverKeepAlive{0}; quint8 maximumQoS{2}; + QMqtt::ReasonCode reasonCode{QMqtt::ReasonCode::Success}; bool valid{false}; // Only set to true after CONNACK bool retainAvailable{true}; bool wildcardSupported{true}; diff --git a/src/mqtt/qmqttglobal.h b/src/mqtt/qmqttglobal.h index dfe2971..28a91e8 100644 --- a/src/mqtt/qmqttglobal.h +++ b/src/mqtt/qmqttglobal.h @@ -64,13 +64,28 @@ enum class ReasonCode : quint16 { Success = 0, NoMatchingSubscriber = 0x10, UnspecifiedError = 0x80, + MalformedPacket = 0x81, + ProtocolError = 0x82, ImplementationSpecificError = 0x83, + UnsupportedProtocolVersion = 0x84, + InvalidClientId = 0x85, + InvalidUserNameOrPassword = 0x86, NotAuthorized = 0x87, + ServerNotAvailable = 0x88, + ServerBusy = 0x89, + ClientBanned = 0x8A, + InvalidAuthenticationMethod = 0x8C, InvalidTopicName = 0x90, MessageIdInUse = 0x91, MessageIdNotFound = 0x92, + PacketTooLarge = 0x95, QuotaExceeded = 0x97, - InvalidPayloadFormat = 0x99 + InvalidPayloadFormat = 0x99, + RetainNotSupported = 0x9A, + QoSNotSupported = 0x9B, + UseAnotherServer = 0x9C, + ServerMoved = 0x9D, + ExceededConnectionRate = 0x9F }; } QT_END_NAMESPACE |