Commit a3d29f51446a7103a2101a21135c5f920aa73dc4

Authored by Wiebe Cazemier
1 parent 4a16d48b

Fix unnecessary QoS packet creation

The extraneous creation would happen when multiple subscribes at
different QoS levels happen.
client.cpp
... ... @@ -251,14 +251,14 @@ void Client::writeMqttPacketAndBlameThisClient(PublishCopyFactory &copyFactory,
251 251  
252 252 MqttPacket *p = copyFactory.getOptimumPacket(max_qos, this->protocolVersion, topic_alias, skip_topic);
253 253  
254   - assert(p->getQos() <= max_qos);
  254 + assert(static_cast<bool>(p->getQos()) == static_cast<bool>(max_qos));
255 255  
256 256 if (p->getQos() > 0)
257 257 {
258 258 // This may change the packet ID and QoS of the incoming packet for each subscriber, but because we don't store that packet anywhere,
259 259 // that should be fine.
260 260 p->setPacketId(packet_id);
261   - p->setQos(max_qos);
  261 + p->setQos(copyFactory.getEffectiveQos(max_qos));
262 262 }
263 263  
264 264 writeMqttPacketAndBlameThisClient(*p);
... ...
publishcopyfactory.cpp
... ... @@ -19,31 +19,32 @@ PublishCopyFactory::PublishCopyFactory(Publish *publish) :
19 19  
20 20 MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const ProtocolVersion protocolVersion, uint16_t topic_alias, bool skip_topic)
21 21 {
  22 + const char actualQos = getEffectiveQos(max_qos);
  23 +
22 24 if (packet)
23 25 {
24 26 if (protocolVersion >= ProtocolVersion::Mqtt5 && (packet->containsClientSpecificProperties() || topic_alias > 0))
25 27 {
26 28 Publish newPublish(packet->getPublishData());
27   - newPublish.qos = max_qos;
  29 + newPublish.qos = actualQos;
28 30 newPublish.topicAlias = topic_alias;
29 31 newPublish.skipTopic = skip_topic;
30 32 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, newPublish);
31 33 return this->oneShotPacket.get();
32 34 }
33 35  
34   - if (packet->getProtocolVersion() == protocolVersion && orgQos == max_qos)
  36 + if (packet->getProtocolVersion() == protocolVersion && static_cast<bool>(orgQos) == static_cast<bool>(actualQos))
35 37 {
36   - assert(orgQos == packet->getQos());
37 38 return packet;
38 39 }
39 40  
40   - const int cache_key = (static_cast<uint8_t>(protocolVersion) * 10) + max_qos;
  41 + const int cache_key = (static_cast<uint8_t>(protocolVersion) * 10) + actualQos;
41 42 std::unique_ptr<MqttPacket> &cachedPack = constructedPacketCache[cache_key];
42 43  
43 44 if (!cachedPack)
44 45 {
45 46 Publish newPublish(packet->getPublishData());
46   - newPublish.qos = max_qos;
  47 + newPublish.qos = actualQos;
47 48 cachedPack = std::make_unique<MqttPacket>(protocolVersion, newPublish);
48 49 }
49 50  
... ... @@ -53,7 +54,7 @@ MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const Proto
53 54 // Getting an instance of a Publish object happens at least on retained messages, will messages and SYS topics. It's low traffic, anyway.
54 55 assert(publish);
55 56  
56   - publish->qos = getEffectiveQos(max_qos);
  57 + publish->qos = actualQos;
57 58  
58 59 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, *publish);
59 60 return this->oneShotPacket.get();
... ...
publishcopyfactory.h
... ... @@ -11,7 +11,7 @@
11 11 * @brief The PublishCopyFactory class is for managing copies of an incoming publish, including sometimes not making copies at all.
12 12 *
13 13 * The idea is that certain incoming packets can just be written to the receiving client as-is, without constructing a new one. We do have to change the bytes
14   - * where the QoS is stored, so we keep track of the original.
  14 + * where the QoS is stored, so we keep track of the original QoS.
15 15 *
16 16 * Ownership info: object of this type are never copied or transferred, so the internal pointers come from (near) the same scope these objects
17 17 * are created from.
... ...