RDK Documentation (Open Sourced RDK Components)
XrdkCentralComBSStore.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2019 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 #include <algorithm>
21 #include <fstream>
22 #include <sstream>
23 #include <string>
24 #include <ctype.h>
25 #include <curl/curl.h>
26 
27 #include "XrdkCentralComBSStore.h"
28 #include "hostIf_utils.h"
29 #include "rfcapi.h"
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #define BS_STORE_KEY "BS_STORE_FILENAME"
33 #define BS_JOURNAL_KEY "BS_JOURNAL_FILENAME"
34 #define RFC_PROPERTIES_FILE "/etc/rfc.properties"
35 #define BS_JSON_FILE "/etc/partners_defaults.json"
36 #define BS_JSON_DEVICE_FILE "/etc/partners_defaults_device.json"
37 #define TR181_PARTNER_ID_KEY "Device.DeviceInfo.X_RDKCENTRAL-COM_Syndication.PartnerId"
38 #define BS_CLEAR_DB_START "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Bootstrap.Control.ClearDB"
39 #define BS_CLEAR_DB_END "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Bootstrap.Control.ClearDBEnd"
40 #define RFC_SERVICE_LOCK "/tmp/.rfcServiceLock"
41 
42 #define CURL_EASY_SETOPT(CURL , CURLoption , Value)\
43  if (curl_easy_setopt(CURL , CURLoption , Value) != CURLE_OK ) {\
44  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: curl_easy_setopt setopt failed ...\n", __FUNCTION__);\
45  }
46 /*CID:121745 - checked return */
47 
48 
49 XBSStore* XBSStore::xbsInstance = NULL;
50 XBSStoreJournal* XBSStore::xbsJournalInstance = NULL;
51 recursive_mutex XBSStore::mtx;
52 thread XBSStore::partnerIdThread;
53 bool XBSStore::m_stopped = false;
54 mutex XBSStore::mtx_stopped;
55 condition_variable XBSStore::cv;
56 mutex XBSStore::g_instance_mutex;
57 
58 size_t static writeCurlResponse(void *ptr, size_t size, size_t nmemb, string stream)
59 {
60  size_t realsize = size * nmemb;
61  string temp(static_cast<const char*>(ptr), realsize);
62  stream.append(temp);
63  return realsize;
64 }
65 void XBSStore::getAuthServicePartnerID()
66 {
67  bool partnerIdChanged = false;
68  auto sec = chrono::seconds(1);
69 
70  while(!m_stopped)
71  {
72  if ( partnerIdChanged )
73  {
74  ifstream f(RFC_SERVICE_LOCK);
75  if (f.good())
76  {
77  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: RFC service in progress. Retry after 30 sec\n", __FUNCTION__);
78  unique_lock<mutex> lck(mtx_stopped);
79  cv.wait_for(lck, 30*sec, [] {return m_stopped;});
80  continue;
81  }
82  else
83  {
84  //Invalidate RFC hash and retrigger so we can apply RFC overrides to the new partner configuration
85  WDMP_STATUS status = setRFCParameter("tr69hostif", "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Control.ConfigSetHash", "INVALIDATE", WDMP_STRING);
86  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: RFC SET to Invalidate Hash status = %d \n", __FUNCTION__, status);
87 
88  status = setRFCParameter("tr69hostif", "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Control.RetrieveNow", "1", WDMP_UINT);
89  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: RFC SET to retrieveNow status = %d \n", __FUNCTION__, status);
90  break;
91  }
92  }
93 
94  string newPartnerId = "";
95  string response;
96  string postData;
97  string tokenheader;
98 
99  CURL *curl = curl_easy_init();
100  if(curl)
101  {
102  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: call curl to get partner ID..\n", __FUNCTION__);
103  std::string sToken = get_security_token();
104  if(sToken.empty()) {
105  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: Thunder security token is empty..\n", __FUNCTION__);
106  }
107  tokenheader = "Authorization: Bearer " + sToken;
108 
109  postData = "{\"jsonrpc\":\"2.0\",\"id\":\"3\",\"method\": \"org.rdk.AuthService.getDeviceId\" }";
110 
111  struct curl_slist *list = NULL;
112 
113  list = curl_slist_append(list, tokenheader.c_str());
114  list = curl_slist_append(list, "Content-Type: application/json");
115 
116  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
117  curl_easy_setopt(curl, CURLOPT_POST, 1L);
118  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
119  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCurlResponse);
120  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
121  curl_easy_setopt(curl, CURLOPT_URL, JSONRPC_URL);
122 
123  CURLcode res = curl_easy_perform(curl);
124  long http_code = 0;
125  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
126  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: curl response : %d http response code: %ld\n", __FUNCTION__, res, http_code);
127  curl_easy_cleanup(curl);
128  curl_slist_free_all(list);
129 
130  if(res == CURLE_OK)
131  {
132  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: curl response string = %s\n", __FUNCTION__, response.c_str());
133  cJSON* root = cJSON_Parse(response.c_str());
134  if(root)
135  {
136  cJSON* jsonObj = cJSON_GetObjectItem(root, "result");
137  if(jsonObj)
138  {
139  cJSON* partnerID = cJSON_GetObjectItem(jsonObj, "partnerId");
140  if(partnerID && partnerID->type == cJSON_String && partnerID->valuestring && strlen(partnerID->valuestring) > 0)
141  {
142  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "Found partnerID value = %s\n", partnerID->valuestring);
143  newPartnerId = partnerID->valuestring;
144  }
145  else
146  {
147  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] json parse error, no \"partnerId\" in the output from Thunder plugin\n", __FUNCTION__);
148  cJSON_Delete(root);
149  return;
150  }
151  }
152  else
153  {
154  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] json parse error, no \"result\" in the output from Thunder plugin\n", __FUNCTION__);
155  cJSON_Delete(root);
156  return;
157  }
158 
159  cJSON_Delete(root);
160  }
161  else
162  {
163  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: json parse error\n", __FUNCTION__);
164  }
165  }
166  }
167  else
168  {
169  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: curl init failed\n", __FUNCTION__);
170  }
171  if(newPartnerId.length() > 0)
172  {
173  string storedPartnerId = xbsInstance->getRawValue(TR181_PARTNER_ID_KEY);
174  if (newPartnerId.compare(storedPartnerId) != 0)
175  {
176  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF,"partnerId has changed\n");
177  partnerIdChanged = true;
178  mtx.lock();
179  xbsInstance->resetCacheAndStore();
180  xbsInstance->setRawValue(TR181_PARTNER_ID_KEY, newPartnerId.c_str(), HOSTIF_SRC_DEFAULT);
181  xbsInstance->m_initDone = false;
182  xbsInstance->init();
183  mtx.unlock();
184  }
185  else
186  break;
187  }
188  else
189  {
190  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: partnerId not found. Retry after 30 sec\n", __FUNCTION__);
191  unique_lock<mutex> lck(mtx_stopped);
192  cv.wait_for(lck, 30*sec, [] {return m_stopped;});
193  }
194  }
195 }
196 
197 void XBSStore::resetCacheAndStore()
198 {
199  m_dict.clear();
200  if (!m_filename.empty())
201  {
202  if(remove(m_filename.c_str()) != 0)
203  {
204  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: Error occured ,File is not removed.\n", __FUNCTION__);
205  } //CID:80489 - Checked Return
206  }
207  xbsJournalInstance->resetCacheAndStore();
208 
209 }
210 
211 // Get device specific bootstrap defaults and give precedence to these values over generic bootstrap defaults.
212 bool XBSStore::getPartnerDeviceConfig(cJSON* partnerConfig, const string & partnerId)
213 {
214  ifstream ifs_json_device(BS_JSON_DEVICE_FILE);
215  if(!ifs_json_device.is_open())
216  {
217  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: Device specific file [%s] does not exist\n", __FUNCTION__, BS_JSON_DEVICE_FILE);
218  return true;
219  }
220 
221  ifs_json_device.seekg(0, std::ios::end);
222  size_t size = ifs_json_device.tellg();
223  string buffer_device(size, ' ');
224  ifs_json_device.seekg(0);
225  ifs_json_device.read(&buffer_device[0], size);
226  const char *jsonTextDevice = buffer_device.c_str();
227 
228  cJSON *jsonDevice = cJSON_Parse(jsonTextDevice);
229  if (!jsonDevice)
230  {
231  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: json parse error for device file \n", __FUNCTION__);
232  return false;
233  }
234 
235  cJSON* partnerDeviceConfig = cJSON_GetObjectItem(jsonDevice, partnerId.c_str());
236  if (!partnerDeviceConfig)
237  {
238  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF,"%s: Unknown partner:%s, using default.\n", __FUNCTION__, partnerId.c_str() );
239  partnerDeviceConfig = cJSON_GetObjectItem(jsonDevice, "default" );
240 
241  if (!partnerDeviceConfig)
242  {
243  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF,"%s: Error for partner:%s, error = [%s]\n", __FUNCTION__, partnerId.c_str(), cJSON_GetErrorPtr());
244  return true;
245  }
246  }
247 
248  cJSON *configDeviceObject = partnerDeviceConfig->child;
249  while( configDeviceObject )
250  {
251  char *configDeviceKey = configDeviceObject->string;
252  char *configDeviceValue = configDeviceObject->valuestring;
253 
254  if (cJSON_GetObjectItem(partnerConfig, configDeviceKey)) {
255  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"%s: key %s exist in generic json...replace entry\n", __FUNCTION__, configDeviceKey );
256  cJSON_ReplaceItemInObject(partnerConfig, configDeviceKey, cJSON_CreateString(configDeviceValue));
257  }
258  else
259  {
260  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF,"%s: key %s does NOT exist generic json...add new entry\n", __FUNCTION__, configDeviceKey );
261  cJSON_AddItemToObject(partnerConfig, configDeviceKey, cJSON_CreateString(configDeviceValue));
262  }
263  configDeviceObject = configDeviceObject->next;
264  }
265  return true;
266 }
267 
268 bool XBSStore::loadFromJson()
269 {
270  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
271 
272  string partnerId = getRawValue(TR181_PARTNER_ID_KEY);
273 
274  if (partnerId.length() == 0)
275  {
276  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: waiting on partnerId..\n", __FUNCTION__);
277  return false;
278  }
279 
280  ifstream ifs_json(BS_JSON_FILE);
281  ifs_json.seekg(0, std::ios::end);
282  size_t size = ifs_json.tellg();
283  string buffer(size, ' ');
284  ifs_json.seekg(0);
285  ifs_json.read(&buffer[0], size);
286  const char *jsonText = buffer.c_str();
287 
288  cJSON *json = cJSON_Parse(jsonText);
289  if (!json)
290  {
291  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: json parse error \n", __FUNCTION__);
292  return false;
293  }
294 
295  cJSON* partnerConfig = cJSON_GetObjectItem(json, partnerId.c_str());
296  if (!partnerConfig)
297  {
298  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF,"Unknown partner:%s, using default.\n", partnerId.c_str() );
299  partnerConfig = cJSON_GetObjectItem(json, "default" );
300 
301  if (!partnerConfig)
302  {
303  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF,"Error for partner:%s, error = [%s]\n", partnerId.c_str(), cJSON_GetErrorPtr());
304  return false;
305  }
306  }
307  if(partnerConfig->type == cJSON_Object) {
308  if(!getPartnerDeviceConfig(partnerConfig, partnerId))
309  {
310  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: error reading partners_defaults_device.json \n", __FUNCTION__);
311  return false;
312  }
313 
314  ifstream ifs_bsini(m_filename);
315  if (ifs_bsini.is_open()) {
316  RDK_LOG (RDK_LOG_DEBUG, LOG_TR69HOSTIF, "%s: File [%s] exist. Look for any default parameter changes.\n", __FUNCTION__, m_filename.c_str());
317  ifs_bsini.close();
318  }
319  else
320  {
321  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: Initial Update of Bootstrap stores\n", __FUNCTION__);
322  m_initialUpdate = true;
323  xbsJournalInstance->setInitialUpdate(true);
324  }
325 
326  cJSON *configObject = partnerConfig->child;
327 
328  //Check if any params were removed in firmware update. Do not remove params that were set by RFC/WebPA.
329  bool removedEntries = false;
330  for (unordered_map<string, string>::iterator it=m_dict.begin(); it!=m_dict.end();)
331  {
332  string key = it->first;
333  if (!cJSON_GetObjectItem(partnerConfig, key.c_str()) && key.compare(TR181_PARTNER_ID_KEY) != 0 && xbsJournalInstance->getJournalSource(key) == HOSTIF_SRC_DEFAULT)
334  {
335  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: Remove param %s from bootstrap store, size=%d\n", __FUNCTION__, key.c_str(), m_dict.size());
336  removedEntries = true;
337  it = m_dict.erase(it);
338  xbsJournalInstance->removeRecord(key);
339  }
340  else
341  {
342  it++;
343  }
344  }
345  if (removedEntries)
346  {
347  ofstream ofs(m_filename, ios::trunc | ios::out);
348  if(!ofs.is_open())
349  {
350  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "Failed to open : %s \n", m_filename.c_str());
351  return false;
352  }
353  for (unordered_map<string, string>::iterator it=m_dict.begin(); it!=m_dict.end(); ++it)
354  {
355  ofs << it->first << '=' << it->second << endl;
356  }
357  ofs.flush();
358  ofs.close();
359  xbsJournalInstance->rfcUpdateEnd();
360  }
361 
362  while( configObject )
363  {
364  char *configKey = configObject->string;
365  char *configValue = configObject->valuestring;
366  RDK_LOG(RDK_LOG_TRACE1, LOG_TR69HOSTIF,"bootstrap json parser: key=%s value=%s\n",configKey, configValue);
367  setRawValue(configKey, configValue, HOSTIF_SRC_DEFAULT);
368  configObject = configObject->next;
369  }
370  m_initialUpdate = false;
371  xbsJournalInstance->setInitialUpdate(false);
372  }
373  else
374  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF,"partnerConfig->type not of object type...");
375  cJSON_Delete(json);
376  return true;
377 }
378 
379 string XBSStore::getRawValue(const string &key)
380 {
381  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
382 
383  mtx.lock();
384  unordered_map<string,string>::const_iterator it = m_dict.find(key);
385  if (it == m_dict.end()) {
386  mtx.unlock();
387  return "";
388  }
389  mtx.unlock();
390  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s : Value = %s \n", __FUNCTION__, it->second.c_str());
391 
392  return it->second;
393 }
394 
395 bool XBSStore::setRawValue(const string &key, const string &value, HostIf_Source_Type_t sourceType)
396 {
397  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
398 
399  RDK_LOG (RDK_LOG_DEBUG, LOG_TR69HOSTIF, " %s: m_initialUpdate=%d\n", __FUNCTION__, m_initialUpdate);
400  std::string outputDir="/opt/secure/RFC";
401  struct stat st;
402  if(stat(outputDir.c_str(),&st) != 0) //creating RFC directory if doesn't exist
403  {
404  mkdir(outputDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
405  }
406  if(m_initialUpdate)
407  {
408  ofstream ofs(m_filename, ios::out | ios::app);
409 
410  if(!ofs.is_open())
411  {
412  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "Failed to open : %s \n", m_filename.c_str());
413  return false;
414  }
415  m_dict[key] = value;
416  ofs << key << '=' << value << endl;
417  ofs.flush();
418  ofs.close();
419  }
420  else
421  {
422  const string &currentValue = getRawValue(key);
423  RDK_LOG (RDK_LOG_DEBUG, LOG_TR69HOSTIF, "Given Value : %s ---- Current value : %s \n", value.c_str(), currentValue.c_str());
424 
425  if(strlen(currentValue.c_str()) > 0)
426  {
427  if(!strcasecmp(currentValue.c_str(), value.c_str()))
428  {
429  RDK_LOG (RDK_LOG_DEBUG, LOG_TR69HOSTIF, "Property value exists, don't have to overwrite\n");
430  if(sourceType != xbsJournalInstance->getJournalSource(key))
431  xbsJournalInstance->setJournalValue(key, value, sourceType); //Update the journal with the latest source so that the value will not be overriden by less favored source later.
432  return true;
433  }
434  }
435 
436  //Keep an updated firmware value in the journal even though it is not active configuration.
437  if(sourceType == HOSTIF_SRC_DEFAULT &&
438  (xbsJournalInstance->getJournalSource(key) == HOSTIF_SRC_RFC || xbsJournalInstance->getJournalSource(key) == HOSTIF_SRC_WEBPA) )
439  {
440  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "Update firmware value in journal even though it is not active..\n");
441  xbsJournalInstance->setJournalValue(key, value, sourceType);
442  return true;
443  }
444  ofstream ofs(m_filename, ios::trunc | ios::out);
445  if(!ofs.is_open())
446  {
447  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "Failed to open : %s \n", m_filename.c_str());
448  return false;
449  }
450  m_dict[key] = value;
451 
452  for (unordered_map<string, string>::iterator it=m_dict.begin(); it!=m_dict.end(); ++it)
453  {
454  ofs << it->first << '=' << it->second << endl;
455  }
456  ofs.flush();
457  ofs.close();
458  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "Bootstrap config update: %s, %s, %s, %d-%s \n", key.c_str(), value.c_str(), currentValue.c_str(), sourceType, xbsJournalInstance->getUpdatedSourceString(sourceType).c_str());
459  }
460  xbsJournalInstance->setJournalValue(key, value, sourceType);
461 
462  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
463  return true;
464 }
465 
466 faultCode_t XBSStore::getValue(HOSTIF_MsgData_t *stMsgData)
467 {
468  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
469  if(!init())
470  {
471  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "Init not complete...value may not be for latest partner ID\n");
472  }
473  string rawValue = getRawValue(stMsgData->paramName);
474  if(rawValue.length() > 0)
475  {
476  putValue(stMsgData, rawValue.c_str());
477  stMsgData->faultCode = fcNoFault;
478  }
479  else
480  {
481  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "%s : Parameter Not Found in %s\n", stMsgData->paramName, m_filename.c_str());
482  stMsgData->faultCode = fcInternalError;
483  }
484  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s\n", __FUNCTION__);
485  return stMsgData->faultCode;
486 }
487 
488 bool XBSStore::clearRfcValues()
489 {
490  ofstream ofs(m_filename, ios::trunc | ios::out);
491  if(!ofs.is_open())
492  {
493  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "Failed to open : %s \n", m_filename.c_str());
494  return false;
495  }
496 
497  for (unordered_map<string, string>::iterator it=m_dict.begin(); it!=m_dict.end(); ++it)
498  {
499  string key = it->first;
500  string defaultValue = "";
501  if(xbsJournalInstance->clearRfcAndGetDefaultValue(key, defaultValue))
502  {
503  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "%s: key=%s, defaultValue=%s\n", __FUNCTION__, key.c_str(), defaultValue.c_str());
504  m_dict[key] = defaultValue;
505  }
506  }
507 
508  for (unordered_map<string, string>::iterator it=m_dict.begin(); it!=m_dict.end(); ++it)
509  {
510  ofs << it->first << '=' << it->second << endl;
511  }
512  ofs.flush();
513  ofs.close();
514  return true;
515 }
516 
517 faultCode_t XBSStore::overrideValue(HOSTIF_MsgData_t *stMsgData)
518 {
519  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
520  if(!init())
521  {
522  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF, "Init Failed, can't handle the request\n");
523  return fcInternalError;
524  }
525 
526  if (strcasecmp(stMsgData->paramName,BS_CLEAR_DB_START) == 0)
527  {
528  m_rfcUpdateInProgress = true;
529  xbsJournalInstance->rfcUpdateStarted();
530  stMsgData->faultCode = fcNoFault;
531  return stMsgData->faultCode;
532  }
533  else if (strcasecmp(stMsgData->paramName,BS_CLEAR_DB_END) == 0)
534  {
535  clearRfcValues();
536  xbsJournalInstance->rfcUpdateEnd();
537  m_rfcUpdateInProgress = false;
538  stMsgData->faultCode = fcNoFault;
539  return stMsgData->faultCode;
540  }
541 
542  mtx.lock();
543  if (m_dict.find(stMsgData->paramName) == m_dict.end())
544  {
545  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "Param does not exist in bootstrap store. Allowing override.\n");
546  }
547 
548  const string &givenValue = getStringValue(stMsgData);
549 
550  HostIf_Source_Type_t sourceType;
551  if(stMsgData->requestor == HOSTIF_SRC_WEBPA)
552  {
553  sourceType = HOSTIF_SRC_WEBPA;
554  }
555  else if(stMsgData->requestor == HOSTIF_SRC_RFC && xbsJournalInstance->getJournalSource(stMsgData->paramName) != HOSTIF_SRC_WEBPA)
556  {
557  sourceType = HOSTIF_SRC_RFC;
558  }
559  else
560  {
561  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "Bootstrap override rules not met: [requestor=%d]\n");
562  mtx.unlock();
563  return fcInternalError;
564  }
565 
566  if (m_rfcUpdateInProgress)
567  xbsJournalInstance->resetClearRfc(stMsgData->paramName);
568 
569  if(setRawValue(stMsgData->paramName, givenValue, sourceType))
570  {
571  stMsgData->faultCode = fcNoFault;
572  }
573  else
574  {
575  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "Unable to Set Value for given Param\n");
576  stMsgData->faultCode = fcInternalError;
577  }
578  mtx.unlock();
579  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
580  return stMsgData->faultCode;
581 }
582 
583 void XBSStore::initBSPropertiesFileName()
584 {
585  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
586  ifstream ifs_rfc(RFC_PROPERTIES_FILE);
587  if(!ifs_rfc.is_open())
588  {
589  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: Trying to open a non-existent file [%s] \n", __FUNCTION__, RFC_PROPERTIES_FILE);
590  }
591  else
592  {
593  string line;
594  while (getline(ifs_rfc, line)) {
595  size_t splitterPos = line.find('=');
596  if (splitterPos < line.length()) {
597  string key = line.substr(0, splitterPos);
598  string value = line.substr(splitterPos+1, line.length());
599  if(!strcmp(key.c_str(), BS_STORE_KEY))
600  {
601  m_filename = value;
602  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF, "Bootstrap Properties FileName = %s\n", m_filename.c_str());
603  }
604  else if(!strcmp(key.c_str(), BS_JOURNAL_KEY))
605  {
606  RDK_LOG(RDK_LOG_DEBUG, LOG_TR69HOSTIF, "Bootstrap Journal FileName = %s\n", value.c_str());
607  xbsJournalInstance = XBSStoreJournal::getInstance(value.c_str());
608  }
609  }
610  }
611  ifs_rfc.close();
612 
613  if(m_filename.empty())
614  {
615  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF, "Didn't find %s in %s\n", BS_STORE_KEY, RFC_PROPERTIES_FILE);
616  }
617  }
618  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
619 }
620 
621 bool XBSStore::loadBSPropertiesIntoCache()
622 {
623  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
624  if(m_filename.empty())
625  {
626  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF, "Invalid Bootstrap Properties filename, Unable to load properties\n");
627  return false;
628  }
629  // get rid of quotes, it is quite common with properties files
630  m_filename.erase(remove(m_filename.begin(), m_filename.end(), '\"'), m_filename.end());
631  m_dict.clear();
632  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "Bootstrap Properties File : %s \n", m_filename.c_str());
633 
634  ifstream ifs_bsini(m_filename);
635  if (ifs_bsini.is_open())
636  {
637  string line;
638  while (getline(ifs_bsini, line)) {
639  size_t splitterPos = line.find('=');
640  if (splitterPos < line.length()) {
641  string key = line.substr(0, splitterPos);
642  string value = line.substr(splitterPos+1, line.length());
643  m_dict[key] = value;
644  }
645  }
646  ifs_bsini.close();
647  }
648  else
649  {
650  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: bootstrap ini does not exist...\n", __FUNCTION__);
651  }
652 
653  if (!loadFromJson())
654  {
655  RDK_LOG(RDK_LOG_ERROR, LOG_TR69HOSTIF, "%s: loadFromJson() failed \n", __FUNCTION__);
656  return false;
657  }
658 
659  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
660  return true;
661 }
662 
663 bool XBSStore::init()
664 {
665  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
666  mtx.lock();
667  if(m_initDone)
668  {
669  mtx.unlock();
670  return m_initDone;
671  }
672  initBSPropertiesFileName();
673 
674  m_initDone = loadBSPropertiesIntoCache();
675 
676  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
677  mtx.unlock();
678  return m_initDone;
679 }
680 
681 XBSStore::XBSStore()
682 {
683  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
684 
685  m_initDone = false;
686  m_initialUpdate = false;
687  m_rfcUpdateInProgress = false;
688 
689  init();
690 
691  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
692 }
693 
694 XBSStore* XBSStore::getInstance()
695 {
696  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Entering %s \n", __FUNCTION__);
697 
698  if(!xbsInstance)
699  {
700  std::lock_guard<std::mutex> guard(g_instance_mutex);
701  if(!xbsInstance)
702  {
703  xbsInstance = new XBSStore;
704  RDK_LOG(RDK_LOG_INFO, LOG_TR69HOSTIF, "%s: Start thread getAuthServicePartnerID \n", __FUNCTION__);
705  partnerIdThread = thread(getAuthServicePartnerID);
706  partnerIdThread.detach();
707  }
708  }
709 
710  RDK_LOG (RDK_LOG_TRACE1, LOG_TR69HOSTIF, "Leaving %s \n", __FUNCTION__);
711  return xbsInstance;
712 }
713 
714 void XBSStore::stop()
715 {
716  m_stopped = true;
717  cv.notify_one();
718 }
XBSStore
Definition: XrdkCentralComBSStore.h:33
HostIf_Source_Type_t
enum _HostIf_Source_Type_t HostIf_Source_Type_t
_HostIf_MsgData_t
Definition: hostIf_tr69ReqHandler.h:170
XBSStoreJournal
Definition: XrdkCentralComBSStoreJournal.h:43
faultCode_t
enum _faultCodes faultCode_t
RDK_LOG
#define RDK_LOG
Definition: rdk_debug.h:258
_HostIf_MsgData_t::faultCode
faultCode_t faultCode
Definition: hostIf_tr69ReqHandler.h:179
_HostIf_MsgData_t::paramName
char paramName[(4 *1024)]
Definition: hostIf_tr69ReqHandler.h:171
get_security_token
std::string get_security_token()
Definition: hostIf_utils.cpp:572
_HostIf_MsgData_t::requestor
HostIf_Source_Type_t requestor
Definition: hostIf_tr69ReqHandler.h:180