RDK Documentation (Open Sourced RDK Components)
libpd.cpp
Go to the documentation of this file.
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 2016 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  * @file libpd.cpp
21  *
22  * @description This file describes the wrapper function for libparodus library
23  *
24  */
25 #include <string.h>
26 #include <unistd.h>
27 #include <math.h>
28 #include <pthread.h>
29 #include <fcntl.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <errno.h>
33 #include "libpd.h"
34 #include "rdk_debug.h"
35 #include "cJSON.h"
36 #include "waldb.h"
37 
38 #define CONTENT_TYPE_JSON "application/json"
39 #define DEVICE_PROPS_FILE "/etc/device.properties"
40 #define CLIENT_PORT_NUM 6667
41 #define URL_SIZE 64
42 #define LOG_FILE "./tr69hostIflog.txt"
43 #define WEBPA_CONFIG_FILE "/etc/webpa_cfg.json"
44 #define PARODUS_URL "tcp://127.0.0.1:6666"
45 #define PAROUDUS_CLIENT_URL "tcp://127.0.0.1:6667"
46 
47 
48 #ifdef __cplusplus
49 extern "C"
50 {
51 #endif
52 #include <libparodus.h>
53 const char *rdk_logger_module_fetch(void);
54 #ifdef __cplusplus
55 }
56 #endif
57 
58 static void connect_parodus();
59 static void get_parodus_url(char *parodus_url, char *client_url);
60 static void parodus_receive_wait();
61 static long timeValDiff(struct timespec *starttime, struct timespec *finishtime);
62 
63 /*----------------------------------------------------------------------------*/
64 /* Global Variables */
65 /*----------------------------------------------------------------------------*/
66 libpd_instance_t libparodus_instance = NULL;
67 char parodus_url[URL_SIZE] = {'\0'};
68 char client_url[URL_SIZE] = {'\0'};
69 bool exit_parodus_recv = false;
70 pthread_cond_t parodus_cond = PTHREAD_COND_INITIALIZER;
71 pthread_mutex_t parodus_lock = PTHREAD_MUTEX_INITIALIZER;
72 /*----------------------------------------------------------------------------*/
73 /* External functions */
74 /*----------------------------------------------------------------------------*/
75 
76 
77 /**
78  * Initialize libpd and Load Data model, Invoke connection to parodus
79  */
80 void libpd_set_notifyConfigFile(const char* configFile)
81 {
82  setInitialNotifyConfigFile(configFile);
83 }
84 
86 {
87  exit_parodus_recv = true;
88  pthread_cond_signal(&parodus_cond);
89 }
90 /**
91  * Initialize libpd and Load Data model, Invoke connection to parodus
92  */
93 void *libpd_client_mgr(void *)
94 {
95  // Load Data model
96  int status =-1;
97  //RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Loading DB \n");
98  const char *fl = "/tmp/webpa";
99  int err = mkdir(fl, S_IRWXU | S_IRWXG);
100  if((err != 0) && (EEXIST == errno))
101  {
102  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"Failed to create \"%s\" folder with error no(%d). \n", fl, errno);
103  }
104 
105  status = checkDataModelStatus();
106  if(status != 0)
107  {
108  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"Error in Database loading,Webpa Cannot be initialized..!! \n");
109  return NULL;
110  }
111  else
112  {
113  // First connect to parodus
114  connect_parodus();
115 
116  // Lets Register the Notify Callback function
118 
119  // Lets set the initial Notification
121 
122  // Call Parodus receive wait function
124  }
125  return NULL;
126 }
127 
128 
129 /**
130  * Listen for Requests coming from Parodus and process
131  */
132 static void parodus_receive_wait()
133 {
134  int rtn;
135  wrp_msg_t *wrp_msg;
136  wrp_msg_t *res_wrp_msg ;
137 
138  struct timespec start,end,*startPtr,*endPtr,currTime;
139 
140  startPtr = &start;
141  endPtr = &end;
142  char *contentType = NULL;
143 
144  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Entering parodus_receive_wait.. \n");
145 
146  while (!exit_parodus_recv)
147  {
148  rtn = libparodus_receive (libparodus_instance, &wrp_msg, 2000);
149  if (rtn == 1)
150  {
151  continue;
152  }
153  if (rtn != 0)
154  {
155  clock_gettime(CLOCK_MONOTONIC, &currTime);
156  currTime.tv_sec += 5;
157  pthread_mutex_lock(&parodus_lock);
158  if(0 != pthread_cond_timedwait(&parodus_cond, &parodus_lock,&currTime ))
159  {
160  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"parodus_receive_wait()::%s:%d wait for key acquisition timed out"); //CID:119759 - checked return
161  }
162  pthread_mutex_unlock(&parodus_lock);
163  continue;
164  }
165 
166  if (wrp_msg && wrp_msg->msg_type == WRP_MSG_TYPE__REQ)
167  {
168  res_wrp_msg = (wrp_msg_t *)malloc(sizeof(wrp_msg_t));
169  memset(res_wrp_msg, 0, sizeof(wrp_msg_t));
170 
171  getCurrentTime(startPtr);
172  processRequest((char*)wrp_msg->u.req.payload, wrp_msg->u.req.transaction_uuid, ((char **)(&(res_wrp_msg->u.req.payload))));
173 
174  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Response payload is %s\n",(char *)(res_wrp_msg->u.req.payload));
175  if(res_wrp_msg->u.req.payload !=NULL)
176  {
177  res_wrp_msg->u.req.payload_size = strlen((const char *)res_wrp_msg->u.req.payload);
178  }
179  res_wrp_msg->msg_type = wrp_msg->msg_type;
180  if(wrp_msg->u.req.dest != NULL)
181  res_wrp_msg->u.req.source = strdup(wrp_msg->u.req.dest);
182  if(wrp_msg->u.req.source != NULL)
183  res_wrp_msg->u.req.dest = strdup(wrp_msg->u.req.source);
184  if(wrp_msg->u.req.transaction_uuid != NULL)
185  res_wrp_msg->u.req.transaction_uuid = strdup(wrp_msg->u.req.transaction_uuid);
186 
187  contentType = (char *)malloc(sizeof(char)*(strlen(CONTENT_TYPE_JSON)+1));
188  strncpy(contentType,CONTENT_TYPE_JSON,strlen(CONTENT_TYPE_JSON)+1);
189  res_wrp_msg->u.req.content_type = contentType;
190  int sendStatus = libparodus_send(libparodus_instance, res_wrp_msg);
191 
192  if(sendStatus == 0)
193  {
194  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Sent message successfully to parodus\n");
195  }
196  else
197  {
198  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"Failed to send message: '%s'\n",libparodus_strerror((libpd_error_t )sendStatus));
199  }
200  getCurrentTime(endPtr);
201  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Elapsed time : %ld ms\n", timeValDiff(startPtr, endPtr));
202  wrp_free_struct (res_wrp_msg);
203  wrp_free_struct(wrp_msg);
204  }
205  }
206  rtn = libparodus_close_receiver (libparodus_instance);
207  if(rtn == 0)
208  {
209  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Successfully closed libparodus receiver. \n");
210  }
211  else
212  {
213  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"Failure in closing libparodus receiver, Ret = %d\n",rtn);
214  }
215  libparodus_shutdown(&libparodus_instance);
216  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"End of parodus_upstream\n");
217 }
218 
219 /**
220  * Send Notification Message
221  * @param[in] - Notification payload
222  * @param[in] - Notification Source
223  * @param[in] - Notification Destination
224  */
225 void sendNotification(char *payload, char *source, char *destination)
226 {
227  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"************Inside sendNotification ************\n");
228  wrp_msg_t *notif_wrp_msg = NULL;
229  int retry_count = 0;
230  int sendStatus = -1;
231  int backoffRetryTime = 0;
232  int c=2;
233  char *contentType = NULL;
234 
235  notif_wrp_msg = (wrp_msg_t *)malloc(sizeof(wrp_msg_t));
236  memset(notif_wrp_msg, 0, sizeof(wrp_msg_t));
237 
238  notif_wrp_msg ->msg_type = WRP_MSG_TYPE__EVENT;
239  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"source: %s\n",source);
240  notif_wrp_msg ->u.event.source = strdup(source);
241  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"destination: %s\n", destination);
242  notif_wrp_msg ->u.event.dest = strdup(destination);
243  contentType = (char *)malloc(sizeof(char)*(strlen(CONTENT_TYPE_JSON)+1));
244  strncpy(contentType,CONTENT_TYPE_JSON,strlen(CONTENT_TYPE_JSON)+1);
245  notif_wrp_msg->u.event.content_type = contentType;
246  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"content_type is %s\n",notif_wrp_msg->u.event.content_type);
247 
248  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Notification payload: %s\n",payload);
249  notif_wrp_msg ->u.event.payload = (void *)payload;
250  notif_wrp_msg ->u.event.payload_size = strlen((const char*)notif_wrp_msg ->u.event.payload);
251 
252  while(retry_count<=3)
253  {
254  backoffRetryTime = (int) pow(2, c) -1;
255 
256  sendStatus = libparodus_send(libparodus_instance, notif_wrp_msg );
257  if(sendStatus == 0)
258  {
259  retry_count = 0;
260  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Notification successfully sent to parodus\n");
261  break;
262  }
263  else
264  {
265  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"sendNotification backoffRetryTime %d seconds\n", backoffRetryTime);
266  sleep(backoffRetryTime);
267  c++;
268  retry_count++;
269  }
270  }
271 
272  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"sendStatus is %d\n",sendStatus);
273  wrp_free_struct (notif_wrp_msg );
274  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Freed notif_wrp_msg struct.\n");
275 }
276 
277 
278 /*----------------------------------------------------------------------------*/
279 /* Internal functions */
280 /*----------------------------------------------------------------------------*/
281 
282 
283 /**
284  * @brief initialize logging Module
285  * @param[out] - Logger module name
286  */
287 const char *rdk_logger_module_fetch(void)
288 {
289  return "LOG.RDK.PARADUSIF";
290 }
291 
292 /**
293  * @brief Fetch Parodus and client URL from device details
294  * @param[in] - parodus URL
295  * @param[in] - Clinet URL
296  */
297 static void get_parodus_url(char *parodus_url, char *client_url)
298 {
299  FILE *fp = NULL;
300  int getStatus = 0;
301  char *webpaCfgFile = NULL;
302  int ch_count = 0;
303 
304  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Reading Parodus URL...\n");
305  fp = fopen(WEBPA_CONFIG_FILE, "r");
306  if (fp != NULL)
307  {
308  fseek(fp, 0, SEEK_END);
309  ch_count = ftell(fp);
310  if(ch_count < 1)
311  {
312  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"WebPA config file is Empty %s\n", WEBPA_CONFIG_FILE);
313  fclose(fp);
314  }
315  else
316  {
317  fseek(fp, 0, SEEK_SET);
318  webpaCfgFile = (char *) malloc(sizeof(char) * (ch_count + 1));
319  if(webpaCfgFile)
320  {
321  fread(webpaCfgFile, 1, ch_count,fp);
322  webpaCfgFile[ch_count] ='\0';
323  fclose(fp);
324  //CID:18143 - NEGATIVE RETURNS - since ch_count cannot be negative
325  cJSON *webpa_cfg = cJSON_Parse(webpaCfgFile);
326  if(webpa_cfg)
327  {
328  cJSON *pUrl = NULL;
329  cJSON *cUrl = NULL;
330 
331  pUrl = cJSON_GetObjectItem(webpa_cfg,"ParodusURL");
332  cUrl = cJSON_GetObjectItem(webpa_cfg,"ParodusClientURL");
333  if((NULL != pUrl && NULL != cUrl) && (NULL != pUrl->valuestring && NULL != pUrl->valuestring))
334  {
335  strncpy(parodus_url,pUrl->valuestring,strlen(pUrl->valuestring));
336  strncpy(client_url,cUrl->valuestring,strlen(pUrl->valuestring));
337  getStatus = 1;
338  }
339  }
340  free(webpaCfgFile);//CID:18606 - Resource leak
341  }
342  }
343  }
344  else
345  {
346  RDK_LOG(RDK_LOG_ERROR,LOG_PARODUS_IF,"Failed to open Webpa cfg file %s\n", WEBPA_CONFIG_FILE);
347  }
348  // Set Default value if not configured
349  if(!getStatus)
350  {
351  strncpy(parodus_url,PARODUS_URL,strlen(PARODUS_URL));
352  strncpy(client_url,PAROUDUS_CLIENT_URL,strlen(PAROUDUS_CLIENT_URL));
353  }
354  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Parodus URL formed = %s \n",parodus_url);
355  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"Client URL formed = %s \n",client_url);
356 }
357 
358 /**
359  * Open Connect to parodus service using libparodus
360  */
361 static void connect_parodus()
362 {
363  int backoffRetryTime = 0;
364  int backoff_max_time = 5;
365  int max_retry_sleep;
366  //Retry Backoff count shall start at c=2 & calculate 2^c - 1.
367  int c =2;
368  int retval=-1;
369 
370  pthread_detach(pthread_self());
371 
372  max_retry_sleep = (int) pow(2, backoff_max_time) -1;
373  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"max_retry_sleep is %d\n", max_retry_sleep );
374 
375  get_parodus_url(parodus_url, client_url);
376 
377  libpd_cfg_t cfg1 = {.service_name = "config",
378  .receive = true, .keepalive_timeout_secs = 64,
379  .parodus_url = parodus_url,
380  .client_url = client_url
381  };
382 
383  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"libparodus_init with parodus url %s and client url %s\n",cfg1.parodus_url,cfg1.client_url);
384 
385  while(1)
386  {
387  if(backoffRetryTime < max_retry_sleep)
388  {
389  backoffRetryTime = (int) pow(2, c) -1;
390  }
391 
392  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"New backoffRetryTime value calculated as %d seconds\n", backoffRetryTime);
393  int ret =libparodus_init (&libparodus_instance, &cfg1);
394  if(ret ==0)
395  {
396  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"Init for parodus Success..!!\n");
397  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"WebPA is now ready to process requests\n");
398 
399  const char* webpa_start_tm_file = "/tmp/webpa/start_time";
400 
401  if(access(webpa_start_tm_file, F_OK) !=0)
402  {
403  FILE *fp = fopen(webpa_start_tm_file, "w");
404  if (fp != NULL) {
405  fprintf(fp,"%ld", time(NULL));
406  fclose(fp);
407  }
408  }
409  break;
410  }
411  else
412  {
413  sleep(backoffRetryTime);
414  c++;
415 
416  if(backoffRetryTime == max_retry_sleep)
417  {
418  c = 2;
419  backoffRetryTime = 0;
420  RDK_LOG(RDK_LOG_INFO,LOG_PARODUS_IF,"backoffRetryTime reached max value, reseting to initial value\n");
421  }
422  }
423  if(libparodus_instance)
424  {
425  retval = libparodus_shutdown(&libparodus_instance);
426  RDK_LOG(RDK_LOG_DEBUG,LOG_PARODUS_IF,"libparodus_shutdown retval %d\n", retval);
427  }
428  }
429 }
430 
431 
432 static long timeValDiff(struct timespec *starttime, struct timespec *finishtime)
433 {
434  long msec;
435  msec=(finishtime->tv_sec-starttime->tv_sec)*1000;
436  msec+=(finishtime->tv_nsec-starttime->tv_nsec)/1000000;
437  return msec;
438 }
getCurrentTime
void getCurrentTime(struct timespec *timer)
Get Current time.
Definition: hostIf_utils.cpp:466
setInitialNotify
void setInitialNotify()
Initializes WebPA configuration file.
Definition: webpa_adapter.cpp:108
libpd_set_notifyConfigFile
void libpd_set_notifyConfigFile(const char *configFile)
Set Initial Notify config files.
Definition: libpd.cpp:80
libpd.h
parodus_receive_wait
static void parodus_receive_wait()
Definition: libpd.cpp:132
rdk_logger_module_fetch
const char * rdk_logger_module_fetch(void)
initialize logging Module
Definition: libpd.cpp:287
rdk_debug.h
processRequest
void processRequest(char *reqPayload, char *transactionId, char **resPayload)
processRequest processes the request and returns response payload
Definition: webpa_adapter.cpp:170
registerNotifyCallback
void registerNotifyCallback()
Registers the notification callback function.
Definition: webpa_adapter.cpp:83
setInitialNotifyConfigFile
void setInitialNotifyConfigFile(const char *nofityConfigFile)
Set Notify configuration file.
Definition: webpa_adapter.cpp:74
RDK_LOG
#define RDK_LOG
Definition: rdk_debug.h:258
sendNotification
void sendNotification(char *payload, char *source, char *destination)
Definition: libpd.cpp:225
libpd_client_mgr
void * libpd_client_mgr(void *)
Initialize libparodus connection and load DB.
Definition: libpd.cpp:93
stop_parodus_recv_wait
void stop_parodus_recv_wait()
Stops parodus receive wait thread.
Definition: libpd.cpp:85
connect_parodus
static void connect_parodus()
Definition: libpd.cpp:361
get_parodus_url
static void get_parodus_url(char *parodus_url, char *client_url)
Fetch Parodus and client URL from device details.
Definition: libpd.cpp:297