Commit 98366c6dfb466bf89d2258d8b446278dd7d600b1
1 parent
39c1873d
Get the semantics of incoming and outgoing aliases correct
Showing
5 changed files
with
39 additions
and
17 deletions
client.cpp
| ... | ... | @@ -208,11 +208,10 @@ int Client::writeMqttPacket(const MqttPacket &packet) |
| 208 | 208 | |
| 209 | 209 | int Client::writeMqttPacketAndBlameThisClient(PublishCopyFactory ©Factory, char max_qos, uint16_t packet_id) |
| 210 | 210 | { |
| 211 | - const Settings *settings = ThreadGlobals::getSettings(); | |
| 212 | 211 | uint16_t topic_alias = 0; |
| 213 | 212 | bool skip_topic = false; |
| 214 | 213 | |
| 215 | - if (protocolVersion >= ProtocolVersion::Mqtt5 && settings->maxOutgoingTopicAliases > this->curOutgoingTopicAlias) | |
| 214 | + if (protocolVersion >= ProtocolVersion::Mqtt5 && this->maxOutgoingTopicAliasValue > this->curOutgoingTopicAlias) | |
| 216 | 215 | { |
| 217 | 216 | uint16_t &id = this->outgoingTopicAliases[copyFactory.getTopic()]; |
| 218 | 217 | |
| ... | ... | @@ -358,15 +357,18 @@ void Client::setTopicAlias(const uint16_t alias_id, const std::string &topic) |
| 358 | 357 | if (topic.empty()) |
| 359 | 358 | return; |
| 360 | 359 | |
| 361 | - if (alias_id > this->maxTopicAliases) | |
| 362 | - throw ProtocolError("Client exceeded max topic aliases."); | |
| 360 | + const Settings *settings = ThreadGlobals::getSettings(); | |
| 361 | + | |
| 362 | + // The specs actually say "The Client MUST NOT send a Topic Alias [...] to the Server greater than this value [Topic Alias Maximum]". So, it's not about count. | |
| 363 | + if (alias_id > settings->maxIncomingTopicAliasValue) | |
| 364 | + throw ProtocolError(formatString("Client tried to set more topic aliases than the server max of %d per client", settings->maxIncomingTopicAliasValue)); | |
| 363 | 365 | |
| 364 | - this->topicAliases[alias_id] = topic; | |
| 366 | + this->incomingTopicAliases[alias_id] = topic; | |
| 365 | 367 | } |
| 366 | 368 | |
| 367 | 369 | const std::string &Client::getTopicAlias(const uint16_t id) |
| 368 | 370 | { |
| 369 | - return this->topicAliases[id]; | |
| 371 | + return this->incomingTopicAliases[id]; | |
| 370 | 372 | } |
| 371 | 373 | |
| 372 | 374 | #ifndef NDEBUG |
| ... | ... | @@ -460,7 +462,7 @@ void Client::setClientProperties(ProtocolVersion protocolVersion, const std::str |
| 460 | 462 | |
| 461 | 463 | |
| 462 | 464 | void Client::setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, |
| 463 | - uint32_t maxPacketSize, uint16_t maxTopicAliases) | |
| 465 | + uint32_t maxPacketSize, uint16_t maxOutgoingTopicAliasValue) | |
| 464 | 466 | { |
| 465 | 467 | this->protocolVersion = protocolVersion; |
| 466 | 468 | this->clientid = clientId; |
| ... | ... | @@ -468,7 +470,7 @@ void Client::setClientProperties(ProtocolVersion protocolVersion, const std::str |
| 468 | 470 | this->connectPacketSeen = connectPacketSeen; |
| 469 | 471 | this->keepalive = keepalive; |
| 470 | 472 | this->maxPacketSize = maxPacketSize; |
| 471 | - this->maxTopicAliases = maxTopicAliases; | |
| 473 | + this->maxOutgoingTopicAliasValue = maxOutgoingTopicAliasValue; | |
| 472 | 474 | } |
| 473 | 475 | |
| 474 | 476 | void Client::setWill(Publish &&willPublish) | ... | ... |
client.h
| ... | ... | @@ -53,7 +53,7 @@ class Client |
| 53 | 53 | |
| 54 | 54 | const size_t initialBufferSize = 0; |
| 55 | 55 | uint32_t maxPacketSize = 0; |
| 56 | - uint16_t maxTopicAliases = 0; | |
| 56 | + uint16_t maxOutgoingTopicAliasValue = 0; | |
| 57 | 57 | |
| 58 | 58 | IoWrapper ioWrapper; |
| 59 | 59 | std::string transportStr; |
| ... | ... | @@ -82,7 +82,7 @@ class Client |
| 82 | 82 | |
| 83 | 83 | std::shared_ptr<Session> session; |
| 84 | 84 | |
| 85 | - std::unordered_map<uint16_t, std::string> topicAliases; | |
| 85 | + std::unordered_map<uint16_t, std::string> incomingTopicAliases; | |
| 86 | 86 | |
| 87 | 87 | uint16_t curOutgoingTopicAlias = 0; |
| 88 | 88 | std::unordered_map<std::string, uint16_t> outgoingTopicAliases; |
| ... | ... | @@ -111,7 +111,7 @@ public: |
| 111 | 111 | void bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::shared_ptr<Client> &sender); |
| 112 | 112 | void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive); |
| 113 | 113 | void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, |
| 114 | - uint32_t maxPacketSize, uint16_t maxTopicAliases); | |
| 114 | + uint32_t maxPacketSize, uint16_t maxOutgoingTopicAliasValue); | |
| 115 | 115 | void setWill(const std::string &topic, const std::string &payload, bool retain, char qos); |
| 116 | 116 | void setWill(Publish &&willPublish); |
| 117 | 117 | void clearWill(); | ... | ... |
configfileparser.cpp
| ... | ... | @@ -461,6 +461,26 @@ void ConfigFileParser::loadFile(bool test) |
| 461 | 461 | } |
| 462 | 462 | tmpSettings->maxQosBytesPendingPerClient = newVal; |
| 463 | 463 | } |
| 464 | + | |
| 465 | + if (key == "max_incoming_topic_alias_value") | |
| 466 | + { | |
| 467 | + int newVal = std::stoi(value); | |
| 468 | + if (newVal < 0 || newVal > 0xFFFF) | |
| 469 | + { | |
| 470 | + throw ConfigFileException(formatString("max_incoming_topic_alias_value value '%d' is invalid. Valid values are between 0 and 65535.", newVal)); | |
| 471 | + } | |
| 472 | + tmpSettings->maxIncomingTopicAliasValue = newVal; | |
| 473 | + } | |
| 474 | + | |
| 475 | + if (key == "max_outgoing_topic_alias_value") | |
| 476 | + { | |
| 477 | + int newVal = std::stoi(value); | |
| 478 | + if (newVal < 0 || newVal > 0xFFFF) | |
| 479 | + { | |
| 480 | + throw ConfigFileException(formatString("max_outgoing_topic_alias_value value '%d' is invalid. Valid values are between 0 and 65535.", newVal)); | |
| 481 | + } | |
| 482 | + tmpSettings->maxOutgoingTopicAliasValue = newVal; | |
| 483 | + } | |
| 464 | 484 | } |
| 465 | 485 | } |
| 466 | 486 | catch (std::invalid_argument &ex) // catch for the stoi() | ... | ... |
mqttpacket.cpp
| ... | ... | @@ -345,7 +345,7 @@ void MqttPacket::handleConnect() |
| 345 | 345 | uint16_t max_qos_packets = settings.maxQosMsgPendingPerClient; |
| 346 | 346 | uint32_t session_expire = settings.expireSessionsAfterSeconds > 0 ? settings.expireSessionsAfterSeconds : std::numeric_limits<uint32_t>::max(); |
| 347 | 347 | uint32_t max_packet_size = settings.maxPacketSize; |
| 348 | - uint16_t max_topic_aliases = settings.maxOutgoingTopicAliases; | |
| 348 | + uint16_t max_outgoing_topic_aliases = 0; // Default MUST BE 0, meaning server won't initiate aliases | |
| 349 | 349 | bool request_response_information = false; |
| 350 | 350 | bool request_problem_information = false; |
| 351 | 351 | |
| ... | ... | @@ -370,7 +370,7 @@ void MqttPacket::handleConnect() |
| 370 | 370 | max_packet_size = std::min<uint32_t>(readFourBytesToUint32(), max_packet_size); |
| 371 | 371 | break; |
| 372 | 372 | case Mqtt5Properties::TopicAliasMaximum: |
| 373 | - max_topic_aliases = std::min<uint16_t>(readTwoBytesToUInt16(), max_topic_aliases); | |
| 373 | + max_outgoing_topic_aliases = std::min<uint16_t>(readTwoBytesToUInt16(), settings.maxOutgoingTopicAliasValue); | |
| 374 | 374 | break; |
| 375 | 375 | case Mqtt5Properties::RequestResponseInformation: |
| 376 | 376 | request_response_information = !!readByte(); |
| ... | ... | @@ -541,7 +541,7 @@ void MqttPacket::handleConnect() |
| 541 | 541 | clientIdGenerated = true; |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | - sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_packet_size, max_topic_aliases); | |
| 544 | + sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_packet_size, max_outgoing_topic_aliases); | |
| 545 | 545 | |
| 546 | 546 | if (will_flag) |
| 547 | 547 | sender->setWill(std::move(willpublish)); |
| ... | ... | @@ -582,7 +582,7 @@ void MqttPacket::handleConnect() |
| 582 | 582 | connAck.propertyBuilder->writeMaxPacketSize(max_packet_size); |
| 583 | 583 | if (clientIdGenerated) |
| 584 | 584 | connAck.propertyBuilder->writeAssignedClientId(client_id); |
| 585 | - connAck.propertyBuilder->writeMaxTopicAliases(max_topic_aliases); | |
| 585 | + connAck.propertyBuilder->writeMaxTopicAliases(settings.maxIncomingTopicAliasValue); | |
| 586 | 586 | connAck.propertyBuilder->writeWildcardSubscriptionAvailable(1); |
| 587 | 587 | connAck.propertyBuilder->writeSubscriptionIdentifiersAvailable(0); |
| 588 | 588 | connAck.propertyBuilder->writeSharedSubscriptionAvailable(0); | ... | ... |
settings.h
| ... | ... | @@ -42,8 +42,8 @@ public: |
| 42 | 42 | bool authPluginSerializeAuthChecks = false; |
| 43 | 43 | int clientInitialBufferSize = 1024; // Must be power of 2 |
| 44 | 44 | int maxPacketSize = 268435461; // 256 MB + 5 |
| 45 | - uint16_t maxIncomingTopicAliases = 65535; | |
| 46 | - uint16_t maxOutgoingTopicAliases = 0; // TODO: setting, when I can confirm with clients that support it that it works. | |
| 45 | + uint16_t maxIncomingTopicAliasValue = 65535; | |
| 46 | + uint16_t maxOutgoingTopicAliasValue = 65535; | |
| 47 | 47 | #ifdef TESTING |
| 48 | 48 | bool logDebug = true; |
| 49 | 49 | #else | ... | ... |