Commit 9a34fc462fc342e97029fd886bf02111ffcb9c08
1 parent
a682f1e0
Change clean session into MQTT5 symantics
The behavior for MQTT3 clients in the same, but I replaced the term 'clean session' and described the behavior in MQTT5 terms, of 'clean start' and an expiry interval.
Showing
9 changed files
with
53 additions
and
57 deletions
FlashMQTests/tst_maintests.cpp
| @@ -1001,15 +1001,15 @@ void MainTests::testSavingSessions() | @@ -1001,15 +1001,15 @@ void MainTests::testSavingSessions() | ||
| 1001 | ThreadGlobals::assign(&auth); | 1001 | ThreadGlobals::assign(&auth); |
| 1002 | 1002 | ||
| 1003 | std::shared_ptr<Client> c1(new Client(0, t, nullptr, false, nullptr, settings, false)); | 1003 | std::shared_ptr<Client> c1(new Client(0, t, nullptr, false, nullptr, settings, false)); |
| 1004 | - c1->setClientProperties(ProtocolVersion::Mqtt311, "c1", "user1", true, 60, false); | ||
| 1005 | - store->registerClientAndKickExistingOne(c1); | 1004 | + c1->setClientProperties(ProtocolVersion::Mqtt311, "c1", "user1", true, 60); |
| 1005 | + store->registerClientAndKickExistingOne(c1, false, 512, 120); | ||
| 1006 | c1->getSession()->touch(); | 1006 | c1->getSession()->touch(); |
| 1007 | c1->getSession()->addIncomingQoS2MessageId(2); | 1007 | c1->getSession()->addIncomingQoS2MessageId(2); |
| 1008 | c1->getSession()->addIncomingQoS2MessageId(3); | 1008 | c1->getSession()->addIncomingQoS2MessageId(3); |
| 1009 | 1009 | ||
| 1010 | std::shared_ptr<Client> c2(new Client(0, t, nullptr, false, nullptr, settings, false)); | 1010 | std::shared_ptr<Client> c2(new Client(0, t, nullptr, false, nullptr, settings, false)); |
| 1011 | - c2->setClientProperties(ProtocolVersion::Mqtt311, "c2", "user2", true, 60, false); | ||
| 1012 | - store->registerClientAndKickExistingOne(c2); | 1011 | + c2->setClientProperties(ProtocolVersion::Mqtt311, "c2", "user2", true, 60); |
| 1012 | + store->registerClientAndKickExistingOne(c2, false, 512, 120); | ||
| 1013 | c2->getSession()->touch(); | 1013 | c2->getSession()->touch(); |
| 1014 | c2->getSession()->addOutgoingQoS2MessageId(55); | 1014 | c2->getSession()->addOutgoingQoS2MessageId(55); |
| 1015 | c2->getSession()->addOutgoingQoS2MessageId(66); | 1015 | c2->getSession()->addOutgoingQoS2MessageId(66); |
| @@ -1120,8 +1120,8 @@ void testCopyPacketHelper(const std::string &topic, char from_qos, char to_qos, | @@ -1120,8 +1120,8 @@ void testCopyPacketHelper(const std::string &topic, char from_qos, char to_qos, | ||
| 1120 | ThreadGlobals::assign(&auth); | 1120 | ThreadGlobals::assign(&auth); |
| 1121 | 1121 | ||
| 1122 | std::shared_ptr<Client> dummyClient(new Client(0, t, nullptr, false, nullptr, settings, false)); | 1122 | std::shared_ptr<Client> dummyClient(new Client(0, t, nullptr, false, nullptr, settings, false)); |
| 1123 | - dummyClient->setClientProperties(ProtocolVersion::Mqtt311, "qostestclient", "user1", true, 60, false); | ||
| 1124 | - store->registerClientAndKickExistingOne(dummyClient); | 1123 | + dummyClient->setClientProperties(ProtocolVersion::Mqtt311, "qostestclient", "user1", true, 60); |
| 1124 | + store->registerClientAndKickExistingOne(dummyClient, false, 512, 120); | ||
| 1125 | 1125 | ||
| 1126 | uint16_t packetid = 66; | 1126 | uint16_t packetid = 66; |
| 1127 | for (int len = 0; len < 150; len++ ) | 1127 | for (int len = 0; len < 150; len++ ) |
client.cpp
| @@ -75,7 +75,7 @@ Client::~Client() | @@ -75,7 +75,7 @@ Client::~Client() | ||
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | // MQTT-3.1.2-6 | 77 | // MQTT-3.1.2-6 |
| 78 | - if (cleanSession) | 78 | + if (session->getDestroyOnDisconnect()) |
| 79 | { | 79 | { |
| 80 | store->removeSession(clientid); | 80 | store->removeSession(clientid); |
| 81 | } | 81 | } |
| @@ -286,9 +286,9 @@ bool Client::writeBufIntoFd() | @@ -286,9 +286,9 @@ bool Client::writeBufIntoFd() | ||
| 286 | 286 | ||
| 287 | std::string Client::repr() | 287 | std::string Client::repr() |
| 288 | { | 288 | { |
| 289 | - std::string s = formatString("[ClientID='%s', username='%s', fd=%d, keepalive=%ds, transport='%s', address='%s', cleanses=%d, prot=%s]", | 289 | + std::string s = formatString("[ClientID='%s', username='%s', fd=%d, keepalive=%ds, transport='%s', address='%s', prot=%s]", |
| 290 | clientid.c_str(), username.c_str(), fd, keepalive, this->transportStr.c_str(), this->address.c_str(), | 290 | clientid.c_str(), username.c_str(), fd, keepalive, this->transportStr.c_str(), this->address.c_str(), |
| 291 | - cleanSession, protocolVersionString(protocolVersion).c_str()); | 291 | + protocolVersionString(protocolVersion).c_str()); |
| 292 | return s; | 292 | return s; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| @@ -334,11 +334,6 @@ void Client::resetBuffersIfEligible() | @@ -334,11 +334,6 @@ void Client::resetBuffersIfEligible() | ||
| 334 | writebuf.resetSizeIfEligable(initialBufferSize); | 334 | writebuf.resetSizeIfEligable(initialBufferSize); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | -void Client::setCleanSession(bool val) | ||
| 338 | -{ | ||
| 339 | - this->cleanSession = val; | ||
| 340 | -} | ||
| 341 | - | ||
| 342 | #ifndef NDEBUG | 337 | #ifndef NDEBUG |
| 343 | /** | 338 | /** |
| 344 | * @brief IoWrapper::setFakeUpgraded(). | 339 | * @brief IoWrapper::setFakeUpgraded(). |
| @@ -421,24 +416,22 @@ void Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::sh | @@ -421,24 +416,22 @@ void Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::sh | ||
| 421 | setReadyForReading(readbuf.freeSpace() > 0); | 416 | setReadyForReading(readbuf.freeSpace() > 0); |
| 422 | } | 417 | } |
| 423 | 418 | ||
| 424 | -void Client::setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, bool cleanSession) | 419 | +void Client::setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive) |
| 425 | { | 420 | { |
| 426 | const Settings *settings = ThreadGlobals::getSettings(); | 421 | const Settings *settings = ThreadGlobals::getSettings(); |
| 427 | 422 | ||
| 428 | - setClientProperties(protocolVersion, clientId, username, connectPacketSeen, keepalive, cleanSession, | ||
| 429 | - settings->maxPacketSize, 0); | 423 | + setClientProperties(protocolVersion, clientId, username, connectPacketSeen, keepalive, settings->maxPacketSize, 0); |
| 430 | } | 424 | } |
| 431 | 425 | ||
| 432 | 426 | ||
| 433 | void Client::setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, | 427 | void Client::setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, |
| 434 | - bool cleanSession, uint32_t maxPacketSize, uint16_t maxTopicAliases) | 428 | + uint32_t maxPacketSize, uint16_t maxTopicAliases) |
| 435 | { | 429 | { |
| 436 | this->protocolVersion = protocolVersion; | 430 | this->protocolVersion = protocolVersion; |
| 437 | this->clientid = clientId; | 431 | this->clientid = clientId; |
| 438 | this->username = username; | 432 | this->username = username; |
| 439 | this->connectPacketSeen = connectPacketSeen; | 433 | this->connectPacketSeen = connectPacketSeen; |
| 440 | this->keepalive = keepalive; | 434 | this->keepalive = keepalive; |
| 441 | - this->cleanSession = cleanSession; | ||
| 442 | this->maxPacketSize = maxPacketSize; | 435 | this->maxPacketSize = maxPacketSize; |
| 443 | this->maxTopicAliases = maxTopicAliases; | 436 | this->maxTopicAliases = maxTopicAliases; |
| 444 | } | 437 | } |
client.h
| @@ -74,7 +74,6 @@ class Client | @@ -74,7 +74,6 @@ class Client | ||
| 74 | std::string clientid; | 74 | std::string clientid; |
| 75 | std::string username; | 75 | std::string username; |
| 76 | uint16_t keepalive = 0; | 76 | uint16_t keepalive = 0; |
| 77 | - bool cleanSession = false; | ||
| 78 | 77 | ||
| 79 | std::string will_topic; | 78 | std::string will_topic; |
| 80 | std::string will_payload; | 79 | std::string will_payload; |
| @@ -108,9 +107,9 @@ public: | @@ -108,9 +107,9 @@ public: | ||
| 108 | void markAsDisconnecting(); | 107 | void markAsDisconnecting(); |
| 109 | bool readFdIntoBuffer(); | 108 | bool readFdIntoBuffer(); |
| 110 | void bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::shared_ptr<Client> &sender); | 109 | void bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn, std::shared_ptr<Client> &sender); |
| 111 | - void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, bool cleanSession); | 110 | + void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive); |
| 112 | void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, | 111 | void setClientProperties(ProtocolVersion protocolVersion, const std::string &clientId, const std::string username, bool connectPacketSeen, uint16_t keepalive, |
| 113 | - bool cleanSession, uint32_t maxPacketSize, uint16_t maxTopicAliases); | 112 | + uint32_t maxPacketSize, uint16_t maxTopicAliases); |
| 114 | void setWill(const std::string &topic, const std::string &payload, bool retain, char qos); | 113 | void setWill(const std::string &topic, const std::string &payload, bool retain, char qos); |
| 115 | void clearWill(); | 114 | void clearWill(); |
| 116 | void setAuthenticated(bool value) { authenticated = value;} | 115 | void setAuthenticated(bool value) { authenticated = value;} |
| @@ -119,7 +118,6 @@ public: | @@ -119,7 +118,6 @@ public: | ||
| 119 | std::shared_ptr<ThreadData> getThreadData() { return threadData; } | 118 | std::shared_ptr<ThreadData> getThreadData() { return threadData; } |
| 120 | std::string &getClientId() { return this->clientid; } | 119 | std::string &getClientId() { return this->clientid; } |
| 121 | const std::string &getUsername() const { return this->username; } | 120 | const std::string &getUsername() const { return this->username; } |
| 122 | - bool getCleanSession() { return cleanSession; } | ||
| 123 | void assignSession(std::shared_ptr<Session> &session); | 121 | void assignSession(std::shared_ptr<Session> &session); |
| 124 | std::shared_ptr<Session> getSession(); | 122 | std::shared_ptr<Session> getSession(); |
| 125 | void setDisconnectReason(const std::string &reason); | 123 | void setDisconnectReason(const std::string &reason); |
| @@ -140,8 +138,6 @@ public: | @@ -140,8 +138,6 @@ public: | ||
| 140 | std::string getKeepAliveInfoString() const; | 138 | std::string getKeepAliveInfoString() const; |
| 141 | void resetBuffersIfEligible(); | 139 | void resetBuffersIfEligible(); |
| 142 | 140 | ||
| 143 | - void setCleanSession(bool val); | ||
| 144 | - | ||
| 145 | #ifndef NDEBUG | 141 | #ifndef NDEBUG |
| 146 | void setFakeUpgraded(); | 142 | void setFakeUpgraded(); |
| 147 | #endif | 143 | #endif |
mainapp.cpp
| @@ -442,11 +442,11 @@ void MainApp::start() | @@ -442,11 +442,11 @@ void MainApp::start() | ||
| 442 | 442 | ||
| 443 | std::shared_ptr<Client> client = std::make_shared<Client>(fd, threaddata, nullptr, fuzzWebsockets, nullptr, settings, true); | 443 | std::shared_ptr<Client> client = std::make_shared<Client>(fd, threaddata, nullptr, fuzzWebsockets, nullptr, settings, true); |
| 444 | std::shared_ptr<Client> subscriber = std::make_shared<Client>(fdnull, threaddata, nullptr, fuzzWebsockets, nullptr, settings, true); | 444 | std::shared_ptr<Client> subscriber = std::make_shared<Client>(fdnull, threaddata, nullptr, fuzzWebsockets, nullptr, settings, true); |
| 445 | - subscriber->setClientProperties(ProtocolVersion::Mqtt311, "subscriber", "subuser", true, 60, true); | 445 | + subscriber->setClientProperties(ProtocolVersion::Mqtt311, "subscriber", "subuser", true, 60); |
| 446 | subscriber->setAuthenticated(true); | 446 | subscriber->setAuthenticated(true); |
| 447 | 447 | ||
| 448 | std::shared_ptr<Client> websocketsubscriber = std::make_shared<Client>(fdnull2, threaddata, nullptr, true, nullptr, settings, true); | 448 | std::shared_ptr<Client> websocketsubscriber = std::make_shared<Client>(fdnull2, threaddata, nullptr, true, nullptr, settings, true); |
| 449 | - websocketsubscriber->setClientProperties(ProtocolVersion::Mqtt311, "websocketsubscriber", "websocksubuser", true, 60, true); | 449 | + websocketsubscriber->setClientProperties(ProtocolVersion::Mqtt311, "websocketsubscriber", "websocksubuser", true, 60); |
| 450 | websocketsubscriber->setAuthenticated(true); | 450 | websocketsubscriber->setAuthenticated(true); |
| 451 | websocketsubscriber->setFakeUpgraded(); | 451 | websocketsubscriber->setFakeUpgraded(); |
| 452 | subscriptionStore->registerClientAndKickExistingOne(websocketsubscriber); | 452 | subscriptionStore->registerClientAndKickExistingOne(websocketsubscriber); |
mqttpacket.cpp
| @@ -363,7 +363,7 @@ void MqttPacket::handleConnect() | @@ -363,7 +363,7 @@ void MqttPacket::handleConnect() | ||
| 363 | bool will_retain = !!(flagByte & 0b00100000); | 363 | bool will_retain = !!(flagByte & 0b00100000); |
| 364 | char will_qos = (flagByte & 0b00011000) >> 3; | 364 | char will_qos = (flagByte & 0b00011000) >> 3; |
| 365 | bool will_flag = !!(flagByte & 0b00000100); | 365 | bool will_flag = !!(flagByte & 0b00000100); |
| 366 | - bool clean_session = !!(flagByte & 0b00000010); | 366 | + bool clean_start = !!(flagByte & 0b00000010); |
| 367 | 367 | ||
| 368 | if (will_qos > 2) | 368 | if (will_qos > 2) |
| 369 | throw ProtocolError("Invalid QoS for will."); | 369 | throw ProtocolError("Invalid QoS for will."); |
| @@ -467,9 +467,9 @@ void MqttPacket::handleConnect() | @@ -467,9 +467,9 @@ void MqttPacket::handleConnect() | ||
| 467 | logger->logf(LOG_ERR, "ClientID '%s' has + or # in the id and 'allow_unsafe_clientid_chars' is false.", client_id.c_str()); | 467 | logger->logf(LOG_ERR, "ClientID '%s' has + or # in the id and 'allow_unsafe_clientid_chars' is false.", client_id.c_str()); |
| 468 | validClientId = false; | 468 | validClientId = false; |
| 469 | } | 469 | } |
| 470 | - else if (!clean_session && client_id.empty()) | 470 | + else if (!clean_start && client_id.empty()) |
| 471 | { | 471 | { |
| 472 | - logger->logf(LOG_ERR, "ClientID empty and clean session 0, which is incompatible"); | 472 | + logger->logf(LOG_ERR, "ClientID empty and clean start 0, which is incompatible"); |
| 473 | validClientId = false; | 473 | validClientId = false; |
| 474 | } | 474 | } |
| 475 | else if (protocolVersion < ProtocolVersion::Mqtt311 && client_id.empty()) | 475 | else if (protocolVersion < ProtocolVersion::Mqtt311 && client_id.empty()) |
| @@ -493,7 +493,7 @@ void MqttPacket::handleConnect() | @@ -493,7 +493,7 @@ void MqttPacket::handleConnect() | ||
| 493 | client_id = getSecureRandomString(23); | 493 | client_id = getSecureRandomString(23); |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | - sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, clean_session, max_packet_size, max_topic_aliases); | 496 | + sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_packet_size, max_topic_aliases); |
| 497 | sender->setWill(will_topic, will_payload, will_retain, will_qos); | 497 | sender->setWill(will_topic, will_payload, will_retain, will_qos); |
| 498 | 498 | ||
| 499 | bool accessGranted = false; | 499 | bool accessGranted = false; |
| @@ -518,7 +518,7 @@ void MqttPacket::handleConnect() | @@ -518,7 +518,7 @@ void MqttPacket::handleConnect() | ||
| 518 | 518 | ||
| 519 | if (accessGranted) | 519 | if (accessGranted) |
| 520 | { | 520 | { |
| 521 | - bool sessionPresent = protocolVersion >= ProtocolVersion::Mqtt311 && !clean_session && subscriptionStore->sessionPresent(client_id); | 521 | + bool sessionPresent = protocolVersion >= ProtocolVersion::Mqtt311 && !clean_start && subscriptionStore->sessionPresent(client_id); |
| 522 | 522 | ||
| 523 | sender->setAuthenticated(true); | 523 | sender->setAuthenticated(true); |
| 524 | ConnAck connAck(ConnAckReturnCodes::Accepted, sessionPresent); | 524 | ConnAck connAck(ConnAckReturnCodes::Accepted, sessionPresent); |
| @@ -526,7 +526,7 @@ void MqttPacket::handleConnect() | @@ -526,7 +526,7 @@ void MqttPacket::handleConnect() | ||
| 526 | sender->writeMqttPacket(response); | 526 | sender->writeMqttPacket(response); |
| 527 | logger->logf(LOG_NOTICE, "Client '%s' logged in successfully", sender->repr().c_str()); | 527 | logger->logf(LOG_NOTICE, "Client '%s' logged in successfully", sender->repr().c_str()); |
| 528 | 528 | ||
| 529 | - subscriptionStore->registerClientAndKickExistingOne(sender, max_qos_packets, session_expire); | 529 | + subscriptionStore->registerClientAndKickExistingOne(sender, clean_start, max_qos_packets, session_expire); |
| 530 | } | 530 | } |
| 531 | else | 531 | else |
| 532 | { | 532 | { |
session.cpp
| @@ -76,8 +76,7 @@ bool Session::requiresPacketRetransmission() const | @@ -76,8 +76,7 @@ bool Session::requiresPacketRetransmission() const | ||
| 76 | if (client->getProtocolVersion() < ProtocolVersion::Mqtt311) | 76 | if (client->getProtocolVersion() < ProtocolVersion::Mqtt311) |
| 77 | return true; | 77 | return true; |
| 78 | 78 | ||
| 79 | - // TODO: for MQTT5, the rules are different. | ||
| 80 | - return !client->getCleanSession(); | 79 | + return !destroyOnDisconnect; |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | void Session::increasePacketId() | 82 | void Session::increasePacketId() |
| @@ -343,18 +342,30 @@ void Session::removeOutgoingQoS2MessageId(u_int16_t packet_id) | @@ -343,18 +342,30 @@ void Session::removeOutgoingQoS2MessageId(u_int16_t packet_id) | ||
| 343 | outgoingQoS2MessageIds.erase(it); | 342 | outgoingQoS2MessageIds.erase(it); |
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | -bool Session::getCleanSession() const | 345 | +/** |
| 346 | + * @brief Session::getDestroyOnDisconnect | ||
| 347 | + * @return | ||
| 348 | + * | ||
| 349 | + * MQTT5: Setting Clean Start to 1 and a Session Expiry Interval of 0, is equivalent to setting CleanSession to 1 in the MQTT Specification Version 3.1.1. | ||
| 350 | + */ | ||
| 351 | +bool Session::getDestroyOnDisconnect() const | ||
| 347 | { | 352 | { |
| 348 | - auto c = client.lock(); | ||
| 349 | - | ||
| 350 | - if (!c) | ||
| 351 | - return false; | ||
| 352 | - | ||
| 353 | - return c->getCleanSession(); | 353 | + return destroyOnDisconnect; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | -void Session::setSessionProperties(uint16_t maxQosPackets, uint32_t sessionExpiryInterval) | 356 | +void Session::setSessionProperties(uint16_t maxQosPackets, uint32_t sessionExpiryInterval, bool clean_start, ProtocolVersion protocol_version) |
| 357 | { | 357 | { |
| 358 | this->maxQosMsgPending = maxQosPackets; | 358 | this->maxQosMsgPending = maxQosPackets; |
| 359 | this->sessionExpiryInterval = sessionExpiryInterval; | 359 | this->sessionExpiryInterval = sessionExpiryInterval; |
| 360 | + | ||
| 361 | + if (protocol_version <= ProtocolVersion::Mqtt311 && clean_start) | ||
| 362 | + destroyOnDisconnect = true; | ||
| 363 | + else | ||
| 364 | + destroyOnDisconnect = sessionExpiryInterval == 0; | ||
| 360 | } | 365 | } |
| 366 | + | ||
| 367 | +uint32_t Session::getSessionExpiryInterval() const | ||
| 368 | +{ | ||
| 369 | + return this->sessionExpiryInterval; | ||
| 370 | +} | ||
| 371 | + |
session.h
| @@ -49,6 +49,7 @@ class Session | @@ -49,6 +49,7 @@ class Session | ||
| 49 | uint32_t sessionExpiryInterval = 0; | 49 | uint32_t sessionExpiryInterval = 0; |
| 50 | uint16_t maxQosMsgPending; | 50 | uint16_t maxQosMsgPending; |
| 51 | uint16_t QoSLogPrintedAtId = 0; | 51 | uint16_t QoSLogPrintedAtId = 0; |
| 52 | + bool destroyOnDisconnect = false; | ||
| 52 | std::chrono::time_point<std::chrono::steady_clock> lastTouched = std::chrono::steady_clock::now(); | 53 | std::chrono::time_point<std::chrono::steady_clock> lastTouched = std::chrono::steady_clock::now(); |
| 53 | Logger *logger = Logger::getInstance(); | 54 | Logger *logger = Logger::getInstance(); |
| 54 | 55 | ||
| @@ -86,9 +87,10 @@ public: | @@ -86,9 +87,10 @@ public: | ||
| 86 | void addOutgoingQoS2MessageId(uint16_t packet_id); | 87 | void addOutgoingQoS2MessageId(uint16_t packet_id); |
| 87 | void removeOutgoingQoS2MessageId(u_int16_t packet_id); | 88 | void removeOutgoingQoS2MessageId(u_int16_t packet_id); |
| 88 | 89 | ||
| 89 | - bool getCleanSession() const; | 90 | + bool getDestroyOnDisconnect() const; |
| 90 | 91 | ||
| 91 | - void setSessionProperties(uint16_t maxQosPackets, uint32_t sessionExpiryInterval); | 92 | + void setSessionProperties(uint16_t maxQosPackets, uint32_t sessionExpiryInterval, bool clean_start, ProtocolVersion protocol_version); |
| 93 | + uint32_t getSessionExpiryInterval() const; | ||
| 92 | }; | 94 | }; |
| 93 | 95 | ||
| 94 | #endif // SESSION_H | 96 | #endif // SESSION_H |
subscriptionstore.cpp
| @@ -204,11 +204,11 @@ void SubscriptionStore::removeSubscription(std::shared_ptr<Client> &client, cons | @@ -204,11 +204,11 @@ void SubscriptionStore::removeSubscription(std::shared_ptr<Client> &client, cons | ||
| 204 | void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> &client) | 204 | void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> &client) |
| 205 | { | 205 | { |
| 206 | const Settings *settings = ThreadGlobals::getSettings(); | 206 | const Settings *settings = ThreadGlobals::getSettings(); |
| 207 | - registerClientAndKickExistingOne(client, settings->maxQosMsgPendingPerClient, settings->expireSessionsAfterSeconds); | 207 | + registerClientAndKickExistingOne(client, true, settings->maxQosMsgPendingPerClient, settings->expireSessionsAfterSeconds); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | // Removes an existing client when it already exists [MQTT-3.1.4-2]. | 210 | // Removes an existing client when it already exists [MQTT-3.1.4-2]. |
| 211 | -void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> &client, uint16_t maxQosPackets, uint32_t sessionExpiryInterval) | 211 | +void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> &client, bool clean_start, uint16_t maxQosPackets, uint32_t sessionExpiryInterval) |
| 212 | { | 212 | { |
| 213 | RWLockGuard lock_guard(&subscriptionsRwlock); | 213 | RWLockGuard lock_guard(&subscriptionsRwlock); |
| 214 | lock_guard.wrlock(); | 214 | lock_guard.wrlock(); |
| @@ -216,7 +216,6 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | @@ -216,7 +216,6 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | ||
| 216 | if (client->getClientId().empty()) | 216 | if (client->getClientId().empty()) |
| 217 | throw ProtocolError("Trying to store client without an ID."); | 217 | throw ProtocolError("Trying to store client without an ID."); |
| 218 | 218 | ||
| 219 | - bool originalClientDemandsSessionDestruction = false; | ||
| 220 | std::shared_ptr<Session> session; | 219 | std::shared_ptr<Session> session; |
| 221 | auto session_it = sessionsById.find(client->getClientId()); | 220 | auto session_it = sessionsById.find(client->getClientId()); |
| 222 | if (session_it != sessionsById.end()) | 221 | if (session_it != sessionsById.end()) |
| @@ -232,11 +231,6 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | @@ -232,11 +231,6 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | ||
| 232 | logger->logf(LOG_NOTICE, "Disconnecting existing client with id '%s'", cl->getClientId().c_str()); | 231 | logger->logf(LOG_NOTICE, "Disconnecting existing client with id '%s'", cl->getClientId().c_str()); |
| 233 | cl->setDisconnectReason("Another client with this ID connected"); | 232 | cl->setDisconnectReason("Another client with this ID connected"); |
| 234 | 233 | ||
| 235 | - // We have to set session to false, because it's no longer up to the destruction of that client | ||
| 236 | - // to destroy the session. We either do it in this function, or not at all. | ||
| 237 | - originalClientDemandsSessionDestruction = cl->getCleanSession(); | ||
| 238 | - cl->setCleanSession(false); | ||
| 239 | - | ||
| 240 | cl->setReadyForDisconnect(); | 234 | cl->setReadyForDisconnect(); |
| 241 | cl->getThreadData()->removeClientQueued(cl); | 235 | cl->getThreadData()->removeClientQueued(cl); |
| 242 | cl->markAsDisconnecting(); | 236 | cl->markAsDisconnecting(); |
| @@ -245,7 +239,7 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | @@ -245,7 +239,7 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | ||
| 245 | } | 239 | } |
| 246 | } | 240 | } |
| 247 | 241 | ||
| 248 | - if (!session || client->getCleanSession() || originalClientDemandsSessionDestruction) | 242 | + if (!session || session->getDestroyOnDisconnect()) |
| 249 | { | 243 | { |
| 250 | session = std::make_shared<Session>(); | 244 | session = std::make_shared<Session>(); |
| 251 | 245 | ||
| @@ -254,7 +248,7 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | @@ -254,7 +248,7 @@ void SubscriptionStore::registerClientAndKickExistingOne(std::shared_ptr<Client> | ||
| 254 | 248 | ||
| 255 | session->assignActiveConnection(client); | 249 | session->assignActiveConnection(client); |
| 256 | client->assignSession(session); | 250 | client->assignSession(session); |
| 257 | - session->setSessionProperties(maxQosPackets, sessionExpiryInterval); | 251 | + session->setSessionProperties(maxQosPackets, sessionExpiryInterval, clean_start, client->getProtocolVersion()); |
| 258 | uint64_t count = session->sendPendingQosMessages(); | 252 | uint64_t count = session->sendPendingQosMessages(); |
| 259 | client->getThreadData()->incrementSentMessageCount(count); | 253 | client->getThreadData()->incrementSentMessageCount(count); |
| 260 | } | 254 | } |
| @@ -744,7 +738,7 @@ void SubscriptionStore::saveSessionsAndSubscriptions(const std::string &filePath | @@ -744,7 +738,7 @@ void SubscriptionStore::saveSessionsAndSubscriptions(const std::string &filePath | ||
| 744 | const Session &org = *pair.second.get(); | 738 | const Session &org = *pair.second.get(); |
| 745 | 739 | ||
| 746 | // Sessions created with clean session need to be destroyed when disconnecting, so no point in saving them. | 740 | // Sessions created with clean session need to be destroyed when disconnecting, so no point in saving them. |
| 747 | - if (org.getCleanSession()) | 741 | + if (org.getDestroyOnDisconnect()) |
| 748 | continue; | 742 | continue; |
| 749 | 743 | ||
| 750 | sessionCopies.push_back(org.getCopy()); | 744 | sessionCopies.push_back(org.getCopy()); |
subscriptionstore.h
| @@ -119,7 +119,7 @@ public: | @@ -119,7 +119,7 @@ public: | ||
| 119 | void addSubscription(std::shared_ptr<Client> &client, const std::string &topic, const std::vector<std::string> &subtopics, char qos); | 119 | void addSubscription(std::shared_ptr<Client> &client, const std::string &topic, const std::vector<std::string> &subtopics, char qos); |
| 120 | void removeSubscription(std::shared_ptr<Client> &client, const std::string &topic); | 120 | void removeSubscription(std::shared_ptr<Client> &client, const std::string &topic); |
| 121 | void registerClientAndKickExistingOne(std::shared_ptr<Client> &client); | 121 | void registerClientAndKickExistingOne(std::shared_ptr<Client> &client); |
| 122 | - void registerClientAndKickExistingOne(std::shared_ptr<Client> &client, uint16_t maxQosPackets, uint32_t sessionExpiryInterval); | 122 | + void registerClientAndKickExistingOne(std::shared_ptr<Client> &client, bool clean_start, uint16_t maxQosPackets, uint32_t sessionExpiryInterval); |
| 123 | bool sessionPresent(const std::string &clientid); | 123 | bool sessionPresent(const std::string &clientid); |
| 124 | 124 | ||
| 125 | void queuePacketAtSubscribers(const std::vector<std::string> &subtopics, MqttPacket &packet, bool dollar = false); | 125 | void queuePacketAtSubscribers(const std::vector<std::string> &subtopics, MqttPacket &packet, bool dollar = false); |