Commit 27b65bef85f713382f55dab4e30148438ac6ab4a
1 parent
56d9c510
Add tests for will
Showing
9 changed files
with
258 additions
and
14 deletions
FlashMQTests/tst_maintests.cpp
| @@ -122,6 +122,12 @@ private slots: | @@ -122,6 +122,12 @@ private slots: | ||
| 122 | 122 | ||
| 123 | void testBasicsWithFlashMQTestClient(); | 123 | void testBasicsWithFlashMQTestClient(); |
| 124 | 124 | ||
| 125 | + void testMqtt3will(); | ||
| 126 | + void testMqtt3NoWillOnDisconnect(); | ||
| 127 | + void testMqtt5NoWillOnDisconnect(); | ||
| 128 | + void testMqtt5DelayedWill(); | ||
| 129 | + void testMqtt5DelayedWillAlwaysOnSessionEnd(); | ||
| 130 | + | ||
| 125 | }; | 131 | }; |
| 126 | 132 | ||
| 127 | MainTests::MainTests() | 133 | MainTests::MainTests() |
| @@ -1424,6 +1430,151 @@ void MainTests::testBasicsWithFlashMQTestClient() | @@ -1424,6 +1430,151 @@ void MainTests::testBasicsWithFlashMQTestClient() | ||
| 1424 | 1430 | ||
| 1425 | } | 1431 | } |
| 1426 | 1432 | ||
| 1433 | +void MainTests::testMqtt3will() | ||
| 1434 | +{ | ||
| 1435 | + std::unique_ptr<FlashMQTestClient> sender = std::make_unique<FlashMQTestClient>(); | ||
| 1436 | + sender->start(); | ||
| 1437 | + std::shared_ptr<WillPublish> will = std::make_shared<WillPublish>(); | ||
| 1438 | + will->topic = "my/will"; | ||
| 1439 | + will->payload = "mypayload"; | ||
| 1440 | + sender->setWill(will); | ||
| 1441 | + sender->connectClient(ProtocolVersion::Mqtt311); | ||
| 1442 | + | ||
| 1443 | + FlashMQTestClient receiver; | ||
| 1444 | + receiver.start(); | ||
| 1445 | + receiver.connectClient(ProtocolVersion::Mqtt311); | ||
| 1446 | + receiver.subscribe("my/will", 0); | ||
| 1447 | + | ||
| 1448 | + sender.reset(); | ||
| 1449 | + | ||
| 1450 | + receiver.waitForMessageCount(1); | ||
| 1451 | + | ||
| 1452 | + MqttPacket pubPack = receiver.receivedPublishes.front(); | ||
| 1453 | + pubPack.parsePublishData(); | ||
| 1454 | + | ||
| 1455 | + QCOMPARE(pubPack.getPublishData().topic, "my/will"); | ||
| 1456 | + QCOMPARE(pubPack.getPublishData().payload, "mypayload"); | ||
| 1457 | + QCOMPARE(pubPack.getPublishData().qos, 0); | ||
| 1458 | +} | ||
| 1459 | + | ||
| 1460 | +void MainTests::testMqtt3NoWillOnDisconnect() | ||
| 1461 | +{ | ||
| 1462 | + std::unique_ptr<FlashMQTestClient> sender = std::make_unique<FlashMQTestClient>(); | ||
| 1463 | + sender->start(); | ||
| 1464 | + std::shared_ptr<WillPublish> will = std::make_shared<WillPublish>(); | ||
| 1465 | + will->topic = "my/will/testMqtt3NoWillOnDisconnect"; | ||
| 1466 | + will->payload = "mypayload"; | ||
| 1467 | + sender->setWill(will); | ||
| 1468 | + sender->connectClient(ProtocolVersion::Mqtt311); | ||
| 1469 | + | ||
| 1470 | + FlashMQTestClient receiver; | ||
| 1471 | + receiver.start(); | ||
| 1472 | + receiver.connectClient(ProtocolVersion::Mqtt311); | ||
| 1473 | + receiver.subscribe("my/will/testMqtt3NoWillOnDisconnect", 0); | ||
| 1474 | + | ||
| 1475 | + receiver.clearReceivedLists(); | ||
| 1476 | + | ||
| 1477 | + sender->disconnect(ReasonCodes::Success); | ||
| 1478 | + sender.reset(); | ||
| 1479 | + | ||
| 1480 | + usleep(250000); | ||
| 1481 | + | ||
| 1482 | + QVERIFY(receiver.receivedPackets.empty()); | ||
| 1483 | +} | ||
| 1484 | + | ||
| 1485 | +void MainTests::testMqtt5NoWillOnDisconnect() | ||
| 1486 | +{ | ||
| 1487 | + std::unique_ptr<FlashMQTestClient> sender = std::make_unique<FlashMQTestClient>(); | ||
| 1488 | + sender->start(); | ||
| 1489 | + std::shared_ptr<WillPublish> will = std::make_shared<WillPublish>(); | ||
| 1490 | + will->topic = "my/will/testMqtt5NoWillOnDisconnect"; | ||
| 1491 | + will->payload = "mypayload"; | ||
| 1492 | + sender->setWill(will); | ||
| 1493 | + sender->connectClient(ProtocolVersion::Mqtt5); | ||
| 1494 | + | ||
| 1495 | + FlashMQTestClient receiver; | ||
| 1496 | + receiver.start(); | ||
| 1497 | + receiver.connectClient(ProtocolVersion::Mqtt5); | ||
| 1498 | + receiver.subscribe("my/will/testMqtt3NoWillOnDisconnect", 0); | ||
| 1499 | + | ||
| 1500 | + receiver.clearReceivedLists(); | ||
| 1501 | + | ||
| 1502 | + sender->disconnect(ReasonCodes::Success); | ||
| 1503 | + sender.reset(); | ||
| 1504 | + | ||
| 1505 | + usleep(250000); | ||
| 1506 | + | ||
| 1507 | + QVERIFY(receiver.receivedPackets.empty()); | ||
| 1508 | +} | ||
| 1509 | + | ||
| 1510 | +void MainTests::testMqtt5DelayedWill() | ||
| 1511 | +{ | ||
| 1512 | + std::unique_ptr<FlashMQTestClient> sender = std::make_unique<FlashMQTestClient>(); | ||
| 1513 | + sender->start(); | ||
| 1514 | + std::shared_ptr<WillPublish> will = std::make_shared<WillPublish>(); | ||
| 1515 | + will->topic = "my/will/testMqtt5DelayedWill"; | ||
| 1516 | + will->payload = "mypayload"; | ||
| 1517 | + will->constructPropertyBuilder(); | ||
| 1518 | + will->propertyBuilder->writeWillDelay(2); | ||
| 1519 | + sender->setWill(will); | ||
| 1520 | + sender->connectClient(ProtocolVersion::Mqtt5, true, 60); | ||
| 1521 | + | ||
| 1522 | + FlashMQTestClient receiver; | ||
| 1523 | + receiver.start(); | ||
| 1524 | + receiver.connectClient(ProtocolVersion::Mqtt5, true, 60); | ||
| 1525 | + receiver.subscribe("my/will/testMqtt5DelayedWill", 0); | ||
| 1526 | + | ||
| 1527 | + receiver.clearReceivedLists(); | ||
| 1528 | + | ||
| 1529 | + sender.reset(); | ||
| 1530 | + | ||
| 1531 | + usleep(250000); | ||
| 1532 | + QVERIFY(receiver.receivedPackets.empty()); | ||
| 1533 | + | ||
| 1534 | + receiver.waitForMessageCount(1, 3); | ||
| 1535 | + | ||
| 1536 | + MqttPacket pubPack = receiver.receivedPublishes.front(); | ||
| 1537 | + pubPack.parsePublishData(); | ||
| 1538 | + | ||
| 1539 | + QCOMPARE(pubPack.getPublishData().topic, "my/will/testMqtt5DelayedWill"); | ||
| 1540 | + QCOMPARE(pubPack.getPublishData().payload, "mypayload"); | ||
| 1541 | + QCOMPARE(pubPack.getPublishData().qos, 0); | ||
| 1542 | +} | ||
| 1543 | + | ||
| 1544 | +void MainTests::testMqtt5DelayedWillAlwaysOnSessionEnd() | ||
| 1545 | +{ | ||
| 1546 | + std::unique_ptr<FlashMQTestClient> sender = std::make_unique<FlashMQTestClient>(); | ||
| 1547 | + sender->start(); | ||
| 1548 | + std::shared_ptr<WillPublish> will = std::make_shared<WillPublish>(); | ||
| 1549 | + will->topic = "my/will/testMqtt5DelayedWillAlwaysOnSessionEnd"; | ||
| 1550 | + will->payload = "mypayload"; | ||
| 1551 | + will->constructPropertyBuilder(); | ||
| 1552 | + will->propertyBuilder->writeWillDelay(120); // This long delay should not matter, because the session expires after 2s. | ||
| 1553 | + sender->setWill(will); | ||
| 1554 | + sender->connectClient(ProtocolVersion::Mqtt5, true, 2); | ||
| 1555 | + | ||
| 1556 | + FlashMQTestClient receiver; | ||
| 1557 | + receiver.start(); | ||
| 1558 | + receiver.connectClient(ProtocolVersion::Mqtt5, true, 60); | ||
| 1559 | + receiver.subscribe("my/will/testMqtt5DelayedWillAlwaysOnSessionEnd", 0); | ||
| 1560 | + | ||
| 1561 | + receiver.clearReceivedLists(); | ||
| 1562 | + | ||
| 1563 | + sender.reset(); | ||
| 1564 | + | ||
| 1565 | + usleep(1000000); | ||
| 1566 | + QVERIFY(receiver.receivedPackets.empty()); | ||
| 1567 | + | ||
| 1568 | + receiver.waitForMessageCount(1, 2); | ||
| 1569 | + | ||
| 1570 | + MqttPacket pubPack = receiver.receivedPublishes.front(); | ||
| 1571 | + pubPack.parsePublishData(); | ||
| 1572 | + | ||
| 1573 | + QCOMPARE(pubPack.getPublishData().topic, "my/will/testMqtt5DelayedWillAlwaysOnSessionEnd"); | ||
| 1574 | + QCOMPARE(pubPack.getPublishData().payload, "mypayload"); | ||
| 1575 | + QCOMPARE(pubPack.getPublishData().qos, 0); | ||
| 1576 | +} | ||
| 1577 | + | ||
| 1427 | 1578 | ||
| 1428 | int main(int argc, char *argv[]) | 1579 | int main(int argc, char *argv[]) |
| 1429 | { | 1580 | { |
flashmqtestclient.cpp
| @@ -32,10 +32,12 @@ FlashMQTestClient::~FlashMQTestClient() | @@ -32,10 +32,12 @@ FlashMQTestClient::~FlashMQTestClient() | ||
| 32 | waitForQuit(); | 32 | waitForQuit(); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | -void FlashMQTestClient::waitForCondition(std::function<bool()> f) | 35 | +void FlashMQTestClient::waitForCondition(std::function<bool()> f, int timeout) |
| 36 | { | 36 | { |
| 37 | + const int loopCount = (timeout * 1000) / 10; | ||
| 38 | + | ||
| 37 | int n = 0; | 39 | int n = 0; |
| 38 | - while(n++ < 100) | 40 | + while(n++ < loopCount) |
| 39 | { | 41 | { |
| 40 | usleep(10000); | 42 | usleep(10000); |
| 41 | 43 | ||
| @@ -60,6 +62,18 @@ void FlashMQTestClient::clearReceivedLists() | @@ -60,6 +62,18 @@ void FlashMQTestClient::clearReceivedLists() | ||
| 60 | receivedPublishes.clear(); | 62 | receivedPublishes.clear(); |
| 61 | } | 63 | } |
| 62 | 64 | ||
| 65 | +void FlashMQTestClient::setWill(std::shared_ptr<WillPublish> &will) | ||
| 66 | +{ | ||
| 67 | + this->will = will; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +void FlashMQTestClient::disconnect(ReasonCodes reason) | ||
| 71 | +{ | ||
| 72 | + client->setReadyForDisconnect(); | ||
| 73 | + Disconnect d(this->client->getProtocolVersion(), reason); | ||
| 74 | + client->writeMqttPacket(d); | ||
| 75 | +} | ||
| 76 | + | ||
| 63 | void FlashMQTestClient::start() | 77 | void FlashMQTestClient::start() |
| 64 | { | 78 | { |
| 65 | testServerWorkerThreadData->start(&do_thread_work); | 79 | testServerWorkerThreadData->start(&do_thread_work); |
| @@ -67,6 +81,11 @@ void FlashMQTestClient::start() | @@ -67,6 +81,11 @@ void FlashMQTestClient::start() | ||
| 67 | 81 | ||
| 68 | void FlashMQTestClient::connectClient(ProtocolVersion protocolVersion) | 82 | void FlashMQTestClient::connectClient(ProtocolVersion protocolVersion) |
| 69 | { | 83 | { |
| 84 | + connectClient(protocolVersion, true, 0); | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +void FlashMQTestClient::connectClient(ProtocolVersion protocolVersion, bool clean_start, uint32_t session_expiry_interval) | ||
| 88 | +{ | ||
| 70 | int sockfd = check<std::runtime_error>(socket(AF_INET, SOCK_STREAM, 0)); | 89 | int sockfd = check<std::runtime_error>(socket(AF_INET, SOCK_STREAM, 0)); |
| 71 | 90 | ||
| 72 | struct sockaddr_in servaddr; | 91 | struct sockaddr_in servaddr; |
| @@ -131,6 +150,10 @@ void FlashMQTestClient::connectClient(ProtocolVersion protocolVersion) | @@ -131,6 +150,10 @@ void FlashMQTestClient::connectClient(ProtocolVersion protocolVersion) | ||
| 131 | }; | 150 | }; |
| 132 | 151 | ||
| 133 | Connect connect(protocolVersion, client->getClientId()); | 152 | Connect connect(protocolVersion, client->getClientId()); |
| 153 | + connect.will = this->will; | ||
| 154 | + connect.clean_start = clean_start; | ||
| 155 | + connect.constructPropertyBuilder(); | ||
| 156 | + connect.propertyBuilder->writeSessionExpiry(session_expiry_interval); | ||
| 134 | MqttPacket connectPack(connect); | 157 | MqttPacket connectPack(connect); |
| 135 | this->client->writeMqttPacketAndBlameThisClient(connectPack); | 158 | this->client->writeMqttPacketAndBlameThisClient(connectPack); |
| 136 | 159 | ||
| @@ -227,9 +250,9 @@ void FlashMQTestClient::waitForConnack() | @@ -227,9 +250,9 @@ void FlashMQTestClient::waitForConnack() | ||
| 227 | }); | 250 | }); |
| 228 | } | 251 | } |
| 229 | 252 | ||
| 230 | -void FlashMQTestClient::waitForMessageCount(const size_t count) | 253 | +void FlashMQTestClient::waitForMessageCount(const size_t count, int timeout) |
| 231 | { | 254 | { |
| 232 | waitForCondition([&]() { | 255 | waitForCondition([&]() { |
| 233 | return this->receivedPublishes.size() >= count; | 256 | return this->receivedPublishes.size() >= count; |
| 234 | - }); | 257 | + }, timeout); |
| 235 | } | 258 | } |
flashmqtestclient.h
| @@ -14,6 +14,7 @@ class FlashMQTestClient | @@ -14,6 +14,7 @@ class FlashMQTestClient | ||
| 14 | std::shared_ptr<Settings> settings; | 14 | std::shared_ptr<Settings> settings; |
| 15 | std::shared_ptr<ThreadData> testServerWorkerThreadData; | 15 | std::shared_ptr<ThreadData> testServerWorkerThreadData; |
| 16 | std::shared_ptr<Client> client; | 16 | std::shared_ptr<Client> client; |
| 17 | + std::shared_ptr<WillPublish> will; | ||
| 17 | 18 | ||
| 18 | std::shared_ptr<ThreadData> dummyThreadData; | 19 | std::shared_ptr<ThreadData> dummyThreadData; |
| 19 | 20 | ||
| @@ -21,7 +22,7 @@ class FlashMQTestClient | @@ -21,7 +22,7 @@ class FlashMQTestClient | ||
| 21 | 22 | ||
| 22 | static int clientCount; | 23 | static int clientCount; |
| 23 | 24 | ||
| 24 | - void waitForCondition(std::function<bool()> f); | 25 | + void waitForCondition(std::function<bool()> f, int timeout = 1); |
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | public: | 28 | public: |
| @@ -33,13 +34,16 @@ public: | @@ -33,13 +34,16 @@ public: | ||
| 33 | 34 | ||
| 34 | void start(); | 35 | void start(); |
| 35 | void connectClient(ProtocolVersion protocolVersion); | 36 | void connectClient(ProtocolVersion protocolVersion); |
| 37 | + void connectClient(ProtocolVersion protocolVersion, bool clean_start, uint32_t session_expiry_interval); | ||
| 36 | void subscribe(const std::string topic, char qos); | 38 | void subscribe(const std::string topic, char qos); |
| 37 | void publish(const std::string &topic, const std::string &payload, char qos); | 39 | void publish(const std::string &topic, const std::string &payload, char qos); |
| 38 | void clearReceivedLists(); | 40 | void clearReceivedLists(); |
| 41 | + void setWill(std::shared_ptr<WillPublish> &will); | ||
| 42 | + void disconnect(ReasonCodes reason); | ||
| 39 | 43 | ||
| 40 | void waitForQuit(); | 44 | void waitForQuit(); |
| 41 | void waitForConnack(); | 45 | void waitForConnack(); |
| 42 | - void waitForMessageCount(const size_t count); | 46 | + void waitForMessageCount(const size_t count, int timeout = 1); |
| 43 | }; | 47 | }; |
| 44 | 48 | ||
| 45 | #endif // FLASHMQTESTCLIENT_H | 49 | #endif // FLASHMQTESTCLIENT_H |
mainapp.cpp
| @@ -65,7 +65,11 @@ MainApp::MainApp(const std::string &configFilePath) : | @@ -65,7 +65,11 @@ MainApp::MainApp(const std::string &configFilePath) : | ||
| 65 | auto f = std::bind(&MainApp::queueCleanup, this); | 65 | auto f = std::bind(&MainApp::queueCleanup, this); |
| 66 | //const uint64_t derrivedSessionCheckInterval = std::max<uint64_t>((settings->expireSessionsAfterSeconds)*1000*2, 600000); | 66 | //const uint64_t derrivedSessionCheckInterval = std::max<uint64_t>((settings->expireSessionsAfterSeconds)*1000*2, 600000); |
| 67 | //const uint64_t sessionCheckInterval = std::min<uint64_t>(derrivedSessionCheckInterval, 86400000); | 67 | //const uint64_t sessionCheckInterval = std::min<uint64_t>(derrivedSessionCheckInterval, 86400000); |
| 68 | - timer.addCallback(f, 10000, "session expiration"); | 68 | + uint64_t interval = 10000; |
| 69 | +#ifdef TESTING | ||
| 70 | + interval = 1000; | ||
| 71 | +#endif | ||
| 72 | + timer.addCallback(f, interval, "session expiration"); | ||
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | auto fKeepAlive = std::bind(&MainApp::queueKeepAliveCheckAtAllThreads, this); | 75 | auto fKeepAlive = std::bind(&MainApp::queueKeepAliveCheckAtAllThreads, this); |
mqtt5properties.cpp
| @@ -145,6 +145,11 @@ void Mqtt5PropertyBuilder::writeAuthenticationData(const std::string &data) | @@ -145,6 +145,11 @@ void Mqtt5PropertyBuilder::writeAuthenticationData(const std::string &data) | ||
| 145 | writeStr(Mqtt5Properties::AuthenticationData, data); | 145 | writeStr(Mqtt5Properties::AuthenticationData, data); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | +void Mqtt5PropertyBuilder::writeWillDelay(uint32_t delay) | ||
| 149 | +{ | ||
| 150 | + writeUint32(Mqtt5Properties::WillDelayInterval, delay, genericBytes); | ||
| 151 | +} | ||
| 152 | + | ||
| 148 | void Mqtt5PropertyBuilder::setNewUserProperties(const std::shared_ptr<std::vector<std::pair<std::string, std::string>>> &userProperties) | 153 | void Mqtt5PropertyBuilder::setNewUserProperties(const std::shared_ptr<std::vector<std::pair<std::string, std::string>>> &userProperties) |
| 149 | { | 154 | { |
| 150 | assert(!this->userProperties); | 155 | assert(!this->userProperties); |
mqtt5properties.h
| @@ -48,6 +48,7 @@ public: | @@ -48,6 +48,7 @@ public: | ||
| 48 | void writeTopicAlias(const uint16_t id); | 48 | void writeTopicAlias(const uint16_t id); |
| 49 | void writeAuthenticationMethod(const std::string &method); | 49 | void writeAuthenticationMethod(const std::string &method); |
| 50 | void writeAuthenticationData(const std::string &data); | 50 | void writeAuthenticationData(const std::string &data); |
| 51 | + void writeWillDelay(uint32_t delay); | ||
| 51 | void setNewUserProperties(const std::shared_ptr<std::vector<std::pair<std::string, std::string>>> &userProperties); | 52 | void setNewUserProperties(const std::shared_ptr<std::vector<std::pair<std::string, std::string>>> &userProperties); |
| 52 | }; | 53 | }; |
| 53 | 54 |
mqttpacket.cpp
| @@ -204,16 +204,25 @@ MqttPacket::MqttPacket(const PubResponse &pubAck) : | @@ -204,16 +204,25 @@ MqttPacket::MqttPacket(const PubResponse &pubAck) : | ||
| 204 | } | 204 | } |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | +/** | ||
| 208 | + * @brief Constructor to create a disconnect packet. In normal server mode, only MQTT5 is supposed to do that (MQTT3 has no concept of server-initiated | ||
| 209 | + * disconnect packet). But, we also use it in the test client. | ||
| 210 | + * @param disconnect | ||
| 211 | + */ | ||
| 207 | MqttPacket::MqttPacket(const Disconnect &disconnect) : | 212 | MqttPacket::MqttPacket(const Disconnect &disconnect) : |
| 208 | bites(disconnect.getLengthWithoutFixedHeader()) | 213 | bites(disconnect.getLengthWithoutFixedHeader()) |
| 209 | { | 214 | { |
| 210 | - this->protocolVersion = ProtocolVersion::Mqtt5; | 215 | + this->protocolVersion = disconnect.protocolVersion; |
| 211 | 216 | ||
| 212 | packetType = PacketType::DISCONNECT; | 217 | packetType = PacketType::DISCONNECT; |
| 213 | first_byte = static_cast<char>(packetType) << 4; | 218 | first_byte = static_cast<char>(packetType) << 4; |
| 214 | 219 | ||
| 215 | - writeByte(static_cast<uint8_t>(disconnect.reasonCode)); | ||
| 216 | - writeProperties(disconnect.propertyBuilder); | 220 | + if (this->protocolVersion >= ProtocolVersion::Mqtt5) |
| 221 | + { | ||
| 222 | + writeByte(static_cast<uint8_t>(disconnect.reasonCode)); | ||
| 223 | + writeProperties(disconnect.propertyBuilder); | ||
| 224 | + } | ||
| 225 | + | ||
| 217 | calculateRemainingLength(); | 226 | calculateRemainingLength(); |
| 218 | } | 227 | } |
| 219 | 228 | ||
| @@ -244,7 +253,17 @@ MqttPacket::MqttPacket(const Connect &connect) : | @@ -244,7 +253,17 @@ MqttPacket::MqttPacket(const Connect &connect) : | ||
| 244 | writeString(magicString); | 253 | writeString(magicString); |
| 245 | 254 | ||
| 246 | writeByte(static_cast<char>(protocolVersion)); | 255 | writeByte(static_cast<char>(protocolVersion)); |
| 247 | - writeByte(2); // flags; The only bit set is 'clean session'. | 256 | + |
| 257 | + uint8_t flags = connect.clean_start << 1; | ||
| 258 | + | ||
| 259 | + if (connect.will) | ||
| 260 | + { | ||
| 261 | + flags |= 4; | ||
| 262 | + flags |= (connect.will->qos << 3); | ||
| 263 | + flags |= (connect.will->retain << 5); | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + writeByte(flags); | ||
| 248 | 267 | ||
| 249 | // Keep-alive | 268 | // Keep-alive |
| 250 | writeUint16(60); | 269 | writeUint16(60); |
| @@ -256,6 +275,17 @@ MqttPacket::MqttPacket(const Connect &connect) : | @@ -256,6 +275,17 @@ MqttPacket::MqttPacket(const Connect &connect) : | ||
| 256 | 275 | ||
| 257 | writeString(connect.clientid); | 276 | writeString(connect.clientid); |
| 258 | 277 | ||
| 278 | + if (connect.will) | ||
| 279 | + { | ||
| 280 | + if (connect.protocolVersion >= ProtocolVersion::Mqtt5) | ||
| 281 | + { | ||
| 282 | + writeProperties(connect.will->propertyBuilder); | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + writeString(connect.will->topic); | ||
| 286 | + writeString(connect.will->payload); | ||
| 287 | + } | ||
| 288 | + | ||
| 259 | calculateRemainingLength(); | 289 | calculateRemainingLength(); |
| 260 | } | 290 | } |
| 261 | 291 |
types.cpp
| @@ -312,15 +312,17 @@ size_t UnsubAck::getLengthWithoutFixedHeader() const | @@ -312,15 +312,17 @@ size_t UnsubAck::getLengthWithoutFixedHeader() const | ||
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | Disconnect::Disconnect(const ProtocolVersion protVersion, ReasonCodes reason_code) : | 314 | Disconnect::Disconnect(const ProtocolVersion protVersion, ReasonCodes reason_code) : |
| 315 | + protocolVersion(protVersion), | ||
| 315 | reasonCode(reason_code) | 316 | reasonCode(reason_code) |
| 316 | { | 317 | { |
| 317 | - assert(protVersion >= ProtocolVersion::Mqtt5); | ||
| 318 | - | ||
| 319 | 318 | ||
| 320 | } | 319 | } |
| 321 | 320 | ||
| 322 | size_t Disconnect::getLengthWithoutFixedHeader() const | 321 | size_t Disconnect::getLengthWithoutFixedHeader() const |
| 323 | { | 322 | { |
| 323 | + if (this->protocolVersion < ProtocolVersion::Mqtt5) | ||
| 324 | + return 0; | ||
| 325 | + | ||
| 324 | size_t result = 1; | 326 | size_t result = 1; |
| 325 | const size_t proplen = propertyBuilder ? propertyBuilder->getLength() : 1; | 327 | const size_t proplen = propertyBuilder ? propertyBuilder->getLength() : 1; |
| 326 | result += proplen; | 328 | result += proplen; |
| @@ -364,8 +366,20 @@ size_t Connect::getLengthWithoutFixedHeader() const | @@ -364,8 +366,20 @@ size_t Connect::getLengthWithoutFixedHeader() const | ||
| 364 | const size_t proplen = propertyBuilder ? propertyBuilder->getLength() : 1; | 366 | const size_t proplen = propertyBuilder ? propertyBuilder->getLength() : 1; |
| 365 | result += proplen; | 367 | result += proplen; |
| 366 | } | 368 | } |
| 367 | - return result; | ||
| 368 | 369 | ||
| 370 | + if (will) | ||
| 371 | + { | ||
| 372 | + if (this->protocolVersion >= ProtocolVersion::Mqtt5) | ||
| 373 | + { | ||
| 374 | + const size_t proplen = will->propertyBuilder ? will->propertyBuilder->getLength() : 1; | ||
| 375 | + result += proplen; | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + result += will->topic.length() + 2; | ||
| 379 | + result += will->payload.length() + 2; | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + return result; | ||
| 369 | } | 383 | } |
| 370 | 384 | ||
| 371 | std::string Connect::getMagicString() const | 385 | std::string Connect::getMagicString() const |
| @@ -376,6 +390,14 @@ std::string Connect::getMagicString() const | @@ -376,6 +390,14 @@ std::string Connect::getMagicString() const | ||
| 376 | return "MQTT"; | 390 | return "MQTT"; |
| 377 | } | 391 | } |
| 378 | 392 | ||
| 393 | +void Connect::constructPropertyBuilder() | ||
| 394 | +{ | ||
| 395 | + if (this->propertyBuilder) | ||
| 396 | + return; | ||
| 397 | + | ||
| 398 | + this->propertyBuilder = std::make_shared<Mqtt5PropertyBuilder>(); | ||
| 399 | +} | ||
| 400 | + | ||
| 379 | Subscribe::Subscribe(const ProtocolVersion protocolVersion, uint16_t packetId, const std::string &topic, char qos) : | 401 | Subscribe::Subscribe(const ProtocolVersion protocolVersion, uint16_t packetId, const std::string &topic, char qos) : |
| 380 | protocolVersion(protocolVersion), | 402 | protocolVersion(protocolVersion), |
| 381 | packetId(packetId), | 403 | packetId(packetId), |
types.h
| @@ -262,6 +262,7 @@ public: | @@ -262,6 +262,7 @@ public: | ||
| 262 | class Disconnect | 262 | class Disconnect |
| 263 | { | 263 | { |
| 264 | public: | 264 | public: |
| 265 | + ProtocolVersion protocolVersion; | ||
| 265 | ReasonCodes reasonCode; | 266 | ReasonCodes reasonCode; |
| 266 | std::shared_ptr<Mqtt5PropertyBuilder> propertyBuilder; | 267 | std::shared_ptr<Mqtt5PropertyBuilder> propertyBuilder; |
| 267 | Disconnect(const ProtocolVersion protVersion, ReasonCodes reason_code); | 268 | Disconnect(const ProtocolVersion protVersion, ReasonCodes reason_code); |
| @@ -280,14 +281,17 @@ public: | @@ -280,14 +281,17 @@ public: | ||
| 280 | struct Connect | 281 | struct Connect |
| 281 | { | 282 | { |
| 282 | const ProtocolVersion protocolVersion; | 283 | const ProtocolVersion protocolVersion; |
| 284 | + bool clean_start = true; | ||
| 283 | std::string clientid; | 285 | std::string clientid; |
| 284 | std::string username; | 286 | std::string username; |
| 285 | std::string password; | 287 | std::string password; |
| 288 | + std::shared_ptr<WillPublish> will; | ||
| 286 | std::shared_ptr<Mqtt5PropertyBuilder> propertyBuilder; | 289 | std::shared_ptr<Mqtt5PropertyBuilder> propertyBuilder; |
| 287 | 290 | ||
| 288 | Connect(ProtocolVersion protocolVersion, const std::string &clientid); | 291 | Connect(ProtocolVersion protocolVersion, const std::string &clientid); |
| 289 | size_t getLengthWithoutFixedHeader() const; | 292 | size_t getLengthWithoutFixedHeader() const; |
| 290 | std::string getMagicString() const; | 293 | std::string getMagicString() const; |
| 294 | + void constructPropertyBuilder(); | ||
| 291 | }; | 295 | }; |
| 292 | 296 | ||
| 293 | /** | 297 | /** |