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