versions-db-manager.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2020 Intel Corporation. All Rights Reserved.
3 #include <fstream>
4 #include <unordered_map>
5 #include <algorithm>
6 #include <regex>
7 
8 #include "json.hpp"
9 #include "versions-db-manager.h"
10 #include <types.h>
11 
12 namespace rs2
13 {
14 
15  namespace sw_update
16  {
18  using namespace http;
19 
20  // Get current platform
21  constexpr const char* PLATFORM =
22 
23 #ifdef _WIN64
24  "Windows amd64";
25 #elif _WIN32
26  "Windows x86";
27 #elif __linux__
28 #ifdef __arm__
29  "Linux arm";
30 #else
31  "Linux amd64";
32 #endif
33 #elif __APPLE__
34  "Mac OS";
35 #elif __ANDROID__
36  "Linux arm";
37 #else
38  "";
39 #endif
40 
42  {
43  // Load server versions info on first access
44  if (!init())
45  {
46  out_version = 0;
47  return DB_LOAD_FAILURE;
48  }
49 
50  std::string platform(PLATFORM);
51 
52  std::string up_str(to_string(policy));
53  std::string comp_str(to_string(component));
54 
55  if (up_str.empty() || comp_str.empty()) return NO_VERSION_FOUND;
56 
57  // Look for the required version
58  auto res = std::find_if(_server_versions_vec.begin(), _server_versions_vec.end(),
59  [&, device_name, up_str, comp_str, platform](std::unordered_map<std::string, std::string> ver)
60  {
61  return (is_device_name_equal(ver["device_name"],device_name,true) && up_str == ver["policy_type"] && comp_str == ver["component"] && (platform == ver["platform"] || ver["platform"] == "*"));
62  });
63 
64  if (res != _server_versions_vec.end())
65  {
66  auto version_str = (*res)["version"];
67  out_version = version(version_str);
68  return VERSION_FOUND;
69  }
70 
71  out_version = 0;
72  return NO_VERSION_FOUND; // Nothing found
73  }
74 
76  {
77  // Check if server versions are loaded
78  if (!_server_versions_loaded) return false;
79 
80  std::string platform = PLATFORM;
81 
82  std::string component_str(to_string(component));
83 
84  if (component_str.empty()) return false;
85 
86  // Look for the required version
87  auto res = std::find_if(_server_versions_vec.begin(), _server_versions_vec.end(),
88  [version, component_str, platform](std::unordered_map<std::string, std::string> version_map)
89  {
90  return (sw_update::version(version_map["version"]) == version && component_str == version_map["component"] && (platform == version_map["platform"] || version_map["platform"] == "*"));
91  });
92 
93  if (res != _server_versions_vec.end())
94  {
95  out = (*res)[req_field];
96  return true;
97  }
98 
99  return false; // Nothing found
100  }
101 
102 
104  {
105  switch (component)
106  {
107  case LIBREALSENSE: return "LIBREALSENSE";
108  case VIEWER: return "VIEWER";
109  case DEPTH_QUALITY_TOOL: return "DEPTH_QUALITY_TOOL";
110  case FIRMWARE: return "FIRMWARE";
111  break;
112  default:
113  LOG_ERROR("Unknown component type: " + component);
114  break;
115  }
116  return "";
117  }
118 
120  {
121 
122  switch (policy)
123  {
124  case EXPERIMENTAL: return "EXPERIMENTAL";
125  case RECOMMENDED: return "RECOMMENDED";
126  case ESSENTIAL: return "ESSENTIAL";
127  break;
128  default:
129  LOG_ERROR("Unknown policy type: " + policy);
130  break;
131  }
132  return "";
133  }
134 
135  bool from_string(const std::string &component_str, component_part_type& component_val)
136  {
137  static std::unordered_map<std::string, component_part_type> map =
138  { {"LIBREALSENSE",LIBREALSENSE},
139  {"VIEWER", VIEWER} ,
140  {"DEPTH_QUALITY_TOOL", DEPTH_QUALITY_TOOL},
141  {"FIRMWARE", FIRMWARE} };
142 
143  auto val = map.find(component_str);
144  if (val != map.end())
145  {
146  component_val = val->second;
147  return true;
148  }
149 
150  LOG_ERROR("Unknown component type: " + component_str);
151  return false;
152  }
153  bool from_string(const std::string &policy_str, update_policy_type& policy_val)
154  {
155  static std::unordered_map<std::string, update_policy_type> map =
156  { {"EXPERIMENTAL",EXPERIMENTAL},
157  {"RECOMMENDED", RECOMMENDED} ,
158  {"ESSENTIAL", ESSENTIAL} };
159 
160  auto val = map.find(policy_str);
161  if (val != map.end())
162  {
163  policy_val = val->second;
164  return true;
165  }
166 
167  LOG_ERROR("Unknown policy type: " + policy_str);
168  return false;
169  }
170 
171  bool versions_db_manager::get_server_data(std::stringstream &ver_data)
172  {
173  bool server_data_retrieved(false);
174 
175  if (false == _local_source_file)
176  {
177  // download file from URL
178  http_downloader hd;
179  if (hd.download_to_stream(_dev_info_url, ver_data, _download_cb_func))
180  {
181  server_data_retrieved = true;
182  }
183  }
184 #ifdef CHECK_FOR_UPDATES
185  else
186  {
187  // read from local file
188  std::ifstream file(_dev_info_url);
189  if (file.good())
190  {
191  server_data_retrieved = true;
192  ver_data << file.rdbuf();
193  }
194  else
195  {
196  LOG_ERROR("Cannot open file: " + _dev_info_url);
197  }
198  }
199 #endif
200  return server_data_retrieved;
201  }
202 
203  void versions_db_manager::parse_versions_data(const std::stringstream &ver_data)
204  {
205  // Parse the json file
206  json j(json::parse(ver_data.str()));
207 
208  std::unordered_map<std::string, std::function<bool(const std::string&)>> schema;
209  build_schema(schema);
210 
211  // Validate json file has a versions array
212  if (j.begin().key() == "versions" && j.begin().value().is_array())
213  {
214  // Iterate through the versions
215  for (auto &ver : j["versions"])
216  { // Iterate through the version fields
217  std::unordered_map<std::string, std::string> curr_version;
218  for (auto it = ver.begin(); it != ver.end(); ++it)
219  {
220  std::string element_key(it.key());
221 
222  auto schema_field(schema.find(element_key));
223  if (schema_field != schema.end()) {
224  if (it.value().is_string())
225  {
226  if (schema_field->second(it.value().get<std::string>()))
227  {
228  // Value validation passed - add to current version
229  curr_version[element_key] = it.value().get<std::string>();
230  }
231  else
232  {
233  std::string error_str("Server versions file parsing error - validation fail on key: " + element_key + " value: " + it.value().get<std::string>() + " \n");
234  LOG_ERROR(error_str);
235  throw std::runtime_error(error_str);
236  }
237  }
238  else
239  {
240  std::string error_str("Server versions file parsing error - " + element_key + " should be represented as a string");
241  LOG_ERROR(error_str);
242  throw std::runtime_error(error_str);
243  }
244  }
245  else
246  {
247  std::string error_str("Server versions file parsing error - " + element_key + " - unknown field");
248  LOG_ERROR(error_str);
249  throw std::runtime_error(error_str);
250  }
251  }
252 
253  // Verify each key in the schema can be found in the current version fields
254  //std::pair<const K, E> &item
255  if (std::all_of(schema.cbegin(), schema.cend(), [curr_version](const std::pair<std::string, std::function<bool(const std::string&)>> &schema_item)
256  {
257  return curr_version.end() != std::find_if(curr_version.cbegin(), curr_version.cend(), [schema_item](const std::pair<std::string, std::string> &ver_item) {return schema_item.first == ver_item.first; });
258  }))
259  {
260  _server_versions_vec.emplace_back(curr_version); // Version added to valid versions vector
261  }
262  else
263  {
264  std::string error_str("Server versions json file corrupted - not matching schema requirements");
265  LOG_ERROR(error_str);
266  throw std::runtime_error(error_str);
267  }
268  }
269  }
270  else
271  {
272  std::string error_str("Server versions json file corrupted - Expect versions field of type array \n)"
273  "Parsed key: " + j.begin().key() + ", value type array: " + (j.begin().value().is_array() ? "TRUE" : "FALSE"));
274  LOG_ERROR(error_str);
275  throw std::runtime_error(error_str);
276  }
277  }
278 
279 
281  {
282  // Load server versions info on first access
283  if (!_server_versions_loaded)
284  {
285  std::stringstream server_versions_data;
286  // Download / Open the json file
287  if (!get_server_data(server_versions_data))
288  {
289  return false; // Failed to get version from server/file
290  }
291  else
292  {
293  // Parse and validate the json file - Throws exception on error
294  parse_versions_data(server_versions_data);
295  _server_versions_loaded = true;
296  }
297  }
298  return true;
299  }
300 
301  void versions_db_manager::build_schema(std::unordered_map<std::string, std::function<bool(const std::string&)>>& verifier)
302  {
303  // Builds a map of fields + validation function
304  verifier.emplace("device_name", [](const std::string& val) -> bool { return true; });
305  verifier.emplace("policy_type", [](const std::string& val) -> bool { return (val == "EXPERIMENTAL") || (val == "RECOMMENDED") || (val == "ESSENTIAL"); });
306  verifier.emplace("component", [](const std::string& val) -> bool { return (val == "LIBREALSENSE") || (val == "VIEWER") || (val == "DEPTH_QUALITY_TOOL") || (val == "FIRMWARE"); });
307  verifier.emplace("version", [](const std::string& val) -> bool { return version(val) != version(); });
308  verifier.emplace("platform", [&](const std::string& val) -> bool { return (val == "*") || (val == "Windows amd64") || (val == "Windows x86") || (val == "Linux amd64") || (val == "Linux arm") || (val == "Mac OS"); });
309  verifier.emplace("link", [](const std::string& val) -> bool { return true; });
310  verifier.emplace("release_notes_link", [](const std::string& val) -> bool { return true; });
311  verifier.emplace("description", [](const std::string& val) -> bool { return true; });
312 
313  }
314 
315  bool versions_db_manager::is_device_name_equal(const std::string &str_from_db, const std::string &str_compared, bool allow_wildcard)
316  {
317  if (allow_wildcard)
318  return (0 == str_from_db.compare(0, str_from_db.find('*'), str_compared, 0, str_from_db.find('*')));
319  else
320  return (str_from_db == str_compared);
321  }
322  }
323 
324 
325 }
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8802
constexpr const char * PLATFORM
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5979
a class to store JSON values
Definition: json.hpp:221
void parse_versions_data(const std::stringstream &ver_data)
Definition: cah-model.h:10
GLsizei const GLchar *const * string
GLuint GLfloat * val
void build_schema(std::unordered_map< std::string, std::function< bool(const std::string &)>> &verifier)
bool get_server_data(std::stringstream &ver_data)
void init(void)
Definition: boing.c:180
GLint j
#define LOG_ERROR(...)
Definition: src/types.h:242
std::string to_string(const component_part_type &component)
bool get_version_data_common(const component_part_type component, const version &version, const std::string &req_field, std::string &out)
bool is_device_name_equal(const std::string &str_from_db, const std::string &str_compared, bool allow_wildcard)
static auto it
query_status_type query_versions(const std::string &device_name, component_part_type component, const update_policy_type policy, version &out_version)
bool download_to_stream(const std::string &url, std::stringstream &output, user_callback_func_type user_callback_func=user_callback_func_type())
reference value() const
return the value of an iterator
Definition: json.hpp:8820
GLuint res
Definition: glext.h:8856
basic_json<> json
default JSON class
Definition: json.hpp:12124
bool from_string(const std::string &component_str, component_part_type &component_val)
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4287
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< U > &&generator)
Definition: catch.hpp:4271


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:14