RDK Documentation (Open Sourced RDK Components)
Device_IP_Diagnostics_SpeedTest.cpp
1 /*
2  * If not stated otherwise in this file or this component's LICENSE 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  * author: Derric_Lynns@cable.comcast.com
20  *
21 */
22 
23 
24 /**
25 * @defgroup tr69hostif
26 * @{
27 * @defgroup hostif
28 * @{
29 **/
30 
31 #include "Device_IP_Diagnostics_SpeedTest.h"
32 #include "hostIf_utils.h"
33 #include <string>
34 #include <fstream>
35 
36 // the below directory holds the database for TR objects
37 #define TR69DIR "/opt/tr-181/"
38 #define STORE_EXTENSION "sdb"
39 
40 // the diagnostics directory is used only in developer builds
41 #define DIAGNOSTICS_DIR "/opt/diagnostics/"
42 #define PROD_DIR "/usr/bin/"
43 
44 // script name
45 #define SPEEDTEST_BIN "speedtest.sh"
46 #define NON_BLOCKING " &"
47 
48 // profile name
49 const char* hostIf_IP_Diagnostics_SpeedTest::SpeedTestProfile = "Device.IP.Diagnostics.X_RDKCENTRAL-COM_SpeedTest.";
50 
51 /**
52  * @brief The constructor checks for the database file at TR69DIR and loads the database
53  * It checks for the database file and if doesnt exist, it creates one
54  *
55  */
57 {
58  std::string filename;
59  filename.append (TR69DIR).append(SpeedTestProfile).append (STORE_EXTENSION);
60 
61  bCalledEnable = false;
62  bCalledRun = false;
63 
64  // load sdb data file
65  if (!dbStore.load (filename))
66  {
67  // creates a new file if it doesn't exist
68  std::ofstream output_stream (filename.c_str());
69  }
70  else
71  {
72  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "[%s] dbStore for SpeedTest is already present\n", __FUNCTION__);
73  }
74 }
75 
76 /**
77  * @brief This function provides single instance of hostIF_IP_Diagnostics_SpeedTest
78  *
79  */
81 {
82  // singleton implementation
83  static hostIf_IP_Diagnostics_SpeedTest instance;
84  return instance;
85 }
86 
87 /**
88  * @brief This function is called when profile parameter needs to be read
89  * It gets the values of Enable_Speedtest, Run, Argument, ClientType, Authentication ans Status
90  * If any other parameter is requested the fault code is set to invalid paramtername
91  *
92  *
93  * @return Returns the status of the operation.
94  *
95  * @retval OK if it is successfully fetch the data from the device else NOK
96  *
97  */
99 {
100  LOG_ENTRY_EXIT;
101 
102  int ret = NOK;
103  std::string spdtst_parameter_name (stMsgData->paramName + strlen (SpeedTestProfile));
104  // the order of if condition is step by step and must not be changed
105  if (spdtst_parameter_name.compare("Enable_Speedtest") &&
106  spdtst_parameter_name.compare ("Run") &&
107  spdtst_parameter_name.compare ("Argument") &&
108  spdtst_parameter_name.compare ("ClientType") &&
109  spdtst_parameter_name.compare ("Authentication") &&
110  spdtst_parameter_name.compare ("Status"))
111  {
112  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] Unsupported SpeedTest parameter '%s'\n", __FUNCTION__, stMsgData->paramName);
113  stMsgData->faultCode = fcInvalidParameterName;
114  }
115  else
116  {
117  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "[%s] SpeedTest parameter '%s' is being set\n", __FUNCTION__, stMsgData->paramName);
118  std::string value = dbStore.value (stMsgData->paramName, "");
119  putValue(stMsgData, value);
120  stMsgData->faultCode = fcNoFault;
121  ret = OK;
122  }
123 
124  return ret;
125 }
126 
127 /**
128  * @brief This function sets the profile parameter data
129  * It sets the values of Enable_Speedtest, Run, Argument, ClientType, Authentication ans Status
130  * If any other parameter is requested the fault code is set to invalid paramtername
131  *
132  * @return Returns the status of the operation.
133  *
134  * @retval OK if it is successfully fetch the data from the device, else it returns NOK
135  *
136  */
138 {
139  LOG_ENTRY_EXIT;
140 
141  int ret = NOK;
142  std::string spdtst_parameter_name (stMsgData->paramName + strlen (SpeedTestProfile));
143  // the order of if condition is step by step and must not be changed
144  if (spdtst_parameter_name.compare("Enable_Speedtest") &&
145  spdtst_parameter_name.compare ("Run") &&
146  spdtst_parameter_name.compare ("Argument") &&
147  spdtst_parameter_name.compare ("ClientType") &&
148  spdtst_parameter_name.compare ("Authentication") &&
149  spdtst_parameter_name.compare ("Status"))
150  {
151  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] Unsupported SpeedTest parameter '%s'\n", __FUNCTION__, stMsgData->paramName);
152  stMsgData->faultCode = fcInvalidParameterName;
153  }
154  else if (false == dbStore.setValue (stMsgData->paramName, getStringValue(stMsgData)))
155  {
156  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] SpeedTest setValue failed '%s'\n", __FUNCTION__, stMsgData->paramName);
157  stMsgData->faultCode = fcInternalError;
158  }
159  else
160  {
161  ret = OK;
162  stMsgData->faultCode = fcNoFault;
163  processMsg(stMsgData);
164 
165  if( stMsgData->faultCode == fcInternalError )
166  {
167  ret = NOK;
168  RDK_LOG (RDK_LOG_ERROR, LOG_TR69HOSTIF, "[%s] SpeedTest setValue failed '%s'\n", __FUNCTION__, stMsgData->paramName);
169  }
170  else
171  {
172  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "[%s] SpeedTest setValue succeeded '%s'\n", __FUNCTION__, stMsgData->paramName);
173  }
174  }
175 
176  return ret;
177 }
178 
179 /**
180  * @brief This function processes the set message for triggering speedtest-client
181  * It checks for Enable_Speedtest and Run profile parameters and sets to launch
182  * internet measurement platform application from the respective location.
183  * the failure of the function is handled in handleSetMsg function when it meets fcInternalError
184  *
185  */
187 {
188  std::string spdtst_parameter_name (stMsgData->paramName + strlen (SpeedTestProfile));
189 
190  if (spdtst_parameter_name.compare ("Enable_Speedtest") == 0)
191  {
192  bCalledEnable = get_boolean(stMsgData->paramValue);
193  }
194 
195  if (spdtst_parameter_name.compare ("Run") == 0)
196  {
197  bCalledRun = get_boolean(stMsgData->paramValue);
198 
199  if (bCalledEnable && bCalledRun)
200  {
201  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "[%s] Speedtest application is being launched '%s'\n", __FUNCTION__, stMsgData->paramName);
202  std::string application_diagnostics;
203  std::string application_prod;
204  std::string application;
205  // read only
206  ifstream launch_script;
207 
208  // the below variables depends on macro, hence do not try optimizing with one variable as compiler could optimize out
209  application_prod.append (PROD_DIR).append(SPEEDTEST_BIN);
210  application_diagnostics.append (DIAGNOSTICS_DIR).append(SPEEDTEST_BIN);
211 
212  // initialize before the SPEEDTEST_DIAGNOSTICS macro check
213  application = application_prod;
214 
215 #ifdef SPEEDTEST_DIAGNOSTICS
216  application = application_diagnostics;
217 #endif
218 
219  // check and launch
220  launch_script.open(application.c_str());
221  if (launch_script.fail())
222  {
223  application = application_prod;
224  launch_script.open(application.c_str());
225  if (launch_script.fail())
226  {
227  RDK_LOG (RDK_LOG_INFO, LOG_TR69HOSTIF, "[%s] Speedtest launch script is not found anywhere\n", __FUNCTION__);
228  }
229  }
230 
231  application.append(NON_BLOCKING);
232  system(application.c_str());
233 
234  // the condition here is for parameter Run and its being reset
235  if( false == dbStore.setValue (stMsgData->paramName, "false"))
236  {
237  // cannot reset then handle return as NOK
238  stMsgData->faultCode = fcInternalError;
239  }
240 
241  bCalledRun = false;
242  }
243  }
244 
245 }
246 
247 /** @} */
248 /** @} */
hostIf_IP_Diagnostics_SpeedTest::processMsg
void processMsg(HOSTIF_MsgData_t *stMsgData)
This function processes the set message for triggering speedtest-client It checks for Enable_Speedtes...
Definition: Device_IP_Diagnostics_SpeedTest.cpp:186
_HostIf_MsgData_t
Definition: hostIf_tr69ReqHandler.h:170
hostIf_IP_Diagnostics_SpeedTest::handleSetMsg
int handleSetMsg(HOSTIF_MsgData_t *stMsgData)
This function sets the profile parameter data It sets the values of Enable_Speedtest,...
Definition: Device_IP_Diagnostics_SpeedTest.cpp:137
hostIf_IP_Diagnostics_SpeedTest::hostIf_IP_Diagnostics_SpeedTest
hostIf_IP_Diagnostics_SpeedTest()
The constructor checks for the database file at TR69DIR and loads the database It checks for the data...
Definition: Device_IP_Diagnostics_SpeedTest.cpp:56
hostIf_IP_Diagnostics_SpeedTest::getInstance
static hostIf_IP_Diagnostics_SpeedTest & getInstance()
This function provides single instance of hostIF_IP_Diagnostics_SpeedTest.
Definition: Device_IP_Diagnostics_SpeedTest.cpp:80
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
hostIf_IP_Diagnostics_SpeedTest
Definition: Device_IP_Diagnostics_SpeedTest.h:36
_HostIf_MsgData_t::paramValue
char paramValue[(4 *1024)]
Definition: hostIf_tr69ReqHandler.h:172
hostIf_IP_Diagnostics_SpeedTest::handleGetMsg
int handleGetMsg(HOSTIF_MsgData_t *stMsgData)
This function is called when profile parameter needs to be read It gets the values of Enable_Speedtes...
Definition: Device_IP_Diagnostics_SpeedTest.cpp:98