diff --git a/source/ccspinterface/busInterface.h b/source/ccspinterface/busInterface.h index 96dd6706..9f80297b 100644 --- a/source/ccspinterface/busInterface.h +++ b/source/ccspinterface/busInterface.h @@ -28,10 +28,33 @@ #define CCSP_COMPONENT_ID "eRT.com.cisco.spvtg.ccsp.telemetry" #endif // CCSP_SUPPORT_ENABLED -typedef struct +/** + * Enumeration of possible types for TR-181 values + */ + +typedef enum { + TR181_TYPE_STRING, + TR181_TYPE_INT, + TR181_TYPE_UNSIGNED, + TR181_TYPE_BOOLEAN, + TR181_TYPE_DATETIME, + TR181_TYPE_BASE64, + TR181_TYPE_LONG, + TR181_TYPE_UNSIGNED_LONG, + TR181_TYPE_FLOAT, + TR181_TYPE_DOUBLE +} TR181ParameterType; + +/** + * Structure containing the name and value of a TR-181 parameter, + * as well as its type (added for correct JSON encoding). + */ + +typedef struct { char *parameterName; char *parameterValue; + TR181ParameterType type; } tr181ValStruct_t; diff --git a/source/ccspinterface/ccspinterface.c b/source/ccspinterface/ccspinterface.c index 2ffd24de..d69a6ce2 100644 --- a/source/ccspinterface/ccspinterface.c +++ b/source/ccspinterface/ccspinterface.c @@ -28,6 +28,8 @@ #include "vector.h" #include "t2common.h" #include "ssp_global.h" +#include "ccsp_memory.h" +#include "ccsp_base_api.h" static void *bus_handle = NULL; @@ -226,8 +228,6 @@ T2ERROR getCCSPParamVal(const char* paramName, char **paramValue) Vector* getCCSPProfileParamValues(Vector *paramList) { - unsigned int i = 0; - int count = Vector_Size(paramList); Vector *profileValueList = NULL; Vector_Create(&profileValueList); @@ -237,108 +237,148 @@ Vector* getCCSPProfileParamValues(Vector *paramList) return profileValueList; } - char** paramNames = (char **) malloc(count * sizeof(char*)); - if(!paramNames) - { - T2Error("Unable allocate memory for paramNames\n"); - return profileValueList; - } - T2Info("TR-181 Param count : %d\n", count); - for( ; i < count; i++ ) - { + for(int i = 0; i < Vector_Size(paramList); i++) { + /* Preparing the storage for the result */ tr181ValStruct_t **paramValues = NULL; parameterValStruct_t **ccspParamValues = NULL; - int paramValCount = 0; - int iterate = 0; - profileValues *profVals = (profileValues *) malloc(sizeof(profileValues)); + int paramValCount = 0; + profileValues *profVals = calloc(1, sizeof(profileValues)); if(profVals == NULL) { T2Error("Unable allocate memory for profVals\n"); continue; } - paramNames[0] = strdup(((Param *) Vector_At(paramList, i))->alias); - if(paramNames[0] == NULL) - { - T2Error("Unable allocate memory for paramNames[0]\n"); - free(profVals); - continue; - } - if(T2ERROR_SUCCESS != ccspGetParameterValues((const char**)paramNames, 1, &ccspParamValues, ¶mValCount)) + + /* Retrieving the TR-181 alias and duplicating it */ + const char *alias = ((Param *)Vector_At(paramList, i))->alias; + char *paramName = alias ? strdup(alias) : NULL; + /* paramNames passed to the CCSP API (must be char*[], not const) */ + char *paramNames[1] = { paramName ? strdup(paramName) : NULL }; + + /* --- CCSP component discovery --- */ + char *destCompName = NULL; + char *destCompPath = NULL; + if(paramName) { - T2Error("Failed to retrieve param : %s\n", paramNames[0]); - paramValCount = 0; + int discRet = findDestComponent(paramName, &destCompName, &destCompPath); + if(discRet != CCSP_SUCCESS) { + T2Error("Component discovery failed for %s (ret=%d)\n", paramName, discRet); + paramValCount = 0; + } + else + { + T2Debug("Discovered comp %s at %s\n", destCompName, destCompPath); + } } - else + + /* --- Call to the CCSP API to retrieve the values --- */ + if(paramNames[0]) { - /* CID 175831: Dereference after null check */ - if(ccspParamValues == NULL) + T2Debug("CcspBaseIf_getParameterValues for: %s\n", paramNames[0]); + int ret = CcspBaseIf_getParameterValues( + bus_handle, + destCompName, + destCompPath, + (char**)paramNames, + 1, + ¶mValCount, + &ccspParamValues); + if(ret != CCSP_SUCCESS) { - T2Info("unable to get ccspParamValues \n"); - free(profVals); - return profileValueList; - } - if(paramValCount == 0) + T2Error("CcspBaseIf_getParameterValues failed for %s (ret=%d)\n", paramNames[0], ret); + paramValCount = 0; + } + else { T2Info("ParameterName : %s Retrieved value count : %d\n", paramNames[0], paramValCount); } } profVals->paramValueCount = paramValCount; + T2Debug("Received %d parameters for %s (CCSP)\n", + paramValCount, + paramNames[0] ? paramNames[0] : "(null)"); - // Populate bus independent parameter value array + /* --- Constructing the TR-181 values array --- */ if(paramValCount == 0) { - paramValues = (tr181ValStruct_t**) malloc(sizeof(tr181ValStruct_t*)); - if(paramValues != NULL) - { - paramValues[0] = (tr181ValStruct_t*) malloc(sizeof(tr181ValStruct_t)); - if(paramValues[0] != NULL) - { - paramValues[0]->parameterName = strdup(paramNames[0]); - paramValues[0]->parameterValue = strdup("NULL"); - } - } + /* Parameters found → copy each one */ + paramValues = calloc(1, sizeof(tr181ValStruct_t*)); + paramValues[0] = calloc(1, sizeof(tr181ValStruct_t)); + paramValues[0]->parameterName = strdup(paramName ? paramName : ""); + paramValues[0]->parameterValue = strdup("NULL"); + paramValues[0]->type = TR181_TYPE_STRING; + profVals->paramValueCount = 1; } else { - paramValues = (tr181ValStruct_t**) malloc(paramValCount * sizeof(tr181ValStruct_t*)); - if(paramValues != NULL) + /* Parameters found → copy each one */ + paramValues = calloc(paramValCount, sizeof(tr181ValStruct_t*)); + for(int j = 0; j < paramValCount; j++) { - for( iterate = 0; iterate < paramValCount; ++iterate ) - { - if(ccspParamValues[iterate]) - { - paramValues[iterate] = (tr181ValStruct_t*) malloc(sizeof(tr181ValStruct_t)); - if(paramValues[iterate]) - { - paramValues[iterate]->parameterName = strdup((ccspParamValues[iterate])->parameterName); - paramValues[iterate]->parameterValue = strdup((ccspParamValues[iterate])->parameterValue); - } - } + parameterValStruct_t *cc = ccspParamValues[j]; + paramValues[j] = calloc(1, sizeof(tr181ValStruct_t)); + /* Copy name and value */ + paramValues[j]->parameterName = strdup(cc->parameterName); + paramValues[j]->parameterValue = strdup(cc->parameterValue); + /* Assign the native TR-181 type */ + switch(ccspParamValues[j]->type) { + case ccsp_boolean: + paramValues[j]->type = TR181_TYPE_BOOLEAN; + break; + case ccsp_int: + paramValues[j]->type = TR181_TYPE_INT; + break; + case ccsp_unsignedInt: + paramValues[j]->type = TR181_TYPE_UNSIGNED; + break; + case ccsp_long: + paramValues[j]->type = TR181_TYPE_LONG; + break; + case ccsp_unsignedLong: + paramValues[j]->type = TR181_TYPE_UNSIGNED_LONG; + break; + case ccsp_float: + paramValues[j]->type = TR181_TYPE_FLOAT; + break; + case ccsp_double: + paramValues[j]->type = TR181_TYPE_DOUBLE; + break; + case ccsp_dateTime: + paramValues[j]->type = TR181_TYPE_DATETIME; + break; + case ccsp_base64: + paramValues[j]->type = TR181_TYPE_BASE64; + break; + case ccsp_string: + default: + paramValues[j]->type = TR181_TYPE_STRING; + break; } - free_parameterValStruct_t(bus_handle, paramValCount, ccspParamValues); } } + /* --- CCSP cleanup and profile finalization --- */ + if(ccspParamValues) + { + free_parameterValStruct_t(bus_handle, paramValCount, ccspParamValues); + } profVals->paramValues = paramValues; // End of populating bus independent parameter value array Vector_PushBack(profileValueList, profVals); - if(paramNames[0]) - { - free(paramNames[0]); - } - } - if(paramNames) - { - free(paramNames); + + /* Free the temporary strings */ + free(paramName); + free(paramNames[0]); + free(destCompName); + free(destCompPath); } T2Debug("%s --Out\n", __FUNCTION__); return profileValueList; } - T2ERROR registerCcspT2EventListener(TelemetryEventCallback eventCB) { int ret; diff --git a/source/ccspinterface/rbusInterface.c b/source/ccspinterface/rbusInterface.c index 41207bad..4b8ea10a 100644 --- a/source/ccspinterface/rbusInterface.c +++ b/source/ccspinterface/rbusInterface.c @@ -274,6 +274,7 @@ Vector* getRbusProfileParamValues(Vector *paramList) paramValues[0] = (tr181ValStruct_t*) malloc(sizeof(tr181ValStruct_t)); paramValues[0]->parameterName = strdup(param); paramValues[0]->parameterValue = strdup("NULL"); + paramValues[0]->type = TR181_TYPE_STRING; // If parameter doesn't exist in device we do populate with entry as NULL. // So count of populated data list has 1 entry and is not 0 profVals->paramValueCount = 1; @@ -289,57 +290,87 @@ Vector* getRbusProfileParamValues(Vector *paramList) if(paramValues != NULL) { rbusProperty_t nextProperty = rbusPropertyValues; - for( iterate = 0; iterate < paramValCount; ++iterate ) // Loop through values obtained from query for individual param in list - { - if(nextProperty) - { - char* stringValue = NULL; + for( iterate = 0; iterate < paramValCount; ++iterate ) { // Loop through values obtained from query for individual param in list + if(nextProperty) { + char* paramName = NULL; rbusValue_t value = rbusProperty_GetValue(nextProperty); paramValues[iterate] = (tr181ValStruct_t*) malloc(sizeof(tr181ValStruct_t)); - if(paramValues[iterate]) - { - stringValue = (char*)rbusProperty_GetName(nextProperty); - paramValues[iterate]->parameterName = strdup(stringValue); + if(paramValues[iterate]) { + // Full name of the parameter. + paramName = (char*)rbusProperty_GetName(nextProperty); + paramValues[iterate]->parameterName = strdup(paramName); + // Retrieving the value as a string rbusValueType_t rbusValueType = rbusValue_GetType(value); - if(rbusValueType == RBUS_BOOLEAN) - { - if(rbusValue_GetBoolean(value)) - { + if(rbusValueType == RBUS_BOOLEAN) { + // Boolean value -> store "true"/"false" as text and as a boolean type + if(rbusValue_GetBoolean(value)) { paramValues[iterate]->parameterValue = strdup("true"); - } - else - { + }else { paramValues[iterate]->parameterValue = strdup("false"); } - } - else - { + paramValues[iterate]->type = TR181_TYPE_BOOLEAN; + }else { + // Other types -> convert to string then set the appropriate type paramValues[iterate]->parameterValue = rbusValue_ToString(value, NULL, 0); + switch(rbusValueType) { + case RBUS_INT32: + case RBUS_INT16: + case RBUS_INT8: + paramValues[iterate]->type = TR181_TYPE_INT; + break; + case RBUS_UINT32: + case RBUS_UINT16: + case RBUS_UINT8: + paramValues[iterate]->type = TR181_TYPE_UNSIGNED; + break; + case RBUS_INT64: + paramValues[iterate]->type = TR181_TYPE_LONG; + break; + case RBUS_UINT64: + paramValues[iterate]->type = TR181_TYPE_UNSIGNED_LONG; + break; + case RBUS_SINGLE: + paramValues[iterate]->type = TR181_TYPE_FLOAT; + break; + case RBUS_DOUBLE: + paramValues[iterate]->type = TR181_TYPE_DOUBLE; + break; + case RBUS_DATETIME: + paramValues[iterate]->type = TR181_TYPE_DATETIME; + break; + case RBUS_BYTES: + paramValues[iterate]->type = TR181_TYPE_BASE64; + break; + case RBUS_STRING: + default: + paramValues[iterate]->type = TR181_TYPE_STRING; + break; + } } + #if defined(ENABLE_RDKV_SUPPORT) + // (Code not modified regarding the FirmwareFilename for RDK-V) -#if defined(ENABLE_RDKV_SUPPORT) // Workaround as video platforms doesn't have a TR param which gives Firmware name // Existing dashboards doesn't like version with file name exentsion // Workaround stays until initiative for unified new TR param for version name gets implemented across board - if(0 == strncmp(stringValue, "Device.DeviceInfo.X_RDKCENTRAL-COM_FirmwareFilename", maxParamLen ) || 0 == strncmp(stringValue, "Device.DeviceInfo.X_COMCAST-COM_FirmwareFilename", maxParamLen )) - { - char* temp = NULL; - temp = strstr(paramValues[iterate]->parameterValue, "-signed.bin"); - if(!temp) - { + if(paramName && (strncmp(paramName, "Device.DeviceInfo.X_RDKCENTRAL-COM_FirmwareFilename", maxParamLen) == 0 || + strncmp(paramName, "Device.DeviceInfo.X_COMCAST-COM_FirmwareFilename", maxParamLen) == 0)) { + char* temp = strstr(paramValues[iterate]->parameterValue, "-signed.bin"); + if(!temp) { temp = strstr(paramValues[iterate]->parameterValue, ".bin"); } if(temp) - { *temp = '\0'; - } } -#endif + #endif } + // Move to next property in list + nextProperty = rbusProperty_GetNext(nextProperty); } - nextProperty = rbusProperty_GetNext(nextProperty); } + } + if(rbusPropertyValues != NULL) { rbusProperty_Release(rbusPropertyValues); } } @@ -350,9 +381,7 @@ Vector* getRbusProfileParamValues(Vector *paramList) Vector_PushBack(profileValueList, profVals); } // End of looping through tr181 parameter list from profile if(paramNames) - { free(paramNames); - } T2Debug("%s --Out\n", __FUNCTION__); return profileValueList; diff --git a/source/reportgen/reportgen.c b/source/reportgen/reportgen.c index 107d9287..437b02c2 100644 --- a/source/reportgen/reportgen.c +++ b/source/reportgen/reportgen.c @@ -246,13 +246,63 @@ T2ERROR encodeParamResultInJSON(cJSON *valArray, Vector *paramNameList, Vector * regfree(®pattern); } } - - if(cJSON_AddStringToObject(arrayItem, param->name, paramValues[0]->parameterValue) == NULL) - { - T2Error("cJSON_AddStringToObject failed.\n"); - cJSON_Delete(arrayItem); - return T2ERROR_FAILURE; - } + switch(paramValues[0]->type) { + case TR181_TYPE_BOOLEAN: { + bool b = false; + // Convert "true"/"false"/"1"/"0" to boolean + if(paramValues[0]->parameterValue && + (strcasecmp(paramValues[0]->parameterValue, "true") == 0 || + strcmp(paramValues[0]->parameterValue, "1") == 0)) { + b = true; + } + if(cJSON_AddBoolToObject(arrayItem, param->name, b) == NULL){ + T2Error("cJSON_AddBoolToObject failed.\n"); + cJSON_Delete(arrayItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_INT: + case TR181_TYPE_LONG: { + long long ll = paramValues[0]->parameterValue ? strtoll(paramValues[0]->parameterValue, NULL, 10) : 0; + if(cJSON_AddNumberToObject(arrayItem, param->name, (double) ll) == NULL){ + T2Error("cJSON_AddNumberToObject failed.\n"); + cJSON_Delete(arrayItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_UNSIGNED: + case TR181_TYPE_UNSIGNED_LONG: { + unsigned long long ull = paramValues[0]->parameterValue ? strtoull(paramValues[0]->parameterValue, NULL, 10) : 0; + if(cJSON_AddNumberToObject(arrayItem, param->name, (double) ull) == NULL){ + T2Error("cJSON_AddNumberToObject failed.\n"); + cJSON_Delete(arrayItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_FLOAT: + case TR181_TYPE_DOUBLE: { + double d = paramValues[0]->parameterValue ? strtod(paramValues[0]->parameterValue, NULL) : 0.0; + if(cJSON_AddNumberToObject(arrayItem, param->name, d) == NULL){ + T2Error("cJSON_AddNumberToObject failed.\n"); + cJSON_Delete(arrayItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_STRING: + case TR181_TYPE_DATETIME: + case TR181_TYPE_BASE64: + default: { + if(cJSON_AddStringToObject(arrayItem, param->name, paramValues[0]->parameterValue) == NULL){ + T2Error("cJSON_AddStringToObject failed.\n"); + cJSON_Delete(arrayItem); + return T2ERROR_FAILURE; + } + } + } // end switch cJSON_AddItemToArray(valArray, arrayItem); } } @@ -320,13 +370,69 @@ T2ERROR encodeParamResultInJSON(cJSON *valArray, Vector *paramNameList, Vector * } } - if(cJSON_AddStringToObject(valItem, paramValues[valIndex]->parameterName, paramValues[valIndex]->parameterValue) == NULL) - { - T2Error("cJSON_AddStringToObject failed\n"); - cJSON_Delete(arrayItem); - cJSON_Delete(valItem); - return T2ERROR_FAILURE; - } + switch(paramValues[valIndex]->type) { + case TR181_TYPE_BOOLEAN: { + bool b = false; + if(paramValues[valIndex]->parameterValue && + (strcasecmp(paramValues[valIndex]->parameterValue, "true") == 0 || + strcmp(paramValues[valIndex]->parameterValue, "1") == 0)) { + b = true; + } + if(cJSON_AddBoolToObject(valItem, paramValues[valIndex]->parameterName, b) == NULL){ + T2Error("cJSON_AddBoolToObject failed\n"); + cJSON_Delete(arrayItem); + cJSON_Delete(valItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_INT: + case TR181_TYPE_LONG: { + long long ll = paramValues[valIndex]->parameterValue ? strtoll(paramValues[valIndex]->parameterValue, NULL, 10) : 0; + if(cJSON_AddNumberToObject(valItem, paramValues[valIndex]->parameterName, (double) ll) == NULL){ + T2Error("cJSON_AddNumberToObject failed\n"); + cJSON_Delete(arrayItem); + cJSON_Delete(valItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_UNSIGNED: + case TR181_TYPE_UNSIGNED_LONG: { + unsigned long long ull = paramValues[valIndex]->parameterValue ? strtoull(paramValues[valIndex]->parameterValue, NULL, 10) : 0; + if(cJSON_AddNumberToObject(valItem, paramValues[valIndex]->parameterName, (double) ull) == NULL){ + T2Error("cJSON_AddNumberToObject failed\n"); + cJSON_Delete(arrayItem); + cJSON_Delete(valItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_FLOAT: + case TR181_TYPE_DOUBLE: { + double d = paramValues[valIndex]->parameterValue ? strtod(paramValues[valIndex]->parameterValue, NULL) : 0.0; + if(cJSON_AddNumberToObject(valItem, paramValues[valIndex]->parameterName, d) == NULL){ + T2Error("cJSON_AddNumberToObject failed\n"); + cJSON_Delete(arrayItem); + cJSON_Delete(valItem); + return T2ERROR_FAILURE; + } + break; + } + case TR181_TYPE_STRING: + case TR181_TYPE_DATETIME: + case TR181_TYPE_BASE64: + default: { + if(cJSON_AddStringToObject(valItem, paramValues[valIndex]->parameterName, paramValues[valIndex]->parameterValue) == NULL){ + T2Error("cJSON_AddStringToObject failed\n"); + cJSON_Delete(arrayItem); + cJSON_Delete(valItem); + return T2ERROR_FAILURE; + } + break; + } + } + // end switch cJSON_AddItemToArray(valList, valItem); isTableEmpty = false ; }