Commit 98366c6dfb466bf89d2258d8b446278dd7d600b1

Authored by Wiebe Cazemier
1 parent 39c1873d

Get the semantics of incoming and outgoing aliases correct

client.cpp
... ... @@ -208,11 +208,10 @@ int Client::writeMqttPacket(const MqttPacket &packet)
208 208  
209 209 int Client::writeMqttPacketAndBlameThisClient(PublishCopyFactory &copyFactory, 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
... ...