diff --git a/.github/workflows/native-build.yml b/.github/workflows/native-build.yml
index b8c6054..f1d0bc0 100644
--- a/.github/workflows/native-build.yml
+++ b/.github/workflows/native-build.yml
@@ -32,5 +32,3 @@ jobs:
# Build component
chmod +x build_tools_workflows/cov_docker_script/build_native.sh
./build_tools_workflows/cov_docker_script/build_native.sh ./cov_docker_script/component_config.json "$(pwd)"
- env:
- GITHUB_TOKEN: ${{ secrets.RDKCM_RDKE }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ed3985..69bfcac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,11 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
-#### 2.8.1
+#### 2.9.0
+- RDKB-67262: Remove Github token from Native build [`#112`](https://github.com/rdkcentral/advanced-security/pull/112)
+- RDKB-66812 RDKB-66844 : Pause Network Intelligence while speedtest is running [`#103`](https://github.com/rdkcentral/advanced-security/pull/103)
+- RDKB-66811 RDKB-66952 : Support webconfig schema for opt-in / opt-out of Network Intelligence feature [`#109`](https://github.com/rdkcentral/advanced-security/pull/109)
- RDKB-66811 RDKB-66952 : Support end user opt-in / opt-out for Network Intelligence feature [`#107`](https://github.com/rdkcentral/advanced-security/pull/107)
- RDKB-66906 : Stop Network Intelligence service in start_adv_security.sh disable logic [`#108`](https://github.com/rdkcentral/advanced-security/pull/108)
- RDKB-66906 : Make cujo-ni service restart dependent on cujo-agent restart [`#104`](https://github.com/rdkcentral/advanced-security/pull/104)
@@ -48,5 +51,5 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- Create fossid_integration_stateless_diffscan_target_repo.yml [`#2`](https://github.com/rdkcentral/advanced-security/pull/2)
- Create CODEOWNERS file [`#1`](https://github.com/rdkcentral/advanced-security/pull/1)
- Import of source (stable2) [`55740fb`](https://github.com/rdkcentral/advanced-security/commit/55740fbcd9f7f71a3b57d286f6f9b6f919819b8b)
+- Add changelog for release 2.8.1 [`198b1d0`](https://github.com/rdkcentral/advanced-security/commit/198b1d0be656ce552639f3581abb278910a65991)
- updating the changelog.md file [`c155519`](https://github.com/rdkcentral/advanced-security/commit/c1555192bbe6c2e48ac278a70b3e2a3137cd5a38)
-- Add changelog for release 2.8.0 [`243972f`](https://github.com/rdkcentral/advanced-security/commit/243972f5e443e88e447b5fbd6fe8cd45b49457b0)
diff --git a/config/TR181-AdvSecurity.xml b/config/TR181-AdvSecurity.xml
index 0f8a3cd..f946b63 100644
--- a/config/TR181-AdvSecurity.xml
+++ b/config/TR181-AdvSecurity.xml
@@ -75,6 +75,7 @@
NetworkIntelligence_GetParamBoolValue
NetworkIntelligence_SetParamBoolValue
+ NetworkIntelligence_SetParamStringValue
@@ -83,6 +84,12 @@
bool
true
+
+ Data
+ string
+ string
+ true
+
diff --git a/source/AdvSecurityDml/Makefile.am b/source/AdvSecurityDml/Makefile.am
index 22d45a9..da1e1c3 100644
--- a/source/AdvSecurityDml/Makefile.am
+++ b/source/AdvSecurityDml/Makefile.am
@@ -26,7 +26,7 @@ hardware_platform = i686-linux-gnu
lib_LTLIBRARIES = libdmlasecurity.la
libdmlasecurity_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/source/AdvSecurityDml -I$(top_srcdir)/source/AdvSecuritySsp $(CPPFLAGS) -I$(top_srcdir)/../Utopia/source/include/sysevent -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus
libdmlasecurity_la_SOURCES = plugin_main.c cosa_adv_security_internal.c cosa_adv_security_dml.c cosa_adv_security_webconfig.c advsecurity_helpers.c advsecurity_param.c
-libdmlasecurity_la_LDFLAGS = -lccsp_common -lsyscfg -lsysevent -lwebconfig_framework -lmsgpackc -ltrower-base64 -lsecure_wrapper -lrbus -lev -lpthread $(SSP_LDFLAGS)
+libdmlasecurity_la_LDFLAGS = -lccsp_common -lsyscfg -lsysevent -lwebconfig_framework -lmsgpackc -ltrower-base64 -lsecure_wrapper -lrbus -lev -lpthread -ltelemetry_msgsender $(SSP_LDFLAGS)
if WIFI_DATA_COLLECTION
libdmlasecurity_la_CPPFLAGS += -DDML_SUPPORT -DWIFI_DATA_COLLECTION
@@ -36,5 +36,6 @@ endif
if NETWORK_INTELLIGENCE
libdmlasecurity_la_CPPFLAGS += -DDML_SUPPORT -DNETWORK_INTELLIGENCE
+libdmlasecurity_la_SOURCES += cosa_network_intelligence_webconfig.c networkintelligence_param.c
libdmlasecurity_la_LDFLAGS += -lwifi_webconfig
endif
\ No newline at end of file
diff --git a/source/AdvSecurityDml/advsecurity_param.c b/source/AdvSecurityDml/advsecurity_param.c
index b110899..c8b7bd6 100644
--- a/source/AdvSecurityDml/advsecurity_param.c
+++ b/source/AdvSecurityDml/advsecurity_param.c
@@ -114,15 +114,10 @@ const char* advsecuritydoc_strerror( int errnum )
int process_advsecurityparams( advsecurityparam_t *e, msgpack_object_map *map )
{
int left = map->size;
- /* Bits 0-4 are the mandatory legacy parameters. NetworkIntelligenceActivate
- * is optional for backward compatibility with the older 5-parameter schema;
- * when absent it retains its zeroed default. */
uint8_t objects_left = 0x1F;
msgpack_object_kv *p;
p = map->ptr;
- /* Iterate every entry: optional parameters may follow the last mandatory
- * one, so we must not stop early once objects_left reaches zero. */
- while( 0 < left-- )
+ while( (0 < left--) && (0 != objects_left) )
{
if( MSGPACK_OBJECT_STR == p->key.type )
{
@@ -153,12 +148,6 @@ int process_advsecurityparams( advsecurityparam_t *e, msgpack_object_map *map )
e->privacy_protection_activate = p->val.via.boolean;
objects_left &= ~(1 << 4);
}
- if( 0 == match(p, "NetworkIntelligenceActivate") )
- {
- e->network_intelligence_activate = p->val.via.boolean;
- e->network_intelligence_present = true;
- objects_left &= ~(1 << 5);
- }
}
}
p++;
diff --git a/source/AdvSecurityDml/advsecurity_param.h b/source/AdvSecurityDml/advsecurity_param.h
index ff7b016..9489d3a 100644
--- a/source/AdvSecurityDml/advsecurity_param.h
+++ b/source/AdvSecurityDml/advsecurity_param.h
@@ -31,11 +31,6 @@ typedef struct
bool safebrowsing_enable;
bool parental_control_activate;
bool privacy_protection_activate;
- bool network_intelligence_activate;
- /* False when the payload used the older 5-parameter schema that omits
- * NetworkIntelligenceActivate. In that case network_intelligence_activate
- * carries no meaning and must not be applied. */
- bool network_intelligence_present;
} advsecurityparam_t;
diff --git a/source/AdvSecurityDml/cosa_adv_security_dml.c b/source/AdvSecurityDml/cosa_adv_security_dml.c
index e8c01ad..1ffc3ab 100644
--- a/source/AdvSecurityDml/cosa_adv_security_dml.c
+++ b/source/AdvSecurityDml/cosa_adv_security_dml.c
@@ -21,6 +21,10 @@
#include "ansc_platform.h"
#include "cosa_adv_security_internal.h"
#include "cosa_adv_security_webconfig.h"
+#ifdef NETWORK_INTELLIGENCE
+#include "cosa_network_intelligence_webconfig.h"
+#include "networkintelligence_param.h"
+#endif
#include "syslog.h"
#include "ccsp_trace.h"
#include "msgpack.h"
@@ -573,7 +577,7 @@ AdvancedSecurity_SetParamStringValue
errno_t rc = -1;
int ind = -1;
- if(ParamName == NULL)
+ if((ParamName == NULL) || (pString == NULL))
return FALSE;
/* check the parameter name and set the corresponding value */
rc = strcmp_s("Data", strlen("Data"), ParamName, &ind);
@@ -592,10 +596,30 @@ AdvancedSecurity_SetParamStringValue
msgpack_unpack_return unpack_ret;
decodeMsgSize = b64_get_decoded_buffer_size(strlen(pString));
+ if(decodeMsgSize <= 0)
+ {
+ CcspTraceError(("Invalid base64 decoded buffer size %d\n", decodeMsgSize));
+ return FALSE;
+ }
+
decodeMsg = (char *) AnscAllocateMemory(sizeof(char) * decodeMsgSize);
+ if(decodeMsg == NULL)
+ {
+ CcspTraceError(("decodeMsg AnscAllocateMemory failed\n"));
+ return FALSE;
+ }
+
size = b64_decode((uint8_t *) pString, strlen(pString),(uint8_t *) decodeMsg );
CcspTraceInfo(("base64 decoded data contains %d bytes\n",size));
+ if((size <= 0) || (size > decodeMsgSize))
+ {
+ CcspTraceError(("base64 decode failed, invalid length %d (buffer %d)\n", size, decodeMsgSize));
+ AnscFreeMemory(decodeMsg);
+ decodeMsg = NULL;
+ return FALSE;
+ }
+
msgpack_zone_init(&mempool, 2048);
unpack_ret = msgpack_unpack(decodeMsg, size, NULL, &mempool, &deserialized);
switch(unpack_ret)
@@ -629,23 +653,14 @@ AdvancedSecurity_SetParamStringValue
err = errno;
CcspTraceInfo(("errno: %s\n", advsecuritydoc_strerror(err)));
- if(ad != NULL)
+ if(ad != NULL && ad->param != NULL && ad->subdoc_name != NULL)
{
CcspTraceInfo(("ad->subdoc_name is %s\n", ad->subdoc_name));
CcspTraceInfo(("ad->version is %lu\n", (long)ad->version));
CcspTraceInfo(("ad->transaction_id %lu\n",(long) ad->transaction_id));
- if (ad->param->network_intelligence_present)
- {
- CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d], network_intelligence_activate[%d]\n",
- ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable,
- ad->param->parental_control_activate,ad->param->privacy_protection_activate,ad->param->network_intelligence_activate));
- }
- else
- {
- CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n",
- ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable,
- ad->param->parental_control_activate,ad->param->privacy_protection_activate));
- }
+ CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n",
+ ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable,
+ ad->param->parental_control_activate,ad->param->privacy_protection_activate));
execData *execDataAdvsec = NULL ;
execDataAdvsec = (execData*) AnscAllocateMemory (sizeof(execData));
@@ -691,6 +706,17 @@ AdvancedSecurity_SetParamStringValue
ret_val = FALSE;
}
}
+ else if(ad != NULL)
+ {
+ CcspTraceError(("advsecuritydoc missing mandatory fields\n"));
+ advsecuritydoc_destroy(ad);
+ ret_val = FALSE;
+ }
+ else
+ {
+ CcspTraceError(("advsecuritydoc_convert failed\n"));
+ ret_val = FALSE;
+ }
}
else
{
@@ -4214,6 +4240,196 @@ NetworkIntelligence_RFC_SetParamUlongValue
CcspTraceWarning(("Unsupported parameter '%s'\n", ParamName));
return FALSE;
}
+
+/**********************************************************************
+
+ caller: owner of this object
+
+ prototype:
+
+ BOOL
+ NetworkIntelligence_SetParamStringValue
+ (
+ ANSC_HANDLE hInsContext,
+ char* ParamName,
+ char* pString
+ );
+
+ description:
+
+ This function is called to set string parameter value;
+
+ argument: ANSC_HANDLE hInsContext,
+ The instance handle;
+
+ char* ParamName,
+ The parameter name;
+
+ char* pString
+ The updated string value;
+
+ return: TRUE if succeeded.
+
+**********************************************************************/
+BOOL
+NetworkIntelligence_SetParamStringValue
+ (
+ ANSC_HANDLE hInsContext,
+ char* ParamName,
+ char* pString
+ )
+{
+ UNREFERENCED_PARAMETER(hInsContext);
+ errno_t rc = -1;
+ int ind = -1;
+
+ if(ParamName == NULL || pString == NULL)
+ return FALSE;
+
+ /* check the parameter name and set the corresponding value */
+ rc = strcmp_s("Data", strlen("Data"), ParamName, &ind);
+ ERR_CHK(rc);
+ if((rc == EOK) && (!ind))
+ {
+ networkintelligencedoc_t *nd = NULL;
+ int err;
+ char * decodeMsg = NULL;
+ int decodeMsgSize = 0;
+ int size = 0;
+ BOOL ret_val = TRUE;
+
+ msgpack_zone mempool;
+ msgpack_object deserialized;
+ msgpack_unpack_return unpack_ret;
+
+ decodeMsgSize = b64_get_decoded_buffer_size(strlen(pString));
+ if (decodeMsgSize <= 0)
+ {
+ CcspTraceError(("Invalid base64 decoded buffer size %d\n", decodeMsgSize));
+ return FALSE;
+ }
+
+ decodeMsg = (char *) AnscAllocateMemory(sizeof(char) * decodeMsgSize);
+ if (decodeMsg == NULL)
+ {
+ CcspTraceError(("decodeMsg AnscAllocateMemory failed\n"));
+ return FALSE;
+ }
+ size = b64_decode((uint8_t *) pString, strlen(pString),(uint8_t *) decodeMsg );
+ CcspTraceInfo(("base64 decoded data contains %d bytes\n",size));
+
+ if ((size <= 0) || (size > decodeMsgSize))
+ {
+ CcspTraceError(("base64 decode failed, invalid length %d (buffer %d)\n", size, decodeMsgSize));
+ AnscFreeMemory(decodeMsg);
+ decodeMsg = NULL;
+ return FALSE;
+ }
+
+ msgpack_zone_init(&mempool, 2048);
+ unpack_ret = msgpack_unpack(decodeMsg, size, NULL, &mempool, &deserialized);
+ switch(unpack_ret)
+ {
+ case MSGPACK_UNPACK_SUCCESS:
+ CcspTraceInfo(("MSGPACK_UNPACK_SUCCESS :%d\n",unpack_ret));
+ break;
+ case MSGPACK_UNPACK_EXTRA_BYTES:
+ CcspTraceInfo(("MSGPACK_UNPACK_EXTRA_BYTES :%d\n",unpack_ret));
+ break;
+ case MSGPACK_UNPACK_CONTINUE:
+ CcspTraceInfo(("MSGPACK_UNPACK_CONTINUE :%d\n",unpack_ret));
+ break;
+ case MSGPACK_UNPACK_PARSE_ERROR:
+ CcspTraceError(("MSGPACK_UNPACK_PARSE_ERROR :%d\n",unpack_ret));
+ break;
+ case MSGPACK_UNPACK_NOMEM_ERROR:
+ CcspTraceError(("MSGPACK_UNPACK_NOMEM_ERROR :%d\n",unpack_ret));
+ break;
+ default:
+ CcspTraceError(("Message Pack decode failed with error: %d\n", unpack_ret));
+ }
+ msgpack_zone_destroy(&mempool);
+
+ CcspTraceInfo(("---------------End of b64 decode--------------\n"));
+
+ if(unpack_ret == MSGPACK_UNPACK_SUCCESS)
+ {
+ CcspTraceInfo(("Msg unpack success\n"));
+ nd = networkintelligencedoc_convert(decodeMsg, size);//used to process the incoming msgobject
+ err = errno;
+ CcspTraceInfo(("errno: %s\n", networkintelligencedoc_strerror(err)));
+
+ if(nd != NULL && nd->param != NULL && nd->subdoc_name != NULL)
+ {
+ CcspTraceInfo(("nd->subdoc_name is %s\n", nd->subdoc_name));
+ CcspTraceInfo(("nd->version is %lu\n", (long)nd->version));
+ CcspTraceInfo(("nd->transaction_id %lu\n",(long) nd->transaction_id));
+ CcspTraceInfo(("network_intelligence_activate:[%d]\n",
+ nd->param->network_intelligence_activate));
+
+ execData *execDataNi = NULL ;
+ execDataNi = (execData*) AnscAllocateMemory (sizeof(execData));
+
+ if ( execDataNi != NULL )
+ {
+ rc = memset_s(execDataNi, sizeof(execData), 0, sizeof(execData));
+ ERR_CHK(rc);
+
+ execDataNi->txid = nd->transaction_id;
+ execDataNi->version = nd->version;
+ execDataNi->numOfEntries = 1;
+
+ rc = strcpy_s(execDataNi->subdoc_name, sizeof(execDataNi->subdoc_name), nd->subdoc_name);
+ if(rc != EOK)
+ {
+ ERR_CHK(rc);
+ AnscFreeMemory(execDataNi);
+ execDataNi = NULL;
+ networkintelligencedoc_destroy(nd);
+ AnscFreeMemory(decodeMsg);
+ decodeMsg = NULL;
+ return FALSE;
+ }
+
+ execDataNi->user_data = (void*) nd;
+ execDataNi->calcTimeout = NULL ;
+ execDataNi->executeBlobRequest = ni_webconfig_process_request;
+ execDataNi->rollbackFunc = ni_webconfig_rollback;
+ execDataNi->freeResources = ni_webconfig_free_resources;
+ PushBlobRequest(execDataNi);
+ CcspTraceInfo(("PushBlobRequest complete\n"));
+ }
+ else
+ {
+ CcspTraceError(("execData AnscAllocateMemory failed\n"));
+ networkintelligencedoc_destroy(nd);
+ ret_val = FALSE;
+ }
+ }
+ else
+ {
+ CcspTraceError(("Failed to convert networkintelligence subdoc\n"));
+ networkintelligencedoc_destroy(nd);
+ ret_val = FALSE;
+ }
+ }
+ else
+ {
+ CcspTraceError(("Failed to unpack msgpack\n"));
+ ret_val = FALSE;
+ }
+
+ if ( decodeMsg )
+ {
+ AnscFreeMemory (decodeMsg);
+ decodeMsg = NULL;
+ }
+ return ret_val;
+ }
+
+ CcspTraceWarning(("Unsupported parameter '%s'\n", ParamName));
+ return FALSE;
+}
#endif // NETWORK_INTELLIGENCE
/***********************************************************************
diff --git a/source/AdvSecurityDml/cosa_adv_security_dml.h b/source/AdvSecurityDml/cosa_adv_security_dml.h
index 94b878a..3196f39 100644
--- a/source/AdvSecurityDml/cosa_adv_security_dml.h
+++ b/source/AdvSecurityDml/cosa_adv_security_dml.h
@@ -631,6 +631,23 @@ NetworkIntelligence_RFC_SetParamUlongValue
char* ParamName,
ULONG uValue
);
+
+/***********************************************************************
+
+ APIs for Object:
+
+ X_RDKCENTRAL-COM_NetworkIntelligence.
+
+ * NetworkIntelligence_SetParamStringValue
+
+***********************************************************************/
+BOOL
+NetworkIntelligence_SetParamStringValue
+ (
+ ANSC_HANDLE hInsContext,
+ char* ParamName,
+ char* pString
+ );
#endif // NETWORK_INTELLIGENCE
/***********************************************************************
diff --git a/source/AdvSecurityDml/cosa_adv_security_internal.c b/source/AdvSecurityDml/cosa_adv_security_internal.c
index 389adbb..0564b00 100644
--- a/source/AdvSecurityDml/cosa_adv_security_internal.c
+++ b/source/AdvSecurityDml/cosa_adv_security_internal.c
@@ -33,6 +33,9 @@
#include "cosa_adv_security_internal.h"
#include "cosa_adv_security_dml.h"
#include "cosa_adv_security_webconfig.h"
+#ifdef NETWORK_INTELLIGENCE
+#include "cosa_network_intelligence_webconfig.h"
+#endif
#include "ccsp_psm_helper.h"
#include
#include
@@ -66,6 +69,10 @@
#define ADVSEC_SYSEVENT_CURRENT_WAN_IFNAME_EVENT "current_wan_ifname"
#define LEVL_DML "Device.WiFi.Levl"
+#define SPEEDTEST_STATUS_DML "Device.IP.Diagnostics.X_RDKCENTRAL-COM_SpeedTest.Status"
+#define SPEEDTEST_TIMEOUT_DML "Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"
+#define ADVSEC_NETWORKINTELLIGENCE_ENABLED_PATH "/tmp/advsec_networkintelligence_enabled"
+#define CUJONICLI_SET_QOSD_ENABLE_CMD "/usr/bin/cujo-ni-cli '{\"method\":\"set_configs\", \"configs\": {\"cujoniqos.daemon.enable\": %d}}' &"
#define ADVSEC_WAIT_FOR_TIMEOUT (60 * 60)
#define MAX_VALUE 32
@@ -152,6 +159,11 @@ static char *g_RaptrEnabled = "Adv_RaptrRFCEnable";
#ifdef NETWORK_INTELLIGENCE
static char *g_AdvSecNetworkIntelligenceEnabled = "Adv_AdvSecNetworkIntelligenceRFCEnable";
static char *g_NetworkIntelligenceMemoryLimit = "Advsecurity_NetworkIntelligenceMemoryLimit";
+STATIC pthread_mutex_t ni_speedtest_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t ni_speedtest_cond = PTHREAD_COND_INITIALIZER;
+static struct timespec ni_speedtest_timeout;
+STATIC BOOL ni_speedtest_thread_running = FALSE;
+static BOOL ni_speedtest_wake_early = FALSE;
static char *g_NetworkIntelligenceActivate = "Adv_AdvSecNetworkIntelligenceActivate";
#endif
#ifdef WIFI_DATA_COLLECTION
@@ -431,6 +443,215 @@ static void eventReceiveHandler(
}
#endif
+#ifdef NETWORK_INTELLIGENCE
+static BOOL is_ni_enabled_and_activated(void)
+{
+ struct stat st;
+
+ if (stat(ADVSEC_NETWORKINTELLIGENCE_ENABLED_PATH, &st) != 0)
+ {
+ return FALSE;
+ }
+ if (stat(ADVSEC_NETWORKINTELLIGENCE_ACTIVATED_PATH, &st) != 0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL ni_qosd_enable(BOOL enable)
+{
+ errno_t rc;
+
+ rc = v_secure_system(CUJONICLI_SET_QOSD_ENABLE_CMD, enable ? 1 : 0);
+ if (!WIFEXITED(rc) || WEXITSTATUS(rc) != 0)
+ {
+ CcspTraceError(("%s: cujo-ni-cli set_configs cujoniqos.daemon.enable=%d failed, rc=%d\n",
+ __FUNCTION__, enable ? 1 : 0, WEXITSTATUS(rc)));
+ return FALSE;
+ }
+ if (enable)
+ {
+ t2_event_d("SYS_INFO_CUJO_NI_resume", 1);
+ }
+ else
+ {
+ t2_event_d("SYS_INFO_CUJO_NI_pause", 1);
+ }
+ return TRUE;
+}
+
+static void *ni_speedtest_handler(void *arg)
+{
+ int waitStatus = 0;
+ BOOL timedOut;
+
+ (void)arg;
+
+ pthread_detach(pthread_self());
+
+ pthread_mutex_lock(&ni_speedtest_mutex);
+ if (!ni_qosd_enable(FALSE))
+ {
+ CcspTraceError(("%s: failed to pause Network Intelligence for speedtest\n", __FUNCTION__));
+ ni_speedtest_thread_running = FALSE;
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+ return NULL;
+ }
+
+ while (!ni_speedtest_wake_early && waitStatus != ETIMEDOUT)
+ {
+ waitStatus = pthread_cond_timedwait(&ni_speedtest_cond, &ni_speedtest_mutex, &ni_speedtest_timeout);
+ if (waitStatus != 0 && waitStatus != ETIMEDOUT)
+ {
+ CcspTraceError(("%s: pthread_cond_timedwait failed, error=%d\n", __FUNCTION__, waitStatus));
+ break;
+ }
+ }
+ timedOut = (waitStatus == ETIMEDOUT);
+ ni_speedtest_wake_early = FALSE;
+
+ if (timedOut)
+ {
+ CcspTraceWarning(("%s: speedtest timeout expired, resuming Network Intelligence\n", __FUNCTION__));
+ t2_event_d("IMP_CUJO_NI_SubscriberUnPauseTimeOut", 1);
+ }
+ if (!ni_qosd_enable(TRUE))
+ {
+ CcspTraceError(("%s: failed to resume Network Intelligence after speedtest\n", __FUNCTION__));
+ }
+
+ ni_speedtest_thread_running = FALSE;
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+
+ return NULL;
+}
+
+static BOOL ni_speedtest_trigger(uint32_t timeout)
+{
+ struct timespec ni_resume_timeout;
+ pthread_t tid;
+ int err;
+
+ if (clock_gettime(CLOCK_REALTIME, &ni_resume_timeout) != 0)
+ {
+ CcspTraceError(("%s: clock_gettime failed, errno=%d\n", __FUNCTION__, errno));
+ return FALSE;
+ }
+ ni_resume_timeout.tv_sec += timeout;
+
+ pthread_mutex_lock(&ni_speedtest_mutex);
+ if (ni_speedtest_thread_running)
+ {
+ ni_speedtest_timeout = ni_resume_timeout;
+ pthread_cond_signal(&ni_speedtest_cond);
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+ CcspTraceInfo(("%s: Network Intelligence already paused for speedtest, refreshed timeout\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ ni_speedtest_timeout = ni_resume_timeout;
+
+ ni_speedtest_wake_early = FALSE;
+ ni_speedtest_thread_running = TRUE;
+
+ err = pthread_create(&tid, NULL, ni_speedtest_handler, NULL);
+ if (err != 0)
+ {
+ ni_speedtest_thread_running = FALSE;
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+ CcspTraceError(("%s: failed to create speedtest timer thread, error=%d\n", __FUNCTION__, err));
+ return FALSE;
+ }
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+ return TRUE;
+}
+
+static void ni_speedtest_complete(void)
+{
+ pthread_mutex_lock(&ni_speedtest_mutex);
+ if (ni_speedtest_thread_running)
+ {
+ ni_speedtest_wake_early = TRUE;
+ pthread_cond_signal(&ni_speedtest_cond);
+ }
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+}
+
+static BOOL speedtestGetTimeout(uint32_t *timeout)
+{
+ rbusValue_t value = NULL;
+ int ret;
+
+ ret = rbus_get(rbus_handle, SPEEDTEST_TIMEOUT_DML, &value);
+ if (ret != RBUS_ERROR_SUCCESS)
+ {
+ CcspTraceError(("%s: rbus_get failed for %s, error=%d\n", __FUNCTION__, SPEEDTEST_TIMEOUT_DML, ret));
+ if (value != NULL)
+ {
+ rbusValue_Release(value);
+ }
+ return FALSE;
+ }
+
+ *timeout = rbusValue_GetUInt32(value);
+ rbusValue_Release(value);
+
+ return TRUE;
+}
+
+STATIC void speedtestEventReceiveHandler(
+ rbusHandle_t handle,
+ rbusEvent_t const* event,
+ rbusEventSubscription_t* subscription)
+{
+ rbusValue_t value;
+ uint32_t status;
+ uint32_t timeout;
+
+ (void)handle;
+ (void)subscription;
+
+ value = rbusObject_GetValue(event->data, NULL);
+ if (value == NULL)
+ {
+ CcspTraceError(("SpeedTest status event has no value\n"));
+ return;
+ }
+
+ status = rbusValue_GetUInt32(value);
+ CcspTraceInfo(("%s: speedtest status event received, status=%u\n", __FUNCTION__, status));
+
+ if (!is_ni_enabled_and_activated())
+ {
+ CcspTraceInfo(("%s: Network Intelligence is disabled or not activated, skipping speedtest event\n", __FUNCTION__));
+ return;
+ }
+
+ if (status == ST_TR181_STATUS_STARTING)
+ {
+ if (!speedtestGetTimeout(&timeout))
+ {
+ CcspTraceError(("%s: failed to get speedtest unpause timeout, Network Intelligence will not be paused\n", __FUNCTION__));
+ return;
+ }
+ if (timeout == 0)
+ {
+ CcspTraceInfo(("%s: speedtest unpause timeout is 0, skipping Network Intelligence pause\n", __FUNCTION__));
+ return;
+ }
+ if (!ni_speedtest_trigger(timeout))
+ {
+ CcspTraceError(("%s: Network Intelligence speedtest trigger failed, Network Intelligence will not be paused\n", __FUNCTION__));
+ }
+ }
+ else if (status == ST_TR181_STATUS_COMPLETE)
+ {
+ ni_speedtest_complete();
+ }
+}
+#endif
+
#if defined(WIFI_DATA_COLLECTION) || defined(NETWORK_INTELLIGENCE)
static int touch_file(const char *filepath)
{
@@ -1584,6 +1805,14 @@ CosaSecurityInitialize
CcspTraceError(("AdvSecurityEventConsumer: rbusEvent_Subscribe %s failed: %d\n", LEVL_DML, ret));
return ANSC_STATUS_FAILURE;
}
+#endif
+#ifdef NETWORK_INTELLIGENCE
+ ret = rbusEvent_Subscribe(rbus_handle, SPEEDTEST_STATUS_DML, speedtestEventReceiveHandler, NULL, 0);
+ if(ret != RBUS_ERROR_SUCCESS)
+ {
+ CcspTraceError(("AdvSecurityEventConsumer: rbusEvent_Subscribe %s failed: %d\n", SPEEDTEST_STATUS_DML, ret));
+ return ANSC_STATUS_FAILURE;
+ }
#endif
return returnStatus;
}
@@ -2568,24 +2797,6 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature)
if ( returnStatus != ANSC_STATUS_SUCCESS )
return SYSCFG_FAILURE;
-#ifdef NETWORK_INTELLIGENCE
- BOOL prev_ni_state = FALSE;
- if (feature->network_intelligence_present)
- {
- prev_ni_state = g_pAdvSecAgent->pNetworkIntelligence->bActivate;
- if (feature->network_intelligence_activate != g_pAdvSecAgent->pNetworkIntelligence->bActivate)
- {
- returnStatus = CosaSetSysCfgUlong(g_NetworkIntelligenceActivate, feature->network_intelligence_activate);
- if ( returnStatus == ANSC_STATUS_SUCCESS )
- {
- g_pAdvSecAgent->pNetworkIntelligence->bActivate = feature->network_intelligence_activate;
- }
- else
- return SYSCFG_FAILURE;
- }
- }
-#endif // NETWORK_INTELLIGENCE
-
if ( feature->fingerprint_enable != g_pAdvSecAgent->bEnable )
{
if ( feature->fingerprint_enable )
@@ -2598,57 +2809,6 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature)
}
else
{
-#ifdef NETWORK_INTELLIGENCE
- if (feature->network_intelligence_present &&
- feature->network_intelligence_activate != prev_ni_state)
- {
- if (g_pAdvSecAgent->pAdvNetworkIntelligence_RFC->bEnable)
- {
- if (feature->network_intelligence_activate)
- {
- // -activateNI_R will restart cujo-agent and enable cujo-ni service
- ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -activateNI_R &");
- if(ret != 0)
- {
- CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret));
- }
- }
- else
- {
- // -deactivateNI_R will restart cujo-agent and disable cujo-ni service
- ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -deactivateNI_R &");
- if(ret != 0)
- {
- CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret));
- }
- }
- // -configure_features not required since cujo-agent restart will configure other features
- return BLOB_EXEC_SUCCESS;
- }
- else
- {
- CcspTraceWarning(("%s: cannot activate NetworkIntelligence feature due to RFC is disabled\n", __FUNCTION__));
- if (feature->network_intelligence_activate)
- {
- // -activateNI will touch /tmp/advsec_networkintelligence_activated file, log only if RFC is enabled
- ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -activateNI &");
- if(ret != 0)
- {
- CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret));
- }
- }
- else
- {
- // -deactivateNI will remove /tmp/advsec_networkintelligence_activated file, log only if RFC is enabled
- ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -deactivateNI &");
- if(ret != 0)
- {
- CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret));
- }
- }
- }
- }
-#endif // NETWORK_INTELLIGENCE
ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -configure_features &");
if(ret != 0)
{
@@ -2660,6 +2820,40 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature)
return BLOB_EXEC_SUCCESS;
}
+#ifdef NETWORK_INTELLIGENCE
+int ni_webconfig_handle_blob(networkintelligenceparam_t *feature)
+{
+ ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS;
+
+ CcspTraceInfo(("Entering %s\n", __FUNCTION__));
+
+ if ( g_pAdvSecAgent == NULL || g_pAdvSecAgent->pNetworkIntelligence == NULL ||
+ g_pAdvSecAgent->pAdvNetworkIntelligence_RFC == NULL )
+ {
+ CcspTraceError(("%s: NetworkIntelligence datamodel is not initialized\n", __FUNCTION__));
+ return ADVSEC_FAILURE;
+ }
+
+ if ( feature->network_intelligence_activate == g_pAdvSecAgent->pNetworkIntelligence->bActivate )
+ {
+ CcspTraceInfo(("%s: NetworkIntelligence activate already set to %d\n",
+ __FUNCTION__, feature->network_intelligence_activate));
+ return BLOB_EXEC_SUCCESS;
+ }
+
+ if ( feature->network_intelligence_activate )
+ returnStatus = CosaNetworkIntelligenceActivate(g_pAdvSecAgent->pNetworkIntelligence);
+ else
+ returnStatus = CosaNetworkIntelligenceDeactivate(g_pAdvSecAgent->pNetworkIntelligence);
+
+ if ( returnStatus != ANSC_STATUS_SUCCESS )
+ return SYSCFG_FAILURE;
+
+ CcspTraceInfo(("Done %s\n", __FUNCTION__));
+ return BLOB_EXEC_SUCCESS;
+}
+#endif // NETWORK_INTELLIGENCE
+
ANSC_STATUS CosaAdvSecGetLoggingPeriod()
{
ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS;
diff --git a/source/AdvSecurityDml/cosa_adv_security_internal.h b/source/AdvSecurityDml/cosa_adv_security_internal.h
index d8cacd4..2389bc1 100644
--- a/source/AdvSecurityDml/cosa_adv_security_internal.h
+++ b/source/AdvSecurityDml/cosa_adv_security_internal.h
@@ -31,6 +31,7 @@
#include
#include "ansc_platform.h"
#include "ansc_string_util.h"
+#include
#define ADVSEC_MIN_LOG_TIMEOUT (60 * 1)
#define ADVSEC_MAX_LOG_TIMEOUT (60 * 48)
@@ -43,6 +44,8 @@
#define ADVSEC_LogLevel_VERBOSE 4
#define BUFLEN_1024 1024
#define PARTNER_REDIRECTORURL_PARAMNAME "Device.DeviceInfo.X_RDKCENTRAL-COM_Syndication.AdvsecRedirectorURL"
+#define ST_TR181_STATUS_STARTING 1
+#define ST_TR181_STATUS_COMPLETE 5
typedef enum {
ADVSEC_SAFEBROWSING=0,
diff --git a/source/AdvSecurityDml/cosa_adv_security_webconfig.c b/source/AdvSecurityDml/cosa_adv_security_webconfig.c
index 4cc4afd..38d4625 100644
--- a/source/AdvSecurityDml/cosa_adv_security_webconfig.c
+++ b/source/AdvSecurityDml/cosa_adv_security_webconfig.c
@@ -87,7 +87,11 @@ int advsec_webconfig_set_blobversion(char* subdoc, uint32_t version)
void advsec_webconfig_init()
{
errno_t rc = -1;
- char *sub_docs[SUBDOC_COUNT+1]= {ADVSEC_WEBCONFIG_SUBDOC_NAME,(char *) 0 };
+ char *sub_docs[SUBDOC_COUNT+1]= {ADVSEC_WEBCONFIG_SUBDOC_NAME,
+#ifdef NETWORK_INTELLIGENCE
+ NI_WEBCONFIG_SUBDOC_NAME,
+#endif
+ (char *) 0 };
blobRegInfo *blobData;
@@ -151,18 +155,9 @@ pErr advsec_webconfig_process_request(void *Data)
CcspTraceInfo(("%s: advsec->subdoc_name is %s\n", __FUNCTION__, advsec->subdoc_name));
CcspTraceInfo(("%s: advsec->version is %lu\n", __FUNCTION__, (long)advsec->version));
CcspTraceInfo(("%s: advsec->transaction_id %lu\n",__FUNCTION__, (long) advsec->transaction_id));
- if (advsec->param->network_intelligence_present)
- {
- CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d], network_intelligence_activate[%d]\n",
- __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable,
- advsec->param->parental_control_activate, advsec->param->privacy_protection_activate, advsec->param->network_intelligence_activate));
- }
- else
- {
- CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n",
- __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable,
- advsec->param->parental_control_activate, advsec->param->privacy_protection_activate));
- }
+ CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n",
+ __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable,
+ advsec->param->parental_control_activate, advsec->param->privacy_protection_activate));
rc = strcmp_s(ADVSEC_WEBCONFIG_SUBDOC_NAME, strlen(ADVSEC_WEBCONFIG_SUBDOC_NAME), advsec->subdoc_name, &ind);
ERR_CHK(rc);
@@ -207,7 +202,7 @@ pErr advsec_webconfig_process_request(void *Data)
int advsec_webconfig_rollback()
{
// return 0 to notify framework when rollback is success
- CcspTraceInfo((" Entering %s \n",__FUNCTION__));
+ CcspTraceInfo(("Entering %s\n", __FUNCTION__));
int ret = 0;
@@ -220,7 +215,7 @@ int advsec_webconfig_rollback()
void advsec_webconfig_free_resources(void *arg)
{
- CcspTraceInfo((" Entering %s \n",__FUNCTION__));
+ CcspTraceInfo(("Entering %s\n", __FUNCTION__));
execData *blob_exec_data = (execData*) arg;
/* CID 158652: Dereference before null check */
diff --git a/source/AdvSecurityDml/cosa_adv_security_webconfig.h b/source/AdvSecurityDml/cosa_adv_security_webconfig.h
index a78e9bc..3bf79c0 100644
--- a/source/AdvSecurityDml/cosa_adv_security_webconfig.h
+++ b/source/AdvSecurityDml/cosa_adv_security_webconfig.h
@@ -31,8 +31,15 @@
#include "webconfig_framework.h"
#include "advsecurity_param.h"
+#ifdef NETWORK_INTELLIGENCE
+#include "networkintelligence_param.h"
+#endif
+#ifdef NETWORK_INTELLIGENCE
+#define SUBDOC_COUNT 2
+#else
#define SUBDOC_COUNT 1
+#endif
#define BLOCK_SIZE 32
diff --git a/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c
new file mode 100644
index 0000000..936a7fb
--- /dev/null
+++ b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright 2016 Comcast Cable Communications Management, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
+*/
+
+#include "cosa_network_intelligence_webconfig.h"
+#include "webconfig_framework.h"
+#include
+#include
+#include "safec_lib_common.h"
+
+/* CallBack API to execute Network Intelligence Blob request */
+pErr ni_webconfig_process_request(void *Data)
+{
+ pErr execRetVal = NULL;
+ errno_t rc = -1;
+ int ind = -1;
+
+ execRetVal = (pErr) AnscAllocateMemory (sizeof(Err));
+ if (execRetVal == NULL )
+ {
+ CcspTraceError(("%s : AnscAllocateMemory failed\n",__FUNCTION__));
+ return execRetVal;
+ }
+
+ rc = memset_s(execRetVal, sizeof(Err), 0, sizeof(Err));
+ ERR_CHK(rc);
+
+ execRetVal->ErrorCode = BLOB_EXEC_SUCCESS;
+
+ networkintelligencedoc_t *ni = (networkintelligencedoc_t *) Data ;
+ if( ni != NULL && ni->subdoc_name != NULL && ni->param != NULL )
+ {
+ CcspTraceInfo(("%s: ni->subdoc_name is %s\n", __FUNCTION__, ni->subdoc_name));
+ CcspTraceInfo(("%s: ni->version is %lu\n", __FUNCTION__, (long)ni->version));
+ CcspTraceInfo(("%s: ni->transaction_id %lu\n",__FUNCTION__, (long) ni->transaction_id));
+ CcspTraceInfo(("%s: network_intelligence_activate[%d]\n",
+ __FUNCTION__, ni->param->network_intelligence_activate));
+
+ rc = strcmp_s(NI_WEBCONFIG_SUBDOC_NAME, strlen(NI_WEBCONFIG_SUBDOC_NAME), ni->subdoc_name, &ind);
+ ERR_CHK(rc);
+ if((rc == EOK) && (ind == 0))
+ {
+ int ret = ni_webconfig_handle_blob(ni->param);
+
+ CcspTraceInfo(("%s: Return value = %d\n",__FUNCTION__, ret));
+
+ if ( ret == BLOB_EXEC_SUCCESS )
+ {
+ if ( ni->param->network_intelligence_activate == TRUE )
+ {
+ strncpy(execRetVal->ErrorMsg,"activated",sizeof(execRetVal->ErrorMsg)-1);
+ }
+ else
+ {
+ strncpy(execRetVal->ErrorMsg,"deactivated",sizeof(execRetVal->ErrorMsg)-1);
+ }
+ }
+ else
+ {
+ execRetVal->ErrorCode = ret;
+ }
+ }
+ else
+ {
+ CcspTraceWarning(("%s: Received an invalid subdoc: %s\n",__FUNCTION__, ni->subdoc_name));
+ execRetVal->ErrorCode = SUBDOC_NOT_SUPPORTED;
+ }
+ }
+ else
+ {
+ CcspTraceWarning(("%s: Received null subdoc blob\n",__FUNCTION__));
+ execRetVal->ErrorCode = NULL_BLOB_EXEC_POINTER;
+ }
+
+ return execRetVal;
+}
+
+/* Callback function to rollback when Network Intelligence blob execution fails */
+int ni_webconfig_rollback()
+{
+ // return 0 to notify framework when rollback is success
+ CcspTraceInfo(("Entering %s\n", __FUNCTION__));
+
+ int ret = 0;
+
+ CcspTraceWarning(("%s: Something went wrong while processing webconfig request\n",__FUNCTION__));
+
+ return ret ;
+}
+
+/* Callback function to free webconfig resources */
+void ni_webconfig_free_resources(void *arg)
+{
+ CcspTraceInfo(("Entering %s\n", __FUNCTION__));
+ execData *blob_exec_data = (execData*) arg;
+
+ if ( blob_exec_data != NULL )
+ {
+ networkintelligencedoc_t *nd = (networkintelligencedoc_t *) blob_exec_data->user_data ;
+
+ if ( nd != NULL )
+ {
+ networkintelligencedoc_destroy(nd);
+ }
+
+ AnscFreeMemory (blob_exec_data);
+ blob_exec_data = NULL ;
+ }
+}
diff --git a/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h
new file mode 100644
index 0000000..dd65a95
--- /dev/null
+++ b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright 2016 Comcast Cable Communications Management, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
+*/
+
+#ifndef _COSA_NETWORK_INTELLIGENCE_WEBCONFIG_H
+#define _COSA_NETWORK_INTELLIGENCE_WEBCONFIG_H
+
+#include
+#include
+#include
+#include
+#include "ansc_status.h"
+#include "ansc_platform.h"
+
+#include "webconfig_framework.h"
+#include "networkintelligence_param.h"
+
+pErr ni_webconfig_process_request(void *Data);
+int ni_webconfig_rollback();
+void ni_webconfig_free_resources(void *arg);
+int ni_webconfig_handle_blob(networkintelligenceparam_t *feature);
+
+#endif
diff --git a/source/AdvSecurityDml/networkintelligence_param.c b/source/AdvSecurityDml/networkintelligence_param.c
new file mode 100644
index 0000000..bbadc66
--- /dev/null
+++ b/source/AdvSecurityDml/networkintelligence_param.c
@@ -0,0 +1,196 @@
+/*
+ *
+ * Copyright 2016 Comcast Cable Communications Management, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
+*/
+
+#include
+#include
+#include
+#include
+#include "ccsp_trace.h"
+#include "advsecurity_helpers.h"
+#include "networkintelligence_param.h"
+#include "ansc_platform.h"
+
+/*----------------------------------------------------------------------------*/
+/* Macros */
+/*----------------------------------------------------------------------------*/
+/* none */
+/*----------------------------------------------------------------------------*/
+/* Data Structures */
+/*----------------------------------------------------------------------------*/
+enum {
+ OK = HELPERS_OK,
+ OUT_OF_MEMORY = HELPERS_OUT_OF_MEMORY,
+ INVALID_FIRST_ELEMENT = HELPERS_INVALID_FIRST_ELEMENT,
+ MISSING_ENTRY = HELPERS_MISSING_WRAPPER,
+ INVALID_OBJECT,
+ INVALID_VERSION,
+};
+/*----------------------------------------------------------------------------*/
+/* File Scoped Variables */
+/*----------------------------------------------------------------------------*/
+/* none */
+/*----------------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------------*/
+int process_networkintelligenceparams( networkintelligenceparam_t *e, msgpack_object_map *map );
+int process_networkintelligencedoc( networkintelligencedoc_t *nd, int num, ...);
+/*----------------------------------------------------------------------------*/
+/* External Functions */
+/*----------------------------------------------------------------------------*/
+/* See networkintelligence_param.h for details. */
+networkintelligencedoc_t* networkintelligencedoc_convert( const void *buf, size_t len )
+{
+ return comp_helper_convert( buf, len, sizeof(networkintelligencedoc_t), NI_WEBCONFIG_SUBDOC_NAME,
+ MSGPACK_OBJECT_MAP, true,
+ (process_fn_t) process_networkintelligencedoc,
+ (destroy_fn_t) networkintelligencedoc_destroy );
+}
+/* See networkintelligence_param.h for details. */
+void networkintelligencedoc_destroy( networkintelligencedoc_t *nd )
+{
+ if( NULL != nd )
+ {
+ if( NULL != nd->subdoc_name )
+ {
+ AnscFreeMemory ( nd->subdoc_name );
+ }
+ if( NULL != nd->param )
+ {
+ AnscFreeMemory ( nd->param );
+ }
+ AnscFreeMemory ( nd );
+ }
+}
+/* See networkintelligence_param.h for details. */
+const char* networkintelligencedoc_strerror( int errnum )
+{
+ struct error_map {
+ int v;
+ const char *txt;
+ } map[] = {
+ { .v = OK, .txt = "No errors." },
+ { .v = OUT_OF_MEMORY, .txt = "Out of memory." },
+ { .v = INVALID_FIRST_ELEMENT, .txt = "Invalid first element." },
+ { .v = INVALID_VERSION, .txt = "Invalid 'version' value." },
+ { .v = INVALID_OBJECT, .txt = "Invalid 'value' array." },
+ { .v = 0, .txt = NULL }
+ };
+ int i = 0;
+ while( (map[i].v != errnum) && (NULL != map[i].txt) ) { i++; }
+ if( NULL == map[i].txt )
+ {
+ CcspTraceError(("----%s----\n", __FUNCTION__));
+ return "Unknown error.";
+ }
+ return map[i].txt;
+}
+/*----------------------------------------------------------------------------*/
+/* Internal functions */
+/*----------------------------------------------------------------------------*/
+/**
+ * Convert the msgpack map into the doc_t structure.
+ *
+ * @param e the entry pointer
+ * @param map the msgpack map pointer
+ *
+ * @return 0 on success, error otherwise
+ */
+int process_networkintelligenceparams( networkintelligenceparam_t *e, msgpack_object_map *map )
+{
+ int left = map->size;
+ uint8_t objects_left = 0x01;
+ msgpack_object_kv *p;
+ p = map->ptr;
+ while( (0 < left--) && (0 != objects_left) )
+ {
+ if( MSGPACK_OBJECT_STR == p->key.type )
+ {
+ if( MSGPACK_OBJECT_BOOLEAN == p->val.type )
+ {
+ if( 0 == match(p, "NetworkIntelligenceActivate") )
+ {
+ e->network_intelligence_activate = p->val.via.boolean;
+ objects_left &= ~(1 << 0);
+ }
+ }
+ }
+ p++;
+ }
+
+ if( 1 & objects_left ) {
+ } else {
+ errno = OK;
+ }
+
+ return (0 == objects_left) ? 0 : -1;
+}
+int process_networkintelligencedoc( networkintelligencedoc_t *nd, int num, ... )
+{
+//To access the variable arguments use va_list
+ va_list valist;
+ va_start(valist, num);//start of variable argument loop
+
+ msgpack_object *obj = va_arg(valist, msgpack_object *);//each usage of va_arg fn argument iterates by one time
+ msgpack_object *obj1 = va_arg(valist, msgpack_object *);
+ msgpack_object *obj2 = va_arg(valist, msgpack_object *);
+ msgpack_object *obj3 = va_arg(valist, msgpack_object *);
+ va_end(valist);//End of variable argument loop
+
+ if( (NULL == obj) || (NULL == obj1) || (NULL == obj2) || (NULL == obj3) )
+ {
+ CcspTraceError(("%s missing mandatory element(s) in subdoc\n", __FUNCTION__));
+ return -1;
+ }
+
+ if( (MSGPACK_OBJECT_MAP != obj->type) ||
+ (MSGPACK_OBJECT_STR != obj1->type) ||
+ (MSGPACK_OBJECT_POSITIVE_INTEGER != obj2->type) ||
+ (MSGPACK_OBJECT_POSITIVE_INTEGER != obj3->type) )
+ {
+ CcspTraceError(("%s unexpected element type(s) in subdoc\n", __FUNCTION__));
+ return -1;
+ }
+
+ msgpack_object_map *mapobj = &obj->via.map;
+
+ nd->subdoc_name = strndup( obj1->via.str.ptr, obj1->via.str.size );
+ if( NULL == nd->subdoc_name )
+ {
+ CcspTraceError(("%s subdoc_name strndup failed\n", __FUNCTION__));
+ return -1;
+ }
+
+ nd->version = (uint32_t) obj2->via.u64;
+ nd->transaction_id = (uint16_t) obj3->via.u64;
+
+ nd->param = (networkintelligenceparam_t *) AnscAllocateMemory( sizeof(networkintelligenceparam_t) );
+ if( NULL == nd->param )
+ {
+ CcspTraceError(("%s entries count AnscAllocateMemory failed\n", __FUNCTION__));
+ return -1;
+ }
+ memset( nd->param, 0, sizeof(networkintelligenceparam_t));
+
+ if( 0 != process_networkintelligenceparams(nd->param, mapobj) )
+ {
+ CcspTraceError(("%s failed\n", __FUNCTION__));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/source/AdvSecurityDml/networkintelligence_param.h b/source/AdvSecurityDml/networkintelligence_param.h
new file mode 100644
index 0000000..e48e04b
--- /dev/null
+++ b/source/AdvSecurityDml/networkintelligence_param.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016 Comcast Cable Communications Management, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
+*/
+
+#ifndef __NETWORKINTELLIGENCE_PARAM_H__
+#define __NETWORKINTELLIGENCE_PARAM_H__
+#include
+#include
+#include
+
+#define NI_WEBCONFIG_SUBDOC_NAME "networkintelligence"
+
+typedef struct
+{
+ bool network_intelligence_activate;
+
+} networkintelligenceparam_t;
+
+typedef struct {
+ networkintelligenceparam_t *param;
+ char * subdoc_name;
+ uint32_t version;
+ uint16_t transaction_id;
+} networkintelligencedoc_t;
+/**
+ * This function converts a msgpack buffer into a networkintelligencedoc_t
+ * structure if possible.
+ *
+ * @param buf the buffer to convert
+ * @param len the length of the buffer in bytes
+ *
+ * @return NULL on error, success otherwise
+ */
+networkintelligencedoc_t* networkintelligencedoc_convert( const void *buf, size_t len );
+/**
+ * This function destroys a networkintelligencedoc_t object.
+ *
+ * @param d the networkintelligencedoc to destroy
+ */
+void networkintelligencedoc_destroy( networkintelligencedoc_t *d );
+/**
+ * This function returns a general reason why the conversion failed.
+ *
+ * @param errnum the errno value to inspect
+ *
+ * @return the constant string (do not alter or free) describing the error
+ */
+const char* networkintelligencedoc_strerror( int errnum );
+#endif
diff --git a/source/AdvSecurityDml/plugin_main.c b/source/AdvSecurityDml/plugin_main.c
index ffe2c57..00d225c 100644
--- a/source/AdvSecurityDml/plugin_main.c
+++ b/source/AdvSecurityDml/plugin_main.c
@@ -111,6 +111,8 @@ COSA_Init
pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_GetParamBoolValue", NetworkIntelligence_GetParamBoolValue);
pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_SetParamBoolValue", NetworkIntelligence_SetParamBoolValue);
+
+ pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_SetParamStringValue", NetworkIntelligence_SetParamStringValue);
#endif // NETWORK_INTELLIGENCE
pPlugInfo->RegisterFunction(pPlugInfo->hContext, "WifiDataCollection_RFC_GetParamBoolValue", WifiDataCollection_RFC_GetParamBoolValue);
diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp
index 3525b14..791fe8c 100644
--- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp
+++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp
@@ -41,6 +41,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test {
g_syseventMock = new SyseventMock();
g_webconfigFwMock = new webconfigFwMock();
g_anscWrapperApiMock = new AnscWrapperApiMock();
+ g_telemetryMock = new telemetryMock();
}
void TearDown() override {
@@ -60,6 +61,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test {
delete g_syseventMock;
delete g_webconfigFwMock;
delete g_anscWrapperApiMock;
+ delete g_telemetryMock;
g_syscfgMock = nullptr;
g_securewrapperMock = nullptr;
g_msgpackMock = nullptr;
@@ -76,6 +78,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test {
g_syseventMock = nullptr;
g_webconfigFwMock = nullptr;
g_anscWrapperApiMock = nullptr;
+ g_telemetryMock = nullptr;
}
};
diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp
index e8695fc..357bf1c 100644
--- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp
+++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp
@@ -43,6 +43,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test {
g_syseventMock = new SyseventMock();
g_webconfigFwMock = new webconfigFwMock();
g_anscWrapperApiMock = new AnscWrapperApiMock();
+ g_telemetryMock = new telemetryMock();
}
void TearDown() override {
@@ -62,6 +63,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test {
delete g_syseventMock;
delete g_webconfigFwMock;
delete g_anscWrapperApiMock;
+ delete g_telemetryMock;
g_syscfgMock = nullptr;
g_securewrapperMock = nullptr;
g_msgpackMock = nullptr;
@@ -78,6 +80,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test {
g_syseventMock = nullptr;
g_webconfigFwMock = nullptr;
g_anscWrapperApiMock = nullptr;
+ g_telemetryMock = nullptr;
}
};
@@ -1441,6 +1444,419 @@ TEST_F(CcspAdvSecurityInternalTestFixture, CosaRabidSetDNSCacheSize)
free(g_pAdvSecAgent);
}
+#ifdef NETWORK_INTELLIGENCE
+#include
+
+extern "C" void speedtestEventReceiveHandler(rbusHandle_t handle, rbusEvent_t const* event, rbusEventSubscription_t* subscription);
+/* Internal SpeedTest timer state exposed (non-static in unit-test builds
+ * via the STATIC macro) purely so tests can synchronize with the
+ * asynchronous timer thread. No test-only function is defined in
+ * production source for this. */
+extern "C" pthread_mutex_t ni_speedtest_mutex;
+extern "C" BOOL ni_speedtest_thread_running;
+
+static const char *g_speedtestNIEnabledPath = "/tmp/advsec_networkintelligence_enabled";
+static const char *g_speedtestNIActivatedPath = "/tmp/advsec_networkintelligence_activated";
+
+static void CreateSpeedtestNIEnabledAndActivated(void)
+{
+ FILE *file = fopen(g_speedtestNIEnabledPath, "w");
+ if (file) fclose(file);
+ file = fopen(g_speedtestNIActivatedPath, "w");
+ if (file) fclose(file);
+}
+
+static void RemoveSpeedtestNIEnabledAndActivated(void)
+{
+ remove(g_speedtestNIEnabledPath);
+ remove(g_speedtestNIActivatedPath);
+}
+
+/* Test-only helper: reads the SpeedTest timer thread's running state
+ * under its production mutex. */
+static bool IsSpeedtestThreadRunning(void)
+{
+ BOOL running;
+
+ pthread_mutex_lock(&ni_speedtest_mutex);
+ running = ni_speedtest_thread_running;
+ pthread_mutex_unlock(&ni_speedtest_mutex);
+ return running ? true : false;
+}
+
+/* Polls IsSpeedtestThreadRunning() until the SpeedTest timer thread
+ * reaches the desired state or maxWaitMs elapses. The thread's work
+ * (mocked v_secure_system calls) completes in microseconds, so this
+ * bounds test time while avoiding a fixed, potentially-flaky sleep. */
+static void WaitForSpeedtestThreadState(bool running, int maxWaitMs)
+{
+ int waited = 0;
+ while (IsSpeedtestThreadRunning() != running && waited < maxWaitMs)
+ {
+ usleep(2000);
+ waited += 2;
+ }
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_PausesAndCompletes_ResumesNI)
+{
+ int marker = 0;
+ int timeoutMarker = 0;
+ int completeMarker = 5;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker;
+ rbusValue_t completeValue = (rbusValue_t)&completeMarker;
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(2)
+ .WillOnce(Return(value))
+ .WillOnce(Return(completeValue));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS)));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue))
+ .Times(1)
+ .WillOnce(Return(86400));
+ EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue))
+ .Times(1);
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _))
+ .Times(2)
+ .WillRepeatedly(Return(0));
+
+ /* status=1: starts the timer thread, which pauses NI immediately. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ WaitForSpeedtestThreadState(true, 200);
+ EXPECT_TRUE(IsSpeedtestThreadRunning());
+
+ /* status=5: wakes the thread early so it resumes NI and exits. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ WaitForSpeedtestThreadState(false, 500);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_PauseFails_ClearsRunningState)
+{
+ int marker = 0;
+ int timeoutMarker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker;
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS)));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue))
+ .Times(1)
+ .WillOnce(Return(86400));
+ EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue))
+ .Times(1);
+ /* Simulate cujo-ni-cli failing (non-zero exit status) on the pause
+ * attempt. The thread must still clear ni_speedtest_thread_running
+ * so future SpeedTest cycles are not permanently blocked. */
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _))
+ .Times(1)
+ .WillOnce(Return(256));
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ WaitForSpeedtestThreadState(false, 500);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_DuplicateStart_RefreshesTimeout)
+{
+ int marker = 0;
+ int timeoutMarker = 0;
+ int completeMarker = 5;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker;
+ rbusValue_t completeValue = (rbusValue_t)&completeMarker;
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(3)
+ .WillOnce(Return(value))
+ .WillOnce(Return(value))
+ .WillOnce(Return(completeValue));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(2)
+ .WillRepeatedly(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ /* Timeout is fetched again on the duplicate STARTING event, since
+ * ni_speedtest_trigger() now refreshes the running timer's deadline
+ * instead of ignoring the event. */
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(2)
+ .WillRepeatedly(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS)));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue))
+ .Times(2)
+ .WillRepeatedly(Return(86400));
+ EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue))
+ .Times(2);
+ /* Only ONE pause + ONE resume, even though status=1 fires twice:
+ * the duplicate STARTING event only refreshes the deadline, it does
+ * not re-pause Network Intelligence or spawn a new thread. */
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _))
+ .Times(2)
+ .WillRepeatedly(Return(0));
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ WaitForSpeedtestThreadState(true, 200);
+ EXPECT_TRUE(IsSpeedtestThreadRunning());
+
+ /* Duplicate status=1 while already running: refreshes the deadline
+ * on the existing thread, no new pause, no new thread. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ EXPECT_TRUE(IsSpeedtestThreadRunning());
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ WaitForSpeedtestThreadState(false, 500);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_NIDisabled_NoAction)
+{
+ int marker = 0;
+ int completeMarker = 5;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t completeValue = (rbusValue_t)&completeMarker;
+ rbusEvent_t event = {};
+ RemoveSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(2)
+ .WillOnce(Return(value))
+ .WillOnce(Return(completeValue));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ /* NI is disabled: speedtestEventReceiveHandler now returns before
+ * ever fetching the timeout, for any status. */
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(0);
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ /* NI is disabled: the top-level is_ni_enabled_and_activated() check
+ * in speedtestEventReceiveHandler skips the event entirely, so
+ * ni_speedtest_thread_running never becomes TRUE. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_NIEnabledButNotActivated_NoAction)
+{
+ int marker = 0;
+ int completeMarker = 5;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t completeValue = (rbusValue_t)&completeMarker;
+ rbusEvent_t event = {};
+ remove(g_speedtestNIActivatedPath);
+ FILE *file = fopen(g_speedtestNIEnabledPath, "w");
+ if (file) fclose(file);
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(2)
+ .WillOnce(Return(value))
+ .WillOnce(Return(completeValue));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ /* NI is enabled but not activated: still gated out before ever
+ * fetching the timeout. */
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(0);
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ /* NI is enabled but not activated: the top-level
+ * is_ni_enabled_and_activated() check skips the event entirely. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ remove(g_speedtestNIEnabledPath);
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_StartingWithZeroTimeout_NoAction)
+{
+ int marker = 0;
+ int timeoutMarker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker;
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS)));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue))
+ .Times(1)
+ .WillOnce(Return(0));
+ EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue))
+ .Times(1);
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_GetTimeoutFailsWithValue_ReleasesRbusValue)
+{
+ int marker = 0;
+ int timeoutMarker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker;
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_STARTING));
+ /* rbus_get() fails but still populates a non-NULL value (a real
+ * rbus behavior in some implementations, e.g. partial/cached state
+ * before returning an error). speedtestGetTimeout() must release it
+ * instead of leaking it. */
+ EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_BUS_ERROR)));
+ EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue))
+ .Times(1);
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+
+ EXPECT_FALSE(IsSpeedtestThreadRunning());
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Complete_NoThreadRunning_NoAction)
+{
+ int marker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Complete_NIDisabled_NoAction)
+{
+ int marker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusEvent_t event = {};
+ RemoveSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(ST_TR181_STATUS_COMPLETE));
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ /* NI disabled: the top-level is_ni_enabled_and_activated() check now
+ * gates COMPLETE the same as STARTING. */
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_NullValue_NoAction)
+{
+ rbusEvent_t event = {};
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return((rbusValue_t)NULL));
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+}
+
+TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Other_NoAction)
+{
+ int marker = 0;
+ rbusValue_t value = (rbusValue_t)▮
+ rbusEvent_t event = {};
+ CreateSpeedtestNIEnabledAndActivated();
+
+ EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _))
+ .Times(1)
+ .WillOnce(Return(value));
+ EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value))
+ .Times(1)
+ .WillOnce(Return(2));
+ EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _))
+ .Times(0);
+
+ speedtestEventReceiveHandler(NULL, &event, NULL);
+
+ RemoveSpeedtestNIEnabledAndActivated();
+}
+#endif
+
TEST_F(CcspAdvSecurityInternalTestFixture, CosaAdvPCInit)
{
const char *AdvParentalControlRFCEnabled = "Adv_PCRFCEnable";
diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp
index a690f88..342b12e 100644
--- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp
+++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp
@@ -34,3 +34,4 @@ cjsonMock *g_cjsonMock = NULL;
SyseventMock *g_syseventMock = NULL;
webconfigFwMock *g_webconfigFwMock = NULL;
AnscWrapperApiMock * g_anscWrapperApiMock = NULL;
+telemetryMock *g_telemetryMock = NULL;
diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h
index f73fbf9..1223968 100644
--- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h
+++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
extern SyscfgMock *g_syscfgMock;
extern SecureWrapperMock *g_securewrapperMock;
@@ -60,6 +61,7 @@ extern cjsonMock *g_cjsonMock;
extern SyseventMock *g_syseventMock;
extern webconfigFwMock *g_webconfigFwMock;
extern AnscWrapperApiMock *g_anscWrapperApiMock;
+extern telemetryMock *g_telemetryMock;
using namespace std;
using std::experimental::filesystem::exists;
diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp
index 597d14b..a1e000c 100644
--- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp
+++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp
@@ -37,6 +37,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test {
g_syseventMock = new SyseventMock();
g_webconfigFwMock = new webconfigFwMock();
g_anscWrapperApiMock = new AnscWrapperApiMock();
+ g_telemetryMock = new telemetryMock();
}
void TearDown() override {
@@ -56,6 +57,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test {
delete g_syseventMock;
delete g_webconfigFwMock;
delete g_anscWrapperApiMock;
+ delete g_telemetryMock;
g_syscfgMock = nullptr;
g_securewrapperMock = nullptr;
g_msgpackMock = nullptr;
@@ -72,6 +74,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test {
g_syseventMock = nullptr;
g_webconfigFwMock = nullptr;
g_anscWrapperApiMock = nullptr;
+ g_telemetryMock = nullptr;
}
};
@@ -165,8 +168,8 @@ TEST_F(CcspAdvSecurityWebconfigTestFixture, advsec_webconfig_init) {
.Times(1)
.WillOnce(Return(0));
EXPECT_CALL(*g_safecLibMock, _strcpy_s_chk(_, _, _, _))
- .Times(1)
- .WillOnce(Return(0));
+ .Times(SUBDOC_COUNT)
+ .WillRepeatedly(Return(0));
EXPECT_CALL(*g_webconfigFwMock, register_sub_docs(_, _, _, _))
.Times(1);
diff --git a/source/test/CcspAdvSecurityDmlTest/Makefile.am b/source/test/CcspAdvSecurityDmlTest/Makefile.am
index 6cfdb0a..49db1db 100644
--- a/source/test/CcspAdvSecurityDmlTest/Makefile.am
+++ b/source/test/CcspAdvSecurityDmlTest/Makefile.am
@@ -45,6 +45,8 @@ CcspAdvSecurityDmlTest_gtest_bin_SOURCES = CcspAdvSecurityMock.cpp \
${top_builddir}/source/AdvSecurityDml/advsecurity_helpers.c \
${top_builddir}/source/AdvSecurityDml/advsecurity_param.c \
${top_builddir}/source/AdvSecurityDml/cosa_adv_security_webconfig.c \
+ ${top_builddir}/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c \
+ ${top_builddir}/source/AdvSecurityDml/networkintelligence_param.c \
${top_builddir}/source/AdvSecurityDml/plugin_main.c \
gtest_main.cpp
@@ -55,6 +57,7 @@ CcspAdvSecurityDmlTest_gtest_bin_LDADD = \
$(HOME)/usr/local/lib/libmock_secure_wrapper.la \
$(HOME)/usr/local/lib/libmock_msgpack.la \
$(HOME)/usr/local/lib/libmock_safec_lib.la \
+ $(HOME)/usr/local/lib/libmock_telemetry.la \
$(HOME)/usr/local/lib/libmock_webconfigframework.la \
$(HOME)/usr/local/lib/libmock_base64.la \
$(HOME)/usr/local/lib/libmock_rbus.la \