2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20#include "iot/mqtt/server/broker/Broker.h"
22#ifndef DOXYGEN_SHOULD_SKIP_THIS
24#include "log/Logger.h"
30#include <nlohmann/json.hpp>
44 if (!sessionStoreFileName.empty()) {
45 std::ifstream sessionStoreFile(sessionStoreFileName);
47 if (sessionStoreFile.is_open()) {
49 nlohmann::json sessionStoreJson;
51 sessionStoreFile >> sessionStoreJson;
53 for (
const auto& [clientId, sessionJson] : sessionStoreJson[
"session_store"].items()) {
54 sessionStore[clientId].fromJson(sessionJson);
56 retainTree.fromJson(sessionStoreJson[
"retain_tree"]);
57 subscribtionTree.fromJson(sessionStoreJson[
"subscribtion_tree"]);
59 LOG(INFO) <<
"MQTT Broker: Persistent session data loaded successful";
60 }
catch (
const nlohmann::json::exception&) {
61 LOG(INFO) <<
"MQTT Broker: Starting with empty session: Session store '" << sessionStoreFileName
62 <<
"' empty or corrupted";
66 subscribtionTree.clear();
69 sessionStoreFile.close();
70 std::remove(sessionStoreFileName.data());
72 LOG(INFO) <<
"MQTT Broker: Restoring saved session done";
74 PLOG(WARNING) <<
"MQTT Broker: Could not read session store '" << sessionStoreFileName <<
"'";
77 LOG(INFO) <<
"MQTT Broker: Session not reloaded: Session store filename empty";
82 if (!sessionStoreFileName.empty()) {
83 nlohmann::json sessionStoreJson;
85 for (
auto& [clientId, session] : sessionStore) {
86 sessionStoreJson[
"session_store"][clientId] = session.toJson();
88 sessionStoreJson[
"retain_tree"] = retainTree.toJson();
89 sessionStoreJson[
"subscribtion_tree"] = subscribtionTree.toJson();
91 if (sessionStoreJson[
"session_store"].empty()) {
92 sessionStoreJson.erase(
"session_store");
94 if (sessionStoreJson[
"retain_tree"].empty()) {
95 sessionStoreJson.erase(
"retain_tree");
97 if (sessionStoreJson[
"subscribtion_tree"].empty()) {
98 sessionStoreJson.erase(
"subscribtion_tree");
101 std::ofstream sessionStoreFile(sessionStoreFileName);
103 if (sessionStoreFile.is_open()) {
104 if (!sessionStoreJson.empty()) {
105 sessionStoreFile << sessionStoreJson;
108 sessionStoreFile.close();
110 LOG(INFO) <<
"MQTT Broker: Session store written '" << sessionStoreFileName <<
"'";
112 PLOG(ERROR) <<
"MQTT Broker: Could not write session store '" << sessionStoreFileName <<
"'";
115 LOG(INFO) <<
"MQTT Broker: Session not saved: Session store filename empty";
120 static const std::shared_ptr<
Broker> broker = std::make_shared<Broker>(maxQoS);
125 void Broker::
appear(
const std::string& clientId,
const std::string& topic, uint8_t qoS) {
126 retainTree.appear(clientId, topic, qoS);
130 subscribtionTree.unsubscribe(clientId);
134 Broker::
publish(
const std::string& originClientId,
const std::string& topic,
const std::string& message, uint8_t qoS,
bool retain) {
135 subscribtionTree.publish(Message(originClientId, topic, message, qoS, retain));
138 retainTree.retain(Message(originClientId, topic, message, qoS, retain));
142 uint8_t
Broker::
subscribe(
const std::string& clientId,
const std::string& topic, uint8_t qoS) {
143 qoS = std::min(
maxQoS, qoS);
144 uint8_t returnCode = 0;
146 if (subscribtionTree.subscribe(topic, clientId, qoS)) {
147 retainTree.appear(clientId, topic, qoS);
158 subscribtionTree.unsubscribe(topic, clientId);
162 return sessionStore.contains(clientId);
166 return hasSession(clientId) && sessionStore[clientId].isActive();
170 return hasSession(clientId) && !sessionStore[clientId].isActive();
174 return hasSession(clientId) && sessionStore[clientId].isOwnedBy(mqtt);
178 sessionStore[clientId] = iot::mqtt::server::broker::Session(mqtt);
180 return &sessionStore[clientId];
184 return sessionStore[clientId].renew(mqtt);
188 LOG(INFO) <<
"MQTT Broker: Retained: Send PUBLISH: " << clientId;
189 subscribtionTree.appear(clientId);
191 LOG(INFO) <<
"MQTT Broker: Queued: Send PUBLISH: " << clientId;
192 sessionStore[clientId].publishQueued();
196 sessionStore[clientId].retain();
200 subscribtionTree.unsubscribe(clientId);
201 sessionStore.erase(clientId);
205 LOG(INFO) <<
"MQTT Broker: Send PUBLISH: " << clientId;
207 sessionStore[clientId].sendPublish(message, qoS, retain);
#define SUBSCRIBTION_FAILURE
#define SUBSCRIBTION_SUCCESS
void restartSession(const std::string &clientId)
uint8_t subscribe(const std::string &clientId, const std::string &topic, uint8_t qoS)
bool hasActiveSession(const std::string &clientId)
static std::shared_ptr< Broker > instance(uint8_t maxQoS)
bool isActiveSession(const std::string &clientId, const Mqtt *mqtt)
void publish(const std::string &originClientId, const std::string &topic, const std::string &message, uint8_t qoS, bool retain)
bool hasSession(const std::string &clientId)
void appear(const std::string &clientId, const std::string &topic, uint8_t qoS)
void unsubscribe(const std::string &clientId, const std::string &topic)
Session * renewSession(const std::string &clientId, iot::mqtt::server::Mqtt *mqtt)
void deleteSession(const std::string &clientId)
void unsubscribe(const std::string &clientId)
bool hasRetainedSession(const std::string &clientId)
Session * newSession(const std::string &clientId, iot::mqtt::server::Mqtt *mqtt)
void sendPublish(const std::string &clientId, Message &message, uint8_t qoS, bool retain)
void retainSession(const std::string &clientId)