Commit 8094510fe9c1aef9aee705fcd63c6a6afc16d941
1 parent
f8667722
QoS on retained messages
Showing
5 changed files
with
27 additions
and
18 deletions
mqttpacket.cpp
| ... | ... | @@ -86,6 +86,7 @@ MqttPacket::MqttPacket(const Publish &publish) : |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | packetType = PacketType::PUBLISH; |
| 89 | + this->qos = publish.qos; | |
| 89 | 90 | first_byte = static_cast<char>(packetType) << 4; |
| 90 | 91 | first_byte |= (publish.qos << 1); |
| 91 | 92 | first_byte |= (static_cast<char>(publish.retain) & 0b00000001); |
| ... | ... | @@ -98,7 +99,10 @@ MqttPacket::MqttPacket(const Publish &publish) : |
| 98 | 99 | |
| 99 | 100 | if (publish.qos) |
| 100 | 101 | { |
| 101 | - throw NotImplementedException("I would write two bytes containing the packet id here, but QoS is not done yet."); | |
| 102 | + // Reserve the space for the packet id, which will be assigned later. | |
| 103 | + packet_id_pos = pos; | |
| 104 | + char zero[2]; | |
| 105 | + writeBytes(zero, 2); | |
| 102 | 106 | } |
| 103 | 107 | |
| 104 | 108 | writeBytes(publish.payload.c_str(), publish.payload.length()); |
| ... | ... | @@ -398,8 +402,8 @@ RemainingLength MqttPacket::getRemainingLength() const |
| 398 | 402 | |
| 399 | 403 | void MqttPacket::setPacketId(uint16_t packet_id) |
| 400 | 404 | { |
| 401 | - // In other words, we assume that this code can only be called on packets of which we have all the bytes, including fixed header. | |
| 402 | - assert(fixed_header_length > 0); | |
| 405 | + assert(fixed_header_length == 0 || first_byte == bites[0]); | |
| 406 | + assert(packet_id_pos > 0); | |
| 403 | 407 | assert(packetType == PacketType::PUBLISH); |
| 404 | 408 | assert(qos > 0); |
| 405 | 409 | |
| ... | ... | @@ -414,15 +418,17 @@ void MqttPacket::setPacketId(uint16_t packet_id) |
| 414 | 418 | // If I read the specs correctly, the DUP flag is merely for show. It doesn't control anything? |
| 415 | 419 | void MqttPacket::setDuplicate() |
| 416 | 420 | { |
| 417 | - // In other words, we assume that this code can only be called on packets of which we have all the bytes, including fixed header. | |
| 418 | - assert(fixed_header_length > 0); | |
| 419 | 421 | assert(packetType == PacketType::PUBLISH); |
| 420 | 422 | assert(qos > 0); |
| 423 | + assert(fixed_header_length == 0 || first_byte == bites[0]); | |
| 424 | + | |
| 425 | + first_byte |= 0b00001000; | |
| 421 | 426 | |
| 422 | - char byte1 = bites[0]; | |
| 423 | - byte1 |= 0b00001000; | |
| 424 | - pos = 0; | |
| 425 | - writeByte(byte1); | |
| 427 | + if (fixed_header_length > 0) | |
| 428 | + { | |
| 429 | + pos = 0; | |
| 430 | + writeByte(first_byte); | |
| 431 | + } | |
| 426 | 432 | } |
| 427 | 433 | |
| 428 | 434 | size_t MqttPacket::getTotalMemoryFootprint() | ... | ... |
session.cpp
| ... | ... | @@ -24,9 +24,9 @@ void Session::assignActiveConnection(std::shared_ptr<Client> &client) |
| 24 | 24 | this->client_id = client->getClientId(); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | -void Session::writePacket(const MqttPacket &packet, char qos_arg) | |
| 27 | +void Session::writePacket(const MqttPacket &packet, char max_qos) | |
| 28 | 28 | { |
| 29 | - const char qos = std::min<char>(packet.getQos(), qos_arg); | |
| 29 | + const char qos = std::min<char>(packet.getQos(), max_qos); | |
| 30 | 30 | |
| 31 | 31 | if (qos == 0) |
| 32 | 32 | { | ... | ... |
session.h
| ... | ... | @@ -36,7 +36,7 @@ public: |
| 36 | 36 | bool clientDisconnected() const; |
| 37 | 37 | std::shared_ptr<Client> makeSharedClient() const; |
| 38 | 38 | void assignActiveConnection(std::shared_ptr<Client> &client); |
| 39 | - void writePacket(const MqttPacket &packet, char qos_arg); | |
| 39 | + void writePacket(const MqttPacket &packet, char max_qos); | |
| 40 | 40 | void clearQosMessage(uint16_t packet_id); |
| 41 | 41 | void sendPendingQosMessages(); |
| 42 | 42 | }; | ... | ... |
subscriptionstore.cpp
| ... | ... | @@ -65,19 +65,22 @@ void SubscriptionStore::addSubscription(Client_p &client, const std::string &top |
| 65 | 65 | deepestNode = node.get(); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | + assert(deepestNode); | |
| 69 | + | |
| 68 | 70 | if (deepestNode) |
| 69 | 71 | { |
| 70 | 72 | auto session_it = sessionsByIdConst.find(client->getClientId()); |
| 71 | 73 | if (session_it != sessionsByIdConst.end()) |
| 72 | 74 | { |
| 73 | - std::weak_ptr<Session> b = session_it->second; | |
| 74 | - deepestNode->addSubscriber(session_it->second, qos); | |
| 75 | + const std::shared_ptr<Session> &ses = session_it->second; | |
| 76 | + deepestNode->addSubscriber(ses, qos); | |
| 77 | + giveClientRetainedMessages(ses, topic, qos); | |
| 75 | 78 | } |
| 76 | 79 | } |
| 77 | 80 | |
| 78 | 81 | lock_guard.unlock(); |
| 79 | 82 | |
| 80 | - giveClientRetainedMessages(client, topic); | |
| 83 | + | |
| 81 | 84 | } |
| 82 | 85 | |
| 83 | 86 | // Removes an existing client when it already exists [MQTT-3.1.4-2]. |
| ... | ... | @@ -176,7 +179,7 @@ void SubscriptionStore::queuePacketAtSubscribers(const std::string &topic, const |
| 176 | 179 | publishRecursively(subtopics.begin(), subtopics.end(), root, packet); |
| 177 | 180 | } |
| 178 | 181 | |
| 179 | -void SubscriptionStore::giveClientRetainedMessages(Client_p &client, const std::string &subscribe_topic) | |
| 182 | +void SubscriptionStore::giveClientRetainedMessages(const std::shared_ptr<Session> &ses, const std::string &subscribe_topic, char max_qos) | |
| 180 | 183 | { |
| 181 | 184 | RWLockGuard locker(&retainedMessagesRwlock); |
| 182 | 185 | locker.rdlock(); |
| ... | ... | @@ -188,7 +191,7 @@ void SubscriptionStore::giveClientRetainedMessages(Client_p &client, const std:: |
| 188 | 191 | const MqttPacket packet(publish); |
| 189 | 192 | |
| 190 | 193 | if (topicsMatch(subscribe_topic, rm.topic)) |
| 191 | - client->writeMqttPacket(packet); // TODO: I think this needs to be session, not client, and then I can store it if it's QoS? I need to research how retain+qos works | |
| 194 | + ses->writePacket(packet, max_qos); | |
| 192 | 195 | } |
| 193 | 196 | } |
| 194 | 197 | ... | ... |
subscriptionstore.h
| ... | ... | @@ -69,7 +69,7 @@ public: |
| 69 | 69 | void registerClientAndKickExistingOne(Client_p &client); |
| 70 | 70 | |
| 71 | 71 | void queuePacketAtSubscribers(const std::string &topic, const MqttPacket &packet, const Client_p &sender); |
| 72 | - void giveClientRetainedMessages(Client_p &client, const std::string &subscribe_topic); | |
| 72 | + void giveClientRetainedMessages(const std::shared_ptr<Session> &ses, const std::string &subscribe_topic, char max_qos); | |
| 73 | 73 | |
| 74 | 74 | void setRetainedMessage(const std::string &topic, const std::string &payload, char qos); |
| 75 | 75 | }; | ... | ... |