Commit 313b3346c39903b76a835d8a211c0679191bf26b
1 parent
9a34fc46
Connect/connack in mqtt5
Showing
10 changed files
with
352 additions
and
20 deletions
CMakeLists.txt
| @@ -60,6 +60,7 @@ add_executable(FlashMQ | @@ -60,6 +60,7 @@ add_executable(FlashMQ | ||
| 60 | threadloop.h | 60 | threadloop.h |
| 61 | publishcopyfactory.h | 61 | publishcopyfactory.h |
| 62 | variablebyteint.h | 62 | variablebyteint.h |
| 63 | + mqtt5properties.h | ||
| 63 | 64 | ||
| 64 | mainapp.cpp | 65 | mainapp.cpp |
| 65 | main.cpp | 66 | main.cpp |
| @@ -99,6 +100,7 @@ add_executable(FlashMQ | @@ -99,6 +100,7 @@ add_executable(FlashMQ | ||
| 99 | threadloop.cpp | 100 | threadloop.cpp |
| 100 | publishcopyfactory.cpp | 101 | publishcopyfactory.cpp |
| 101 | variablebyteint.cpp | 102 | variablebyteint.cpp |
| 103 | + mqtt5properties.cpp | ||
| 102 | 104 | ||
| 103 | ) | 105 | ) |
| 104 | 106 |
forward_declarations.h
| @@ -26,6 +26,7 @@ class MqttPacket; | @@ -26,6 +26,7 @@ class MqttPacket; | ||
| 26 | class SubscriptionStore; | 26 | class SubscriptionStore; |
| 27 | class Session; | 27 | class Session; |
| 28 | class Settings; | 28 | class Settings; |
| 29 | +class Mqtt5PropertyBuilder; | ||
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | #endif // FORWARD_DECLARATIONS_H | 32 | #endif // FORWARD_DECLARATIONS_H |
mqtt5properties.cpp
0 → 100644
| 1 | +#include "mqtt5properties.h" | ||
| 2 | + | ||
| 3 | +#include "cstring" | ||
| 4 | + | ||
| 5 | +#include "exceptions.h" | ||
| 6 | + | ||
| 7 | +Mqtt5PropertyBuilder::Mqtt5PropertyBuilder() | ||
| 8 | +{ | ||
| 9 | + bites.reserve(128); | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +size_t Mqtt5PropertyBuilder::getLength() const | ||
| 13 | +{ | ||
| 14 | + return length.getLen() + bites.size(); | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +const VariableByteInt &Mqtt5PropertyBuilder::getVarInt() const | ||
| 18 | +{ | ||
| 19 | + return length; | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +const std::vector<char> &Mqtt5PropertyBuilder::getBites() const | ||
| 23 | +{ | ||
| 24 | + return bites; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +void Mqtt5PropertyBuilder::writeSessionExpiry(uint32_t val) | ||
| 28 | +{ | ||
| 29 | + writeUint32(Mqtt5Properties::SessionExpiryInterval, val); | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +void Mqtt5PropertyBuilder::writeReceiveMax(uint16_t val) | ||
| 33 | +{ | ||
| 34 | + writeUint16(Mqtt5Properties::ReceiveMaximum, val); | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +void Mqtt5PropertyBuilder::writeRetainAvailable(uint8_t val) | ||
| 38 | +{ | ||
| 39 | + writeUint8(Mqtt5Properties::RetainAvailable, val); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +void Mqtt5PropertyBuilder::writeMaxPacketSize(uint32_t val) | ||
| 43 | +{ | ||
| 44 | + writeUint32(Mqtt5Properties::MaximumPacketSize, val); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void Mqtt5PropertyBuilder::writeAssignedClientId(const std::string &clientid) | ||
| 48 | +{ | ||
| 49 | + writeStr(Mqtt5Properties::AssignedClientIdentifier, clientid); | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +void Mqtt5PropertyBuilder::writeMaxTopicAliases(uint16_t val) | ||
| 53 | +{ | ||
| 54 | + writeUint16(Mqtt5Properties::TopicAliasMaximum, val); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +void Mqtt5PropertyBuilder::writeWildcardSubscriptionAvailable(uint8_t val) | ||
| 58 | +{ | ||
| 59 | + writeUint8(Mqtt5Properties::WildcardSubscriptionAvailable, val); | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +void Mqtt5PropertyBuilder::writeSharedSubscriptionAvailable(uint8_t val) | ||
| 63 | +{ | ||
| 64 | + writeUint8(Mqtt5Properties::SharedSubscriptionAvailable, val); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +void Mqtt5PropertyBuilder::writeUint32(Mqtt5Properties prop, const uint32_t x) | ||
| 68 | +{ | ||
| 69 | + size_t pos = bites.size(); | ||
| 70 | + const size_t newSize = pos + 5; | ||
| 71 | + bites.resize(newSize); | ||
| 72 | + this->length = newSize; | ||
| 73 | + | ||
| 74 | + const uint8_t a = static_cast<uint8_t>(x >> 24); | ||
| 75 | + const uint8_t b = static_cast<uint8_t>(x >> 16); | ||
| 76 | + const uint8_t c = static_cast<uint8_t>(x >> 8); | ||
| 77 | + const uint8_t d = static_cast<uint8_t>(x); | ||
| 78 | + | ||
| 79 | + bites[pos++] = static_cast<uint8_t>(prop); | ||
| 80 | + bites[pos++] = a; | ||
| 81 | + bites[pos++] = b; | ||
| 82 | + bites[pos++] = c; | ||
| 83 | + bites[pos] = d; | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +void Mqtt5PropertyBuilder::writeUint16(Mqtt5Properties prop, const uint16_t x) | ||
| 87 | +{ | ||
| 88 | + size_t pos = bites.size(); | ||
| 89 | + const size_t newSize = pos + 3; | ||
| 90 | + bites.resize(newSize); | ||
| 91 | + this->length = newSize; | ||
| 92 | + | ||
| 93 | + const uint8_t a = static_cast<uint8_t>(x >> 8); | ||
| 94 | + const uint8_t b = static_cast<uint8_t>(x); | ||
| 95 | + | ||
| 96 | + bites[pos++] = static_cast<uint8_t>(prop); | ||
| 97 | + bites[pos++] = a; | ||
| 98 | + bites[pos] = b; | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +void Mqtt5PropertyBuilder::writeUint8(Mqtt5Properties prop, const uint8_t x) | ||
| 102 | +{ | ||
| 103 | + size_t pos = bites.size(); | ||
| 104 | + const size_t newSize = pos + 2; | ||
| 105 | + bites.resize(newSize); | ||
| 106 | + this->length = newSize; | ||
| 107 | + | ||
| 108 | + bites[pos++] = static_cast<uint8_t>(prop); | ||
| 109 | + bites[pos] = x; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +void Mqtt5PropertyBuilder::writeStr(Mqtt5Properties prop, const std::string &str) | ||
| 113 | +{ | ||
| 114 | + if (str.length() > 65535) | ||
| 115 | + throw ProtocolError("String too long."); | ||
| 116 | + | ||
| 117 | + const uint16_t strlen = str.length(); | ||
| 118 | + | ||
| 119 | + size_t pos = bites.size(); | ||
| 120 | + const size_t newSize = pos + strlen + 2; | ||
| 121 | + bites.resize(newSize); | ||
| 122 | + this->length = newSize; | ||
| 123 | + | ||
| 124 | + const uint8_t a = static_cast<uint8_t>(strlen >> 8); | ||
| 125 | + const uint8_t b = static_cast<uint8_t>(strlen); | ||
| 126 | + | ||
| 127 | + bites[pos++] = static_cast<uint8_t>(prop); | ||
| 128 | + bites[pos++] = a; | ||
| 129 | + bites[pos++] = b; | ||
| 130 | + | ||
| 131 | + std::memcpy(&bites[pos], str.c_str(), strlen); | ||
| 132 | +} | ||
| 133 | + |
mqtt5properties.h
0 → 100644
| 1 | +#ifndef MQTT5PROPERTIES_H | ||
| 2 | +#define MQTT5PROPERTIES_H | ||
| 3 | + | ||
| 4 | +#include <vector> | ||
| 5 | + | ||
| 6 | +#include "types.h" | ||
| 7 | +#include "variablebyteint.h" | ||
| 8 | + | ||
| 9 | +class Mqtt5PropertyBuilder | ||
| 10 | +{ | ||
| 11 | + std::vector<char> bites; | ||
| 12 | + VariableByteInt length; | ||
| 13 | + | ||
| 14 | + void writeUint32(Mqtt5Properties prop, const uint32_t x); | ||
| 15 | + void writeUint16(Mqtt5Properties prop, const uint16_t x); | ||
| 16 | + void writeUint8(Mqtt5Properties prop, const uint8_t x); | ||
| 17 | + void writeStr(Mqtt5Properties prop, const std::string &str); | ||
| 18 | +public: | ||
| 19 | + Mqtt5PropertyBuilder(); | ||
| 20 | + | ||
| 21 | + size_t getLength() const; | ||
| 22 | + const VariableByteInt &getVarInt() const; | ||
| 23 | + const std::vector<char> &getBites() const; | ||
| 24 | + | ||
| 25 | + void writeSessionExpiry(uint32_t val); | ||
| 26 | + void writeReceiveMax(uint16_t val); | ||
| 27 | + void writeRetainAvailable(uint8_t val); | ||
| 28 | + void writeMaxPacketSize(uint32_t val); | ||
| 29 | + void writeAssignedClientId(const std::string &clientid); | ||
| 30 | + void writeMaxTopicAliases(uint16_t val); | ||
| 31 | + void writeWildcardSubscriptionAvailable(uint8_t val); | ||
| 32 | + void writeSharedSubscriptionAvailable(uint8_t val); | ||
| 33 | +}; | ||
| 34 | + | ||
| 35 | +#endif // MQTT5PROPERTIES_H |
mqttpacket.cpp
| @@ -110,17 +110,20 @@ std::shared_ptr<MqttPacket> MqttPacket::getCopy(char new_max_qos) const | @@ -110,17 +110,20 @@ std::shared_ptr<MqttPacket> MqttPacket::getCopy(char new_max_qos) const | ||
| 110 | return copyPacket; | 110 | return copyPacket; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | -// This constructor cheats and doesn't use calculateRemainingLength, because it's always the same. It allocates enough space in the vector. | ||
| 114 | MqttPacket::MqttPacket(const ConnAck &connAck) : | 113 | MqttPacket::MqttPacket(const ConnAck &connAck) : |
| 115 | - bites(connAck.getLengthWithoutFixedHeader() + 2) | 114 | + bites(connAck.getLengthWithoutFixedHeader()) |
| 116 | { | 115 | { |
| 117 | - fixed_header_length = 2; | ||
| 118 | packetType = PacketType::CONNACK; | 116 | packetType = PacketType::CONNACK; |
| 119 | first_byte = static_cast<char>(packetType) << 4; | 117 | first_byte = static_cast<char>(packetType) << 4; |
| 120 | - writeByte(first_byte); | ||
| 121 | - writeByte(2); // length is always 2. | ||
| 122 | writeByte(connAck.session_present & 0b00000001); // all connect-ack flags are 0, except session-present. [MQTT-3.2.2.1] | 118 | writeByte(connAck.session_present & 0b00000001); // all connect-ack flags are 0, except session-present. [MQTT-3.2.2.1] |
| 123 | - writeByte(static_cast<char>(connAck.return_code)); | 119 | + writeByte(connAck.return_code); |
| 120 | + | ||
| 121 | + if (connAck.protocol_version >= ProtocolVersion::Mqtt5) | ||
| 122 | + { | ||
| 123 | + writeProperties(connAck.propertyBuilder); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + calculateRemainingLength(); | ||
| 124 | } | 127 | } |
| 125 | 128 | ||
| 126 | MqttPacket::MqttPacket(const SubAck &subAck) : | 129 | MqttPacket::MqttPacket(const SubAck &subAck) : |
| @@ -343,7 +346,10 @@ void MqttPacket::handleConnect() | @@ -343,7 +346,10 @@ void MqttPacket::handleConnect() | ||
| 343 | } | 346 | } |
| 344 | else | 347 | else |
| 345 | { | 348 | { |
| 346 | - ConnAck connAck(ConnAckReturnCodes::UnacceptableProtocolVersion); | 349 | + // The specs are unclear when to use the version 3 codes or version 5 codes. |
| 350 | + ProtocolVersion fuzzyProtocolVersion = protocol_level < 0x05 ? ProtocolVersion::Mqtt31 : ProtocolVersion::Mqtt5; | ||
| 351 | + | ||
| 352 | + ConnAck connAck(fuzzyProtocolVersion, ReasonCodes::UnsupportedProtocolVersion); | ||
| 347 | MqttPacket response(connAck); | 353 | MqttPacket response(connAck); |
| 348 | sender->setReadyForDisconnect(); | 354 | sender->setReadyForDisconnect(); |
| 349 | sender->writeMqttPacket(response); | 355 | sender->writeMqttPacket(response); |
| @@ -398,7 +404,7 @@ void MqttPacket::handleConnect() | @@ -398,7 +404,7 @@ void MqttPacket::handleConnect() | ||
| 398 | max_packet_size = std::min<uint32_t>(readFourBytesToUint32(), max_packet_size); | 404 | max_packet_size = std::min<uint32_t>(readFourBytesToUint32(), max_packet_size); |
| 399 | break; | 405 | break; |
| 400 | case Mqtt5Properties::TopicAliasMaximum: | 406 | case Mqtt5Properties::TopicAliasMaximum: |
| 401 | - max_topic_aliases = readTwoBytesToUInt16(); | 407 | + max_topic_aliases = std::min<uint16_t>(readTwoBytesToUInt16(), max_topic_aliases); |
| 402 | break; | 408 | break; |
| 403 | case Mqtt5Properties::RequestResponseInformation: | 409 | case Mqtt5Properties::RequestResponseInformation: |
| 404 | request_response_information = !!readByte(); | 410 | request_response_information = !!readByte(); |
| @@ -451,7 +457,7 @@ void MqttPacket::handleConnect() | @@ -451,7 +457,7 @@ void MqttPacket::handleConnect() | ||
| 451 | // The specs don't really say what to do when client id not UTF8, so including here. | 457 | // The specs don't really say what to do when client id not UTF8, so including here. |
| 452 | if (!isValidUtf8(client_id) || !isValidUtf8(username) || !isValidUtf8(password) || !isValidUtf8(will_topic)) | 458 | if (!isValidUtf8(client_id) || !isValidUtf8(username) || !isValidUtf8(password) || !isValidUtf8(will_topic)) |
| 453 | { | 459 | { |
| 454 | - ConnAck connAck(ConnAckReturnCodes::MalformedUsernameOrPassword); | 460 | + ConnAck connAck(protocolVersion, ReasonCodes::BadUserNameOrPassword); |
| 455 | MqttPacket response(connAck); | 461 | MqttPacket response(connAck); |
| 456 | sender->setReadyForDisconnect(); | 462 | sender->setReadyForDisconnect(); |
| 457 | sender->writeMqttPacket(response); | 463 | sender->writeMqttPacket(response); |
| @@ -480,7 +486,7 @@ void MqttPacket::handleConnect() | @@ -480,7 +486,7 @@ void MqttPacket::handleConnect() | ||
| 480 | 486 | ||
| 481 | if (!validClientId) | 487 | if (!validClientId) |
| 482 | { | 488 | { |
| 483 | - ConnAck connAck(ConnAckReturnCodes::ClientIdRejected); | 489 | + ConnAck connAck(protocolVersion, ReasonCodes::ClientIdentifierNotValid); |
| 484 | MqttPacket response(connAck); | 490 | MqttPacket response(connAck); |
| 485 | sender->setDisconnectReason("Invalid clientID"); | 491 | sender->setDisconnectReason("Invalid clientID"); |
| 486 | sender->setReadyForDisconnect(); | 492 | sender->setReadyForDisconnect(); |
| @@ -488,9 +494,11 @@ void MqttPacket::handleConnect() | @@ -488,9 +494,11 @@ void MqttPacket::handleConnect() | ||
| 488 | return; | 494 | return; |
| 489 | } | 495 | } |
| 490 | 496 | ||
| 497 | + bool clientIdGenerated = false; | ||
| 491 | if (client_id.empty()) | 498 | if (client_id.empty()) |
| 492 | { | 499 | { |
| 493 | client_id = getSecureRandomString(23); | 500 | client_id = getSecureRandomString(23); |
| 501 | + clientIdGenerated = true; | ||
| 494 | } | 502 | } |
| 495 | 503 | ||
| 496 | sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_packet_size, max_topic_aliases); | 504 | sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_packet_size, max_topic_aliases); |
| @@ -521,7 +529,22 @@ void MqttPacket::handleConnect() | @@ -521,7 +529,22 @@ void MqttPacket::handleConnect() | ||
| 521 | bool sessionPresent = protocolVersion >= ProtocolVersion::Mqtt311 && !clean_start && subscriptionStore->sessionPresent(client_id); | 529 | bool sessionPresent = protocolVersion >= ProtocolVersion::Mqtt311 && !clean_start && subscriptionStore->sessionPresent(client_id); |
| 522 | 530 | ||
| 523 | sender->setAuthenticated(true); | 531 | sender->setAuthenticated(true); |
| 524 | - ConnAck connAck(ConnAckReturnCodes::Accepted, sessionPresent); | 532 | + ConnAck connAck(protocolVersion, ReasonCodes::Success, sessionPresent); |
| 533 | + | ||
| 534 | + if (protocolVersion >= ProtocolVersion::Mqtt5) | ||
| 535 | + { | ||
| 536 | + connAck.propertyBuilder = std::make_shared<Mqtt5PropertyBuilder>(); | ||
| 537 | + connAck.propertyBuilder->writeSessionExpiry(session_expire); | ||
| 538 | + connAck.propertyBuilder->writeReceiveMax(max_qos_packets); | ||
| 539 | + connAck.propertyBuilder->writeRetainAvailable(1); | ||
| 540 | + connAck.propertyBuilder->writeMaxPacketSize(max_packet_size); | ||
| 541 | + if (clientIdGenerated) | ||
| 542 | + connAck.propertyBuilder->writeAssignedClientId(client_id); | ||
| 543 | + connAck.propertyBuilder->writeMaxTopicAliases(max_topic_aliases); | ||
| 544 | + connAck.propertyBuilder->writeWildcardSubscriptionAvailable(1); | ||
| 545 | + connAck.propertyBuilder->writeSharedSubscriptionAvailable(0); | ||
| 546 | + } | ||
| 547 | + | ||
| 525 | MqttPacket response(connAck); | 548 | MqttPacket response(connAck); |
| 526 | sender->writeMqttPacket(response); | 549 | sender->writeMqttPacket(response); |
| 527 | logger->logf(LOG_NOTICE, "Client '%s' logged in successfully", sender->repr().c_str()); | 550 | logger->logf(LOG_NOTICE, "Client '%s' logged in successfully", sender->repr().c_str()); |
| @@ -530,7 +553,7 @@ void MqttPacket::handleConnect() | @@ -530,7 +553,7 @@ void MqttPacket::handleConnect() | ||
| 530 | } | 553 | } |
| 531 | else | 554 | else |
| 532 | { | 555 | { |
| 533 | - ConnAck connDeny(ConnAckReturnCodes::NotAuthorized, false); | 556 | + ConnAck connDeny(protocolVersion, ReasonCodes::NotAuthorized, false); |
| 534 | MqttPacket response(connDeny); | 557 | MqttPacket response(connDeny); |
| 535 | sender->setDisconnectReason("Access denied"); | 558 | sender->setDisconnectReason("Access denied"); |
| 536 | sender->setReadyForDisconnect(); | 559 | sender->setReadyForDisconnect(); |
| @@ -960,6 +983,23 @@ void MqttPacket::writeBytes(const char *b, size_t len) | @@ -960,6 +983,23 @@ void MqttPacket::writeBytes(const char *b, size_t len) | ||
| 960 | pos += len; | 983 | pos += len; |
| 961 | } | 984 | } |
| 962 | 985 | ||
| 986 | +void MqttPacket::writeProperties(const std::shared_ptr<Mqtt5PropertyBuilder> &properties) | ||
| 987 | +{ | ||
| 988 | + if (!properties) | ||
| 989 | + writeByte(0); | ||
| 990 | + else | ||
| 991 | + { | ||
| 992 | + writeVariableByteInt(properties->getVarInt()); | ||
| 993 | + const std::vector<char> &b = properties->getBites(); | ||
| 994 | + writeBytes(b.data(), b.size()); | ||
| 995 | + } | ||
| 996 | +} | ||
| 997 | + | ||
| 998 | +void MqttPacket::writeVariableByteInt(const VariableByteInt &v) | ||
| 999 | +{ | ||
| 1000 | + writeBytes(v.data(), v.getLen()); | ||
| 1001 | +} | ||
| 1002 | + | ||
| 963 | uint16_t MqttPacket::readTwoBytesToUInt16() | 1003 | uint16_t MqttPacket::readTwoBytesToUInt16() |
| 964 | { | 1004 | { |
| 965 | if (pos + 2 > bites.size()) | 1005 | if (pos + 2 > bites.size()) |
mqttpacket.h
| @@ -34,6 +34,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | @@ -34,6 +34,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | ||
| 34 | #include "mainapp.h" | 34 | #include "mainapp.h" |
| 35 | 35 | ||
| 36 | #include "variablebyteint.h" | 36 | #include "variablebyteint.h" |
| 37 | +#include "mqtt5properties.h" | ||
| 37 | 38 | ||
| 38 | class MqttPacket | 39 | class MqttPacket |
| 39 | { | 40 | { |
| @@ -62,6 +63,8 @@ class MqttPacket | @@ -62,6 +63,8 @@ class MqttPacket | ||
| 62 | void writeByte(char b); | 63 | void writeByte(char b); |
| 63 | void writeUint16(uint16_t x); | 64 | void writeUint16(uint16_t x); |
| 64 | void writeBytes(const char *b, size_t len); | 65 | void writeBytes(const char *b, size_t len); |
| 66 | + void writeProperties(const std::shared_ptr<Mqtt5PropertyBuilder> &properties); | ||
| 67 | + void writeVariableByteInt(const VariableByteInt &v); | ||
| 65 | uint16_t readTwoBytesToUInt16(); | 68 | uint16_t readTwoBytesToUInt16(); |
| 66 | uint32_t readFourBytesToUint32(); | 69 | uint32_t readFourBytesToUint32(); |
| 67 | size_t remainingAfterPos(); | 70 | size_t remainingAfterPos(); |
types.cpp
| @@ -18,14 +18,66 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | @@ -18,14 +18,66 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | #include "cassert" | 18 | #include "cassert" |
| 19 | 19 | ||
| 20 | #include "types.h" | 20 | #include "types.h" |
| 21 | +#include "mqtt5properties.h" | ||
| 21 | 22 | ||
| 22 | -ConnAck::ConnAck(ConnAckReturnCodes return_code, bool session_present) : | ||
| 23 | - return_code(return_code), | 23 | +ConnAck::ConnAck(const ProtocolVersion protVersion, ReasonCodes return_code, bool session_present) : |
| 24 | + protocol_version(protVersion), | ||
| 24 | session_present(session_present) | 25 | session_present(session_present) |
| 25 | { | 26 | { |
| 26 | - // [MQTT-3.2.2-4] | ||
| 27 | - if (return_code > ConnAckReturnCodes::Accepted) | ||
| 28 | - session_present = false; | 27 | + |
| 28 | + if (this->protocol_version <= ProtocolVersion::Mqtt311) | ||
| 29 | + { | ||
| 30 | + ConnAckReturnCodes mqtt3_return = ConnAckReturnCodes::Accepted; | ||
| 31 | + | ||
| 32 | + switch (return_code) | ||
| 33 | + { | ||
| 34 | + case ReasonCodes::Success: | ||
| 35 | + mqtt3_return = ConnAckReturnCodes::Accepted; | ||
| 36 | + break; | ||
| 37 | + case ReasonCodes::UnsupportedProtocolVersion: | ||
| 38 | + mqtt3_return = ConnAckReturnCodes::UnacceptableProtocolVersion; | ||
| 39 | + break; | ||
| 40 | + case ReasonCodes::ClientIdentifierNotValid: | ||
| 41 | + mqtt3_return = ConnAckReturnCodes::ClientIdRejected; | ||
| 42 | + break; | ||
| 43 | + case ReasonCodes::ServerUnavailable: | ||
| 44 | + mqtt3_return = ConnAckReturnCodes::ServerUnavailable; | ||
| 45 | + break; | ||
| 46 | + case ReasonCodes::BadUserNameOrPassword: | ||
| 47 | + mqtt3_return = ConnAckReturnCodes::MalformedUsernameOrPassword; | ||
| 48 | + break; | ||
| 49 | + case ReasonCodes::NotAuthorized: | ||
| 50 | + mqtt3_return = ConnAckReturnCodes::NotAuthorized; | ||
| 51 | + default: | ||
| 52 | + assert(false); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + // [MQTT-3.2.2-4] | ||
| 56 | + if (mqtt3_return > ConnAckReturnCodes::Accepted) | ||
| 57 | + session_present = false; | ||
| 58 | + | ||
| 59 | + this->return_code = static_cast<uint8_t>(mqtt3_return); | ||
| 60 | + } | ||
| 61 | + else | ||
| 62 | + { | ||
| 63 | + this->return_code = static_cast<uint8_t>(return_code); | ||
| 64 | + | ||
| 65 | + // MQTT-3.2.2-6 | ||
| 66 | + if (this->return_code > 0) | ||
| 67 | + session_present = false; | ||
| 68 | + } | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +size_t ConnAck::getLengthWithoutFixedHeader() const | ||
| 72 | +{ | ||
| 73 | + size_t result = 2; | ||
| 74 | + | ||
| 75 | + if (this->protocol_version >= ProtocolVersion::Mqtt5) | ||
| 76 | + { | ||
| 77 | + const size_t proplen = propertyBuilder ? propertyBuilder->getLength() : 1; | ||
| 78 | + result += proplen; | ||
| 79 | + } | ||
| 80 | + return result; | ||
| 29 | } | 81 | } |
| 30 | 82 | ||
| 31 | SubAck::SubAck(uint16_t packet_id, const std::list<char> &subs_qos_reponses) : | 83 | SubAck::SubAck(uint16_t packet_id, const std::list<char> &subs_qos_reponses) : |
types.h
| @@ -21,6 +21,9 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | @@ -21,6 +21,9 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. | ||
| 21 | #include "stdint.h" | 21 | #include "stdint.h" |
| 22 | #include <list> | 22 | #include <list> |
| 23 | #include <string> | 23 | #include <string> |
| 24 | +#include <memory> | ||
| 25 | + | ||
| 26 | +#include "forward_declarations.h" | ||
| 24 | 27 | ||
| 25 | enum class PacketType | 28 | enum class PacketType |
| 26 | { | 29 | { |
| @@ -83,6 +86,9 @@ enum class Mqtt5Properties | @@ -83,6 +86,9 @@ enum class Mqtt5Properties | ||
| 83 | SharedSubscriptionAvailable = 42 | 86 | SharedSubscriptionAvailable = 42 |
| 84 | }; | 87 | }; |
| 85 | 88 | ||
| 89 | +/** | ||
| 90 | + * @brief The ConnAckReturnCodes enum are for MQTT3 | ||
| 91 | + */ | ||
| 86 | enum class ConnAckReturnCodes | 92 | enum class ConnAckReturnCodes |
| 87 | { | 93 | { |
| 88 | Accepted = 0, | 94 | Accepted = 0, |
| @@ -93,13 +99,67 @@ enum class ConnAckReturnCodes | @@ -93,13 +99,67 @@ enum class ConnAckReturnCodes | ||
| 93 | NotAuthorized = 5 | 99 | NotAuthorized = 5 |
| 94 | }; | 100 | }; |
| 95 | 101 | ||
| 102 | +/** | ||
| 103 | + * @brief The ReasonCodes enum are for MQTT5. | ||
| 104 | + */ | ||
| 105 | +enum class ReasonCodes | ||
| 106 | +{ | ||
| 107 | + Success = 0, | ||
| 108 | + GrantedQoS0 = 0, | ||
| 109 | + GrantedQoS1 = 1, | ||
| 110 | + GrantedQoS2 = 2, | ||
| 111 | + DisconnectWithWill = 4, | ||
| 112 | + NoMatchingSubscribers = 16, | ||
| 113 | + NoSubscriptionExisted = 17, | ||
| 114 | + ContinueAuthentication = 24, | ||
| 115 | + ReAuthenticate = 25, | ||
| 116 | + UnspecifiedError = 128, | ||
| 117 | + MalformedPacket = 129, | ||
| 118 | + ProtocolError = 130, | ||
| 119 | + ImplementationSpecificError = 131, | ||
| 120 | + UnsupportedProtocolVersion = 132, | ||
| 121 | + ClientIdentifierNotValid = 133, | ||
| 122 | + BadUserNameOrPassword = 134, | ||
| 123 | + NotAuthorized = 135, | ||
| 124 | + ServerUnavailable = 136, | ||
| 125 | + ServerBusy = 137, | ||
| 126 | + Banned = 138, | ||
| 127 | + ServerShuttingDown = 139, | ||
| 128 | + BadAuthenticationMethod = 140, | ||
| 129 | + KeepAliveTimeout = 141, | ||
| 130 | + SessionTakenOver = 142, | ||
| 131 | + TopicFilterInvalid = 143, | ||
| 132 | + TopicNameInvalid = 144, | ||
| 133 | + PacketIdentifierInUse = 145, | ||
| 134 | + ReceiveMaximumExceeded = 147, | ||
| 135 | + TopicAliasInvalid = 148, | ||
| 136 | + PacketTooLarge = 149, | ||
| 137 | + MessageRateTooHigh = 150, | ||
| 138 | + QuoteExceeded = 151, | ||
| 139 | + AdministrativeAction = 152, | ||
| 140 | + PayloadFormatInvalid = 153, | ||
| 141 | + RetainNotSupported = 154, | ||
| 142 | + QosNotSupported = 155, | ||
| 143 | + UseAnotherServer = 156, | ||
| 144 | + ServerMoved = 157, | ||
| 145 | + SharedSubscriptionsNotSupported = 158, | ||
| 146 | + ConnectionRateExceeded = 159, | ||
| 147 | + MaximumConnectTime = 160, | ||
| 148 | + SubscriptionIdentifiersNotSupported = 161, | ||
| 149 | + WildcardSubscriptionsNotSupported = 162 | ||
| 150 | +}; | ||
| 151 | + | ||
| 96 | class ConnAck | 152 | class ConnAck |
| 97 | { | 153 | { |
| 98 | public: | 154 | public: |
| 99 | - ConnAck(ConnAckReturnCodes return_code, bool session_present=false); | ||
| 100 | - ConnAckReturnCodes return_code; | 155 | + ConnAck(const ProtocolVersion protVersion, ReasonCodes return_code, bool session_present=false); |
| 156 | + | ||
| 157 | + const ProtocolVersion protocol_version; | ||
| 158 | + uint8_t return_code; | ||
| 101 | bool session_present = false; | 159 | bool session_present = false; |
| 102 | - size_t getLengthWithoutFixedHeader() const { return 2;} // size of connack is always the same | 160 | + std::shared_ptr<Mqtt5PropertyBuilder> propertyBuilder; |
| 161 | + | ||
| 162 | + size_t getLengthWithoutFixedHeader() const; | ||
| 103 | }; | 163 | }; |
| 104 | 164 | ||
| 105 | enum class SubAckReturnCodes | 165 | enum class SubAckReturnCodes |
variablebyteint.cpp
variablebyteint.h
| @@ -12,6 +12,7 @@ public: | @@ -12,6 +12,7 @@ public: | ||
| 12 | void readIntoBuf(CirBuf &buf) const; | 12 | void readIntoBuf(CirBuf &buf) const; |
| 13 | VariableByteInt &operator=(uint32_t x); | 13 | VariableByteInt &operator=(uint32_t x); |
| 14 | uint8_t getLen() const; | 14 | uint8_t getLen() const; |
| 15 | + const char *data() const; | ||
| 15 | }; | 16 | }; |
| 16 | 17 | ||
| 17 | #endif // VARIABLEBYTEINT_H | 18 | #endif // VARIABLEBYTEINT_H |