Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
secondary_config.cc
1 #include <fstream>
2 #include <iostream>
3 #include <unordered_map>
4 
5 #include <json/json.h>
6 
7 #include "logging/logging.h"
8 #include "secondary_config.h"
9 #include "utilities/utils.h"
10 
11 namespace Primary {
12 
13 const char* const IPSecondariesConfig::Type = "IP";
14 
15 SecondaryConfigParser::Configs SecondaryConfigParser::parse_config_file(const boost::filesystem::path& config_file) {
16  if (!boost::filesystem::exists(config_file)) {
17  throw std::invalid_argument("Specified config file doesn't exist: " + config_file.string());
18  }
19 
20  auto cfg_file_ext = boost::filesystem::extension(config_file);
21  std::unique_ptr<SecondaryConfigParser> cfg_parser;
22 
23  if (cfg_file_ext == ".json") {
24  cfg_parser = std_::make_unique<JsonConfigParser>(config_file);
25  } else { // add your format of configuration file + implement SecondaryConfigParser specialization
26  throw std::invalid_argument("Unsupported type of config format: " + cfg_file_ext);
27  }
28 
29  return cfg_parser->parse();
30 }
31 
32 /*
33 config file example
34 
35 {
36  "IP": {
37  "secondaries_wait_port": 9040,
38  "secondaries_wait_timeout": 20,
39  "secondaries": [
40  {"addr": "127.0.0.1:9031"}
41  {"addr": "127.0.0.1:9032"}
42  ]
43  },
44  "socketcan": {
45  "common-key": "common-value",
46  "secondaries": [
47  {"key": "value", "key1": "value1"},
48  {"key": "value", "key1": "value1"}
49  ]
50  }
51 }
52 
53 
54 */
55 
56 JsonConfigParser::JsonConfigParser(const boost::filesystem::path& config_file) {
57  assert(boost::filesystem::exists(config_file));
58  std::ifstream json_file_stream(config_file.string());
59  std::string errs;
60 
61  if (!Json::parseFromStream(Json::CharReaderBuilder(), json_file_stream, &root_, &errs)) {
62  throw std::invalid_argument("Failed to parse secondary config file: " + config_file.string() + ": " + errs);
63  }
64 }
65 
66 SecondaryConfigParser::Configs JsonConfigParser::parse() {
67  Configs res_sec_cfg;
68 
69  for (auto it = root_.begin(); it != root_.end(); ++it) {
70  std::string secondary_type = it.key().asString();
71 
72  if (sec_cfg_factory_registry_.find(secondary_type) == sec_cfg_factory_registry_.end()) {
73  LOG_ERROR << "Unsupported type of sescondary config was found: `" << secondary_type
74  << "`. Ignoring it and continuing with parsing of other secondary configs";
75  } else {
76  (sec_cfg_factory_registry_.at(secondary_type))(res_sec_cfg, *it);
77  }
78  }
79 
80  return res_sec_cfg;
81 }
82 
83 static std::pair<std::string, uint16_t> getIPAndPort(const std::string& addr) {
84  auto del_pos = addr.find_first_of(':');
85  if (del_pos == std::string::npos) {
86  throw std::invalid_argument("Incorrect address string, couldn't find port delimeter: " + addr);
87  }
88  std::string ip = addr.substr(0, del_pos);
89  uint16_t port = static_cast<uint16_t>(std::stoul(addr.substr(del_pos + 1)));
90 
91  return std::make_pair(ip, port);
92 }
93 
94 void JsonConfigParser::createIPSecondariesCfg(Configs& configs, const Json::Value& json_ip_sec_cfg) {
95  auto resultant_cfg = std::make_shared<IPSecondariesConfig>(
96  static_cast<uint16_t>(json_ip_sec_cfg[IPSecondariesConfig::PortField].asUInt()),
97  json_ip_sec_cfg[IPSecondariesConfig::TimeoutField].asInt());
98  auto secondaries = json_ip_sec_cfg[IPSecondariesConfig::SecondariesField];
99 
100  LOG_INFO << "Found IP secondaries config: " << *resultant_cfg;
101 
102  for (const auto& secondary : secondaries) {
103  auto addr = getIPAndPort(secondary[IPSecondaryConfig::AddrField].asString());
104  IPSecondaryConfig sec_cfg{addr.first, addr.second};
105 
106  LOG_INFO << " found IP secondary config: " << sec_cfg;
107  resultant_cfg->secondaries_cfg.push_back(sec_cfg);
108  }
109 
110  configs.push_back(resultant_cfg);
111 }
112 
113 void JsonConfigParser::createVirtualSecondariesCfg(Configs& configs, const Json::Value& json_virtual_sec_cfg) {
114  for (const auto& json_config : json_virtual_sec_cfg) {
115  auto virtual_config = std::make_shared<VirtualSecondaryConfig>(json_config);
116  configs.push_back(virtual_config);
117  }
118 }
119 
120 } // namespace Primary