Commit 940d7edcfc79174cff791b336000dbc2025a58c1
1 parent
592e12eb
Replace the thread_local global subtopic memory
It caused typical global variable issues, showing in the retained messages recursive alghorithm breaking, because the referenced subtopics changed half way (see previous commit of the test for it). I need to perform some benchmarks to see if I need to devise an alternative.
Showing
3 changed files
with
12 additions
and
21 deletions
mqttpacket.cpp
| ... | ... | @@ -24,10 +24,6 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. |
| 24 | 24 | #include "utils.h" |
| 25 | 25 | #include "threadauth.h" |
| 26 | 26 | |
| 27 | -// We can void constant reallocation of space for parsed subtopics by using this. But, beware to only use it during handling of the current | |
| 28 | -// packet. Don't access it for a stored packet, because then it will have changed. | |
| 29 | -thread_local std::vector<std::string> gSubtopics; | |
| 30 | - | |
| 31 | 27 | RemainingLength::RemainingLength() |
| 32 | 28 | { |
| 33 | 29 | memset(bytes, 0, 4); |
| ... | ... | @@ -110,8 +106,7 @@ MqttPacket::MqttPacket(const Publish &publish) : |
| 110 | 106 | } |
| 111 | 107 | |
| 112 | 108 | this->topic = publish.topic; |
| 113 | - this->subtopics = &gSubtopics; | |
| 114 | - splitTopic(this->topic, gSubtopics); | |
| 109 | + splitTopic(this->topic, subtopics); | |
| 115 | 110 | |
| 116 | 111 | packetType = PacketType::PUBLISH; |
| 117 | 112 | this->qos = publish.qos; |
| ... | ... | @@ -417,7 +412,6 @@ void MqttPacket::handleDisconnect() |
| 417 | 412 | |
| 418 | 413 | void MqttPacket::handleSubscribe() |
| 419 | 414 | { |
| 420 | - this->subtopics = &gSubtopics; | |
| 421 | 415 | const char firstByteFirstNibble = (first_byte & 0x0F); |
| 422 | 416 | |
| 423 | 417 | if (firstByteFirstNibble != 2) |
| ... | ... | @@ -449,11 +443,11 @@ void MqttPacket::handleSubscribe() |
| 449 | 443 | if (qos > 2) |
| 450 | 444 | throw ProtocolError("QoS is greater than 2, and/or reserved bytes in QoS field are not 0."); |
| 451 | 445 | |
| 452 | - splitTopic(topic, *subtopics); | |
| 453 | - if (authentication.aclCheck(sender->getClientId(), sender->getUsername(), topic, *subtopics, AclAccess::subscribe, qos, false) == AuthResult::success) | |
| 446 | + splitTopic(topic, subtopics); | |
| 447 | + if (authentication.aclCheck(sender->getClientId(), sender->getUsername(), topic, subtopics, AclAccess::subscribe, qos, false) == AuthResult::success) | |
| 454 | 448 | { |
| 455 | 449 | logger->logf(LOG_SUBSCRIBE, "Client '%s' subscribed to '%s' QoS %d", sender->repr().c_str(), topic.c_str(), qos); |
| 456 | - sender->getThreadData()->getSubscriptionStore()->addSubscription(sender, topic, *subtopics, qos); | |
| 450 | + sender->getThreadData()->getSubscriptionStore()->addSubscription(sender, topic, subtopics, qos); | |
| 457 | 451 | subs_reponse_codes.push_back(qos); |
| 458 | 452 | } |
| 459 | 453 | else |
| ... | ... | @@ -477,7 +471,6 @@ void MqttPacket::handleSubscribe() |
| 477 | 471 | SubAck subAck(packet_id, subs_reponse_codes); |
| 478 | 472 | MqttPacket response(subAck); |
| 479 | 473 | sender->writeMqttPacket(response); |
| 480 | - this->subtopics = nullptr; | |
| 481 | 474 | } |
| 482 | 475 | |
| 483 | 476 | void MqttPacket::handleUnsubscribe() |
| ... | ... | @@ -540,8 +533,7 @@ void MqttPacket::handlePublish() |
| 540 | 533 | throw ProtocolError("Duplicate flag is set for QoS 0 packet. This is illegal."); |
| 541 | 534 | |
| 542 | 535 | topic = std::string(readBytes(variable_header_length), variable_header_length); |
| 543 | - subtopics = &gSubtopics; | |
| 544 | - splitTopic(topic, gSubtopics); | |
| 536 | + splitTopic(topic, subtopics); | |
| 545 | 537 | |
| 546 | 538 | if (!isValidUtf8(topic, true)) |
| 547 | 539 | { |
| ... | ... | @@ -593,12 +585,12 @@ void MqttPacket::handlePublish() |
| 593 | 585 | payloadStart = pos; |
| 594 | 586 | |
| 595 | 587 | Authentication &authentication = *ThreadAuth::getAuth(); |
| 596 | - if (authentication.aclCheck(sender->getClientId(), sender->getUsername(), topic, *subtopics, AclAccess::write, qos, retain) == AuthResult::success) | |
| 588 | + if (authentication.aclCheck(sender->getClientId(), sender->getUsername(), topic, subtopics, AclAccess::write, qos, retain) == AuthResult::success) | |
| 597 | 589 | { |
| 598 | 590 | if (retain) |
| 599 | 591 | { |
| 600 | 592 | std::string payload(readBytes(payloadLen), payloadLen); |
| 601 | - sender->getThreadData()->getSubscriptionStore()->setRetainedMessage(topic, *subtopics, payload, qos); | |
| 593 | + sender->getThreadData()->getSubscriptionStore()->setRetainedMessage(topic, subtopics, payload, qos); | |
| 602 | 594 | } |
| 603 | 595 | |
| 604 | 596 | // Set dup flag to 0, because that must not be propagated [MQTT-3.3.1-3]. |
| ... | ... | @@ -607,9 +599,8 @@ void MqttPacket::handlePublish() |
| 607 | 599 | first_byte = bites[0]; |
| 608 | 600 | |
| 609 | 601 | // For the existing clients, we can just write the same packet back out, with our small alterations. |
| 610 | - sender->getThreadData()->getSubscriptionStore()->queuePacketAtSubscribers(*subtopics, *this); | |
| 602 | + sender->getThreadData()->getSubscriptionStore()->queuePacketAtSubscribers(subtopics, *this); | |
| 611 | 603 | } |
| 612 | - this->subtopics = nullptr; | |
| 613 | 604 | } |
| 614 | 605 | |
| 615 | 606 | void MqttPacket::handlePubAck() |
| ... | ... | @@ -767,7 +758,7 @@ const std::string &MqttPacket::getTopic() const |
| 767 | 758 | * @brief MqttPacket::getSubtopics returns a pointer to the parsed subtopics. Use with care! |
| 768 | 759 | * @return a pointer to a vector of subtopics that will be overwritten the next packet! |
| 769 | 760 | */ |
| 770 | -const std::vector<std::string> *MqttPacket::getSubtopics() const | |
| 761 | +const std::vector<std::string> &MqttPacket::getSubtopics() const | |
| 771 | 762 | { |
| 772 | 763 | return this->subtopics; |
| 773 | 764 | } | ... | ... |
mqttpacket.h
| ... | ... | @@ -48,7 +48,7 @@ class MqttPacket |
| 48 | 48 | #endif |
| 49 | 49 | |
| 50 | 50 | std::string topic; |
| 51 | - std::vector<std::string> *subtopics = nullptr; | |
| 51 | + std::vector<std::string> subtopics; | |
| 52 | 52 | std::vector<char> bites; |
| 53 | 53 | size_t fixed_header_length = 0; // if 0, this packet does not contain the bytes of the fixed header. |
| 54 | 54 | RemainingLength remainingLength; |
| ... | ... | @@ -108,7 +108,7 @@ public: |
| 108 | 108 | const std::vector<char> &getBites() const { return bites; } |
| 109 | 109 | char getQos() const { return qos; } |
| 110 | 110 | const std::string &getTopic() const; |
| 111 | - const std::vector<std::string> *getSubtopics() const; | |
| 111 | + const std::vector<std::string> &getSubtopics() const; | |
| 112 | 112 | std::shared_ptr<Client> getSender() const; |
| 113 | 113 | void setSender(const std::shared_ptr<Client> &value); |
| 114 | 114 | bool containsFixedHeader() const; | ... | ... |
session.cpp
| ... | ... | @@ -129,7 +129,7 @@ void Session::writePacket(const MqttPacket &packet, char max_qos, bool retain, u |
| 129 | 129 | Authentication *_auth = ThreadAuth::getAuth(); |
| 130 | 130 | assert(_auth); |
| 131 | 131 | Authentication &auth = *_auth; |
| 132 | - if (auth.aclCheck(client_id, username, packet.getTopic(), *packet.getSubtopics(), AclAccess::read, qos, retain) == AuthResult::success) | |
| 132 | + if (auth.aclCheck(client_id, username, packet.getTopic(), packet.getSubtopics(), AclAccess::read, qos, retain) == AuthResult::success) | |
| 133 | 133 | { |
| 134 | 134 | if (qos == 0) |
| 135 | 135 | { | ... | ... |