• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
4  *  Copyright (C) 2018 The Linux Foundation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 #define LOG_TAG "device_iot_config"
20 
21 #include "device/include/device_iot_config.h"
22 
23 #include <bluetooth/log.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <time.h>
27 #include <unistd.h>
28 
29 #include <mutex>
30 #include <string>
31 
32 #include "device_iot_config_int.h"
33 #include "internal_include/bt_target.h"
34 #include "osi/include/alarm.h"
35 #include "osi/include/allocator.h"
36 #include "osi/include/compat.h"
37 #include "osi/include/config.h"
38 
39 enum ConfigSource device_iot_config_source = NOT_LOADED;
40 
41 int device_iot_config_devices_loaded = -1;
42 char device_iot_config_time_created[TIME_STRING_LENGTH];
43 
44 std::mutex config_lock;  // protects operations on |config|.
45 std::unique_ptr<config_t> config;
46 alarm_t* config_timer;
47 
48 using namespace bluetooth;
49 
device_iot_config_has_section(const std::string & section)50 bool device_iot_config_has_section(const std::string& section) {
51   std::unique_lock<std::mutex> lock(config_lock);
52   log::assert_that(config != NULL, "assert failed: config != NULL");
53 
54   return config_has_section(*config, section);
55 }
56 
device_iot_config_exist(const std::string & section,const std::string & key)57 bool device_iot_config_exist(const std::string& section, const std::string& key) {
58   std::unique_lock<std::mutex> lock(config_lock);
59   log::assert_that(config != NULL, "assert failed: config != NULL");
60 
61   return config_has_key(*config, section, key);
62 }
63 
device_iot_config_get_int(const std::string & section,const std::string & key,int & value)64 bool device_iot_config_get_int(const std::string& section, const std::string& key, int& value) {
65   std::unique_lock<std::mutex> lock(config_lock);
66   log::assert_that(config != NULL, "assert failed: config != NULL");
67 
68   bool ret = config_has_key(*config, section, key);
69   if (ret) {
70     value = config_get_int(*config, section, key, value);
71   }
72 
73   return ret;
74 }
75 
device_iot_config_set_int(const std::string & section,const std::string & key,int value)76 bool device_iot_config_set_int(const std::string& section, const std::string& key, int value) {
77   std::unique_lock<std::mutex> lock(config_lock);
78   log::assert_that(config != NULL, "assert failed: config != NULL");
79 
80   char value_str[32] = {0};
81   snprintf(value_str, sizeof(value_str), "%d", value);
82   if (device_iot_config_has_key_value(section, key, value_str)) {
83     return true;
84   }
85 
86   config_set_string(config.get(), section, key, value_str);
87   device_iot_config_save_async();
88 
89   return true;
90 }
91 
device_iot_config_int_add_one(const std::string & section,const std::string & key)92 bool device_iot_config_int_add_one(const std::string& section, const std::string& key) {
93   std::unique_lock<std::mutex> lock(config_lock);
94   log::assert_that(config != NULL, "assert failed: config != NULL");
95 
96   int result = 0;
97   result = config_get_int(*config, section, key, result);
98   if (result >= 0) {
99     result += 1;
100   } else {
101     result = 0;
102   }
103   config_set_int(config.get(), section, key, result);
104   device_iot_config_save_async();
105 
106   return true;
107 }
108 
device_iot_config_get_hex(const std::string & section,const std::string & key,int & value)109 bool device_iot_config_get_hex(const std::string& section, const std::string& key, int& value) {
110   std::unique_lock<std::mutex> lock(config_lock);
111   log::assert_that(config != NULL, "assert failed: config != NULL");
112 
113   const std::string* stored_value = config_get_string(*config, section, key, NULL);
114   if (!stored_value) {
115     return false;
116   }
117 
118   errno = 0;
119   char* endptr = nullptr;
120   int result = strtoul(stored_value->c_str(), &endptr, 16);
121   if (stored_value->c_str() == endptr) {
122     return false;
123   }
124   if (endptr == nullptr || endptr[0] != '\0') {
125     return false;
126   }
127   if (errno) {
128     return false;
129   }
130 
131   value = result;
132   return true;
133 }
134 
device_iot_config_set_hex(const std::string & section,const std::string & key,int value,int byte_num)135 bool device_iot_config_set_hex(const std::string& section, const std::string& key, int value,
136                                int byte_num) {
137   char value_str[32] = {0};
138   if (byte_num == 1) {
139     snprintf(value_str, sizeof(value_str), "%02x", value);
140   } else if (byte_num == 2) {
141     snprintf(value_str, sizeof(value_str), "%04x", value);
142   } else if (byte_num == 3) {
143     snprintf(value_str, sizeof(value_str), "%06x", value);
144   } else if (byte_num == 4) {
145     snprintf(value_str, sizeof(value_str), "%08x", value);
146   }
147 
148   std::unique_lock<std::mutex> lock(config_lock);
149   log::assert_that(config != NULL, "assert failed: config != NULL");
150   if (device_iot_config_has_key_value(section, key, value_str)) {
151     return true;
152   }
153 
154   config_set_string(config.get(), section, key, value_str);
155   device_iot_config_save_async();
156 
157   return true;
158 }
159 
device_iot_config_set_hex_if_greater(const std::string & section,const std::string & key,int value,int byte_num)160 bool device_iot_config_set_hex_if_greater(const std::string& section, const std::string& key,
161                                           int value, int byte_num) {
162   int stored_value = 0;
163   bool ret = device_iot_config_get_hex(section, key, stored_value);
164   if (ret && stored_value >= value) {
165     return true;
166   }
167 
168   return device_iot_config_set_hex(section, key, value, byte_num);
169 }
170 
device_iot_config_get_str(const std::string & section,const std::string & key,char * value,int * size_bytes)171 bool device_iot_config_get_str(const std::string& section, const std::string& key, char* value,
172                                int* size_bytes) {
173   std::unique_lock<std::mutex> lock(config_lock);
174   log::assert_that(config != NULL, "assert failed: config != NULL");
175   log::assert_that(value != NULL, "assert failed: value != NULL");
176   log::assert_that(size_bytes != NULL, "assert failed: size_bytes != NULL");
177 
178   const std::string* stored_value = config_get_string(*config, section, key, NULL);
179 
180   if (!stored_value) {
181     return false;
182   }
183 
184   osi_strlcpy(value, stored_value->c_str(), *size_bytes);
185   *size_bytes = strlen(value) + 1;
186 
187   return true;
188 }
189 
device_iot_config_set_str(const std::string & section,const std::string & key,const std::string & value)190 bool device_iot_config_set_str(const std::string& section, const std::string& key,
191                                const std::string& value) {
192   std::unique_lock<std::mutex> lock(config_lock);
193   log::assert_that(config != NULL, "assert failed: config != NULL");
194 
195   if (device_iot_config_has_key_value(section, key, value)) {
196     return true;
197   }
198 
199   config_set_string(config.get(), section, key, value);
200   device_iot_config_save_async();
201 
202   return true;
203 }
204 
device_iot_config_get_bin(const std::string & section,const std::string & key,uint8_t * value,size_t * length)205 bool device_iot_config_get_bin(const std::string& section, const std::string& key, uint8_t* value,
206                                size_t* length) {
207   std::unique_lock<std::mutex> lock(config_lock);
208   log::assert_that(config != NULL, "assert failed: config != NULL");
209   log::assert_that(value != NULL, "assert failed: value != NULL");
210   log::assert_that(length != NULL, "assert failed: length != NULL");
211 
212   const std::string* value_string = config_get_string(*config, section, key, NULL);
213 
214   if (!value_string) {
215     return false;
216   }
217 
218   const char* value_str = value_string->c_str();
219 
220   size_t value_len = strlen(value_str);
221   if ((value_len % 2) != 0 || *length < (value_len / 2)) {
222     return false;
223   }
224 
225   for (size_t i = 0; i < value_len; ++i) {
226     if (!isxdigit(value_str[i])) {
227       return false;
228     }
229   }
230 
231   for (*length = 0; *value_str; value_str += 2, *length += 1) {
232     errno = 0;
233     char* endptr = nullptr;
234     value[*length] = strtoul(value_str, &endptr, 16);
235     if (value_str == endptr) {
236       return false;
237     }
238     if (*endptr) {
239       return false;
240     }
241     if (errno) {
242       return false;
243     }
244   }
245 
246   return true;
247 }
248 
device_iot_config_get_bin_length(const std::string & section,const std::string & key)249 size_t device_iot_config_get_bin_length(const std::string& section, const std::string& key) {
250   std::unique_lock<std::mutex> lock(config_lock);
251   log::assert_that(config != NULL, "assert failed: config != NULL");
252 
253   const std::string* value_str = config_get_string(*config, section, key, NULL);
254 
255   if (!value_str) {
256     return 0;
257   }
258 
259   size_t value_len = strlen(value_str->c_str());
260   return ((value_len % 2) != 0) ? 0 : (value_len / 2);
261 }
262 
device_iot_config_set_bin(const std::string & section,const std::string & key,const uint8_t * value,size_t length)263 bool device_iot_config_set_bin(const std::string& section, const std::string& key,
264                                const uint8_t* value, size_t length) {
265   const char* lookup = "0123456789abcdef";
266 
267   log::verbose("Key = {}", key);
268   if (length > 0) {
269     log::assert_that(value != NULL, "assert failed: value != NULL");
270   }
271 
272   char* str = (char*)osi_calloc(length * 2 + 1);
273   if (str == NULL) {
274     log::error("Unable to allocate a str.");
275     return false;
276   }
277 
278   for (size_t i = 0; i < length; ++i) {
279     str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
280     str[(i * 2) + 1] = lookup[value[i] & 0x0F];
281   }
282 
283   std::unique_lock<std::mutex> lock(config_lock);
284   log::assert_that(config != NULL, "assert failed: config != NULL");
285   if (device_iot_config_has_key_value(section, key, str)) {
286     osi_free(str);
287     return true;
288   }
289 
290   config_set_string(config.get(), section, key, str);
291   device_iot_config_save_async();
292 
293   osi_free(str);
294   return true;
295 }
296 
device_iot_config_remove(const std::string & section,const std::string & key)297 bool device_iot_config_remove(const std::string& section, const std::string& key) {
298   std::unique_lock<std::mutex> lock(config_lock);
299   log::assert_that(config != NULL, "assert failed: config != NULL");
300 
301   return config_remove_key(config.get(), section, key);
302 }
303 
device_iot_config_flush(void)304 void device_iot_config_flush(void) {
305   log::assert_that(config != NULL, "assert failed: config != NULL");
306   log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL");
307 
308   int event =
309           alarm_is_scheduled(config_timer) ? IOT_CONFIG_SAVE_TIMER_FIRED_EVT : IOT_CONFIG_FLUSH_EVT;
310   log::verbose("evt={}", event);
311   alarm_cancel(config_timer);
312   device_iot_config_write(event, NULL);
313 }
314 
device_iot_config_clear(void)315 bool device_iot_config_clear(void) {
316   log::assert_that(config != NULL, "assert failed: config != NULL");
317   log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL");
318 
319   log::info("");
320   alarm_cancel(config_timer);
321 
322   std::unique_lock<std::mutex> lock(config_lock);
323   config.reset();
324 
325   config = config_new_empty();
326   if (config == NULL) {
327     return false;
328   }
329 
330   bool ret = config_save(*config, IOT_CONFIG_FILE_PATH);
331   device_iot_config_source = RESET;
332   return ret;
333 }
334 
device_debug_iot_config_dump(int fd)335 void device_debug_iot_config_dump(int fd) {
336   dprintf(fd, "\nBluetooth Iot Config:\n");
337 
338   dprintf(fd, "  Config Source: ");
339   switch (device_iot_config_source) {
340     case NOT_LOADED:
341       dprintf(fd, "Not loaded\n");
342       break;
343     case ORIGINAL:
344       dprintf(fd, "Original file\n");
345       break;
346     case BACKUP:
347       dprintf(fd, "Backup file\n");
348       break;
349     case NEW_FILE:
350       dprintf(fd, "New file\n");
351       break;
352     case RESET:
353       dprintf(fd, "Reset file\n");
354       break;
355   }
356 
357   dprintf(fd, "  Devices loaded: %d\n", device_iot_config_devices_loaded);
358   dprintf(fd, "  File created/tagged: %s\n", device_iot_config_time_created);
359 }
360