MQTTSuite
Loading...
Searching...
No Matches
BridgeStore.cpp
Go to the documentation of this file.
1/*
2 * MQTTSuite - A lightweight MQTT Integration System
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2022, 2023, 2024, 2025
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42#include "BridgeStore.h"
43
44#ifndef DOXYGEN_SHOULD_SKIP_THIS
45
46#include "nlohmann/json-schema.hpp"
47
48#include <cmath>
49#include <exception>
50#include <fstream>
51#include <list>
52#include <log/Logger.h>
53#include <map>
54#include <nlohmann/json.hpp>
55#include <utility>
56
57// IWYU pragma: no_include <nlohmann/json_fwd.hpp>
58// IWYU pragma: no_include <nlohmann/detail/iterators/iter_impl.hpp>
59
60#endif // DOXYGEN_SHOULD_SKIP_THIS
61
62namespace mqtt::bridge::lib {
63
65 static BridgeStore bridgeConfigLoader;
66
67 return bridgeConfigLoader;
68 }
69
70 bool BridgeStore::loadAndValidate(const std::string& fileName) {
71 bool success = !brokers.empty();
72
73#include "bridge-schema.json.h" // IWYU pragma: keep
74
75 if (!success) {
76 try {
77 const nlohmann::json bridgeJsonSchema = nlohmann::json::parse(bridgeJsonSchemaString);
78
79 if (!fileName.empty()) {
80 std::ifstream bridgeConfigJsonFile(fileName);
81
82 if (bridgeConfigJsonFile.is_open()) {
83 VLOG(1) << "Bridge config JSON: " << fileName;
84
85 try {
86 nlohmann::json bridgesConfigJson;
87
88 bridgeConfigJsonFile >> bridgesConfigJson;
89
90 try {
91 const nlohmann::json_schema::json_validator validator(bridgeJsonSchema);
92
93 try {
94 const nlohmann::json defaultPatch = validator.validate(bridgesConfigJson);
95
96 try {
97 bridgesConfigJson = bridgesConfigJson.patch(defaultPatch);
98
99 for (const nlohmann::json& bridgeConfigJson : bridgesConfigJson["bridges"]) {
100 Bridge& bridge = bridgeList.emplace_back(
101 bridgeConfigJson["name"], bridgeConfigJson["prefix"], bridgeConfigJson["disabled"]);
102
103 for (const nlohmann::json& brokerConfigJson : bridgeConfigJson["brokers"]) {
104 std::list<iot::mqtt::Topic> topics;
105 for (const nlohmann::json& topicJson : brokerConfigJson["topics"]) {
106 if (!topicJson["topic"].get<std::string>().empty()) {
107 topics.emplace_back(topicJson["topic"], // cppcheck-suppress useStlAlgorithm
108 topicJson["qos"]);
109 }
110 }
111
112 const nlohmann::json& mqtt = brokerConfigJson["mqtt"];
113 const nlohmann::json& network = brokerConfigJson["network"];
114
115 const std::string fullInstanceName =
116 bridge.getName() + "+" + network["instance_name"].get<std::string>();
117
118 brokers.emplace(fullInstanceName,
119 Broker(bridge,
120 brokerConfigJson["session_store"],
121 fullInstanceName,
122 network["protocol"],
123 network["encryption"],
124 network["transport"],
125 network[network["protocol"]],
126 mqtt["client_id"],
127 mqtt["keep_alive"],
128 mqtt["clean_session"],
129 mqtt["will_topic"],
130 mqtt["will_message"],
131 mqtt["will_qos"],
132 mqtt["will_retain"],
133 mqtt["username"],
134 mqtt["password"],
135 mqtt["loop_prevention"],
136 brokerConfigJson["prefix"],
137 brokerConfigJson["disabled"],
138 topics));
139 }
140 }
141
142 success = true;
143 } catch (const std::exception& e) {
144 VLOG(1) << " Patching JSON with default patch failed:\n" << defaultPatch.dump(4);
145 VLOG(1) << " " << e.what();
146 }
147 } catch (const std::exception& e) {
148 VLOG(1) << " Validating JSON failed:\n" << bridgesConfigJson.dump(4);
149 VLOG(1) << " " << e.what();
150 }
151 } catch (const std::exception& e) {
152 VLOG(1) << " Setting root json mapping schema failed:\n" << bridgeJsonSchema.dump(4);
153 VLOG(1) << " " << e.what();
154 }
155 } catch (const std::exception& e) {
156 VLOG(1) << " JSON map file parsing failed:" << e.what() << " at " << bridgeConfigJsonFile.tellg();
157 }
158
159 bridgeConfigJsonFile.close();
160 } else {
161 VLOG(1) << "BridgeJsonConfig: " << fileName << " not found";
162 }
163 } else {
164 // Do not log missing path. In regular use this missing option is captured by the command line interface
165 }
166 } catch (const std::exception& e) {
167 VLOG(1) << "Parsing schema failed: " << e.what();
168 VLOG(1) << bridgeJsonSchemaString;
169 }
170 } else {
171 VLOG(1) << "MappingFile already loaded and validated";
172 }
173
174 return success;
175 }
176
177 const Broker& BridgeStore::getBroker(const std::string& instanceName) {
178 return brokers.find(instanceName)->second;
179 }
180
182 return brokers;
183 }
184
185} // namespace mqtt::bridge::lib
std::map< std::string, Broker > brokers
Definition BridgeStore.h:72
static BridgeStore & instance()
const std::map< std::string, Broker > & getBrokers()
json_validator(const json &, schema_loader=nullptr, format_checker=nullptr, content_checker=nullptr)