Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
86b503b
Update rrdInterface.h
Abhinavpv28 Apr 8, 2026
c9587f0
Update rrdInterface.h
Abhinavpv28 Apr 8, 2026
8b712e9
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
28ba654
Update rrdInterface.h
Abhinavpv28 Apr 8, 2026
2a7dcba
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
81cc501
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
bb266ac
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
48f1a70
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
588db7a
Update rrdInterface.c
Abhinavpv28 Apr 8, 2026
71e27f3
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
4639540
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
6f34dd2
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
72c6e36
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
b651cf2
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
b5e0f60
Add helper functions for profile data processing
Abhinavpv28 Apr 10, 2026
9797e9e
Update rrdInterface.c
Abhinavpv28 Apr 10, 2026
394c0e3
Update rrdInterface.h
Abhinavpv28 Apr 10, 2026
46281d3
Update Client_Mock.h
Abhinavpv28 Apr 10, 2026
f68941b
Add mock implementations for RBusApiWrapper methods
Abhinavpv28 Apr 10, 2026
a3c4abe
Remove mock profile handler functions for GTEST
Abhinavpv28 Apr 10, 2026
cfbefff
Update Client_Mock.cpp
Abhinavpv28 Apr 10, 2026
a9984c7
Update Client_Mock.h
Abhinavpv28 Apr 10, 2026
2ee0aaa
Update rrdInterface.h
Abhinavpv28 Apr 10, 2026
244cb3f
Update Makefile.am
Abhinavpv28 Apr 10, 2026
b0069c0
Update src/rrdInterface.c
Abhinavpv28 Apr 10, 2026
80fa8af
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 10, 2026
71560b5
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 10, 2026
1f25d18
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
a25d7a5
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
351899d
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
1d7601a
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
2571992
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
c0efadc
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
110f4c7
Create profileTestValid.json
Abhinavpv28 Apr 13, 2026
21dbcc4
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
dc44dad
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
9da608c
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
6aae47f
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
349f9f2
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
bdbb0f4
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
ea84c80
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
4f602e6
Update rrdUnitTestRunner.cpp
Abhinavpv28 Apr 13, 2026
e9de8bd
Create profileTestInvalid.json
Abhinavpv28 Apr 13, 2026
b224fe8
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
38cd181
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
73a52ec
Update rrdInterface.c
Abhinavpv28 Apr 13, 2026
4ea416c
Update rrdInterface.c
Abhinavpv28 Apr 14, 2026
81780e1
Update rrdInterface.c
Abhinavpv28 Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
328 changes: 328 additions & 0 deletions src/rrdInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,73 @@ key_t key = 1234;
uint32_t gWebCfgBloBVersion = 0;
rbusHandle_t rrdRbusHandle;

// Global storage for profile category
char RRDProfileCategory[256] = "all";
#define MAX_PROFILE_JSON_SIZE 32768

// Helper functions for profile category file-based storage
int load_profile_category(void) {
FILE *fp = fopen(RRD_PROFILE_CATEGORY_FILE, "r");
if (fp) {
if (fgets(RRDProfileCategory, sizeof(RRDProfileCategory), fp)) {
// Remove trailing newline
char *newline = strchr(RRDProfileCategory, '\n');
if (newline) *newline = '\0';
fclose(fp);
return 0;
}
fclose(fp);
}
// Default to "all" if file doesn't exist or read fails
strncpy(RRDProfileCategory, "all", sizeof(RRDProfileCategory) - 1);
RRDProfileCategory[sizeof(RRDProfileCategory) - 1] = '\0';
return -1;
}

int save_profile_category(void) {
FILE *fp = fopen(RRD_PROFILE_CATEGORY_FILE, "w");
if (fp) {
fprintf(fp, "%s\n", RRDProfileCategory);
fclose(fp);
return 0;
}
return -1;
}

#define DATA_HANDLER_SET_MACRO \
{ \
NULL, \
rrd_SetHandler, \
NULL, \
NULL, \
NULL, \
NULL \
}

#define DATA_HANDLER_GET_MACRO \
{ \
rrd_GetHandler, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL \
}

// Data elements for profile data RBUS provider
rbusDataElement_t profileDataElements[2] = {
{
RRD_SET_PROFILE_EVENT,
RBUS_ELEMENT_TYPE_PROPERTY,
DATA_HANDLER_SET_MACRO
},
{
RRD_GET_PROFILE_EVENT,
RBUS_ELEMENT_TYPE_PROPERTY,
DATA_HANDLER_GET_MACRO
}
};

/*Function: RRD_subscribe
*Details: This helps to perform Bus init/connect and event handler registration for receiving
*events from the TR181 parameter.
Expand Down Expand Up @@ -103,6 +170,21 @@ int RRD_subscribe()
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: SUCCESS: RBUS Event Subscribe for RRD done! \n", __FUNCTION__, __LINE__);
}

// Load profile category from file
if (load_profile_category() == 0) {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Loaded profile category: %s\n", __FUNCTION__, __LINE__, RRDProfileCategory);
} else {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: No stored profile category, defaulting to 'all'\n", __FUNCTION__, __LINE__);
}

// Register RBUS data elements for profile data provider
ret = rbus_regDataElements(rrdRbusHandle, 2, profileDataElements);
if (ret != RBUS_ERROR_SUCCESS) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: RBUS regDataElements failed with error: %d\n", __FUNCTION__, __LINE__, ret);
} else {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: SUCCESS: RBUS profile data elements registered\n", __FUNCTION__, __LINE__);
}

webconfigFrameworkInit();
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: ...Exiting.. \n", __FUNCTION__, __LINE__);
return ret;
Expand Down Expand Up @@ -428,6 +510,14 @@ int RRD_unsubscribe()
return ret;
}

// Unregister RBUS data elements for profile data provider
ret = rbus_unregDataElements(rrdRbusHandle, 2, profileDataElements);
if (ret != 0) {
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RRD_unsubscribe checks if (ret != 0) after rbus_unregDataElements, but RBUS APIs conventionally use RBUS_ERROR_SUCCESS for success. For consistency with the subscribe path (and to avoid misclassifying non-zero success codes), compare against RBUS_ERROR_SUCCESS.

Suggested change
if (ret != 0) {
if (ret != RBUS_ERROR_SUCCESS) {

Copilot uses AI. Check for mistakes.
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: RBUS unregDataElements failed with error: %d\n", __FUNCTION__, __LINE__, ret);
} else {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: SUCCESS: RBUS profile data elements unregistered\n", __FUNCTION__, __LINE__);
}
Comment on lines +513 to +519
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In RRD_unsubscribe, the rbus_unregDataElements result is checked with ret != 0 instead of ret != RBUS_ERROR_SUCCESS (as used elsewhere). Prefer comparing against RBUS_ERROR_SUCCESS for clarity/consistency and to avoid assumptions about enum values.

Copilot uses AI. Check for mistakes.

ret = rbus_close(rrdRbusHandle);
if (ret != 0)
{
Expand All @@ -443,3 +533,241 @@ int RRD_unsubscribe()
#endif
return ret;
}
/**
* @brief Set handler for RDK Remote Debugger profile category selection
*/
rbusError_t rrd_SetHandler(rbusHandle_t handle, rbusProperty_t prop, rbusSetHandlerOptions_t* opts)
{
(void)handle;
(void)opts;

char const* propertyName = rbusProperty_GetName(prop);
rbusValue_t value = rbusProperty_GetValue(prop);
rbusValueType_t type = rbusValue_GetType(value);

RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Set handler called for [%s]\n", __FUNCTION__, __LINE__, propertyName);

if(strcmp(propertyName, RRD_SET_PROFILE_EVENT) == 0) {
if (type == RBUS_STRING) {
const char* str = rbusValue_GetString(value, NULL);
if(strlen(str) > 255) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: String too long for setProfileData\n", __FUNCTION__, __LINE__);
return RBUS_ERROR_INVALID_INPUT;
}

strncpy(RRDProfileCategory, str, sizeof(RRDProfileCategory)-1);
RRDProfileCategory[sizeof(RRDProfileCategory)-1] = '\0';
RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "[%s:%d]: setProfileData value: %s\n", __FUNCTION__, __LINE__, RRDProfileCategory);

// Store the category selection to file
if(save_profile_category() != 0) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Failed to store profile category\n", __FUNCTION__, __LINE__);
return RBUS_ERROR_BUS_ERROR;
}

RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "[%s:%d]: Successfully set profile category to: %s\n", __FUNCTION__, __LINE__, RRDProfileCategory);
return RBUS_ERROR_SUCCESS;
} else {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Invalid type for setProfileData\n", __FUNCTION__, __LINE__);
return RBUS_ERROR_INVALID_INPUT;
}
}

return RBUS_ERROR_INVALID_INPUT;
}

/**
* @brief Check if a category has direct commands (not nested structure)
*/
bool has_direct_commands(cJSON *category)
{
cJSON *item = NULL;
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_direct_commands will crash if category is NULL (the function is called with NULL in tests). Add an early if (!category) return false; before cJSON_ArrayForEach.

Suggested change
cJSON *item = NULL;
cJSON *item = NULL;
if (!category) {
return false;
}

Copilot uses AI. Check for mistakes.
cJSON_ArrayForEach(item, category) {
if (cJSON_IsObject(item)) {
cJSON *commands = cJSON_GetObjectItem(item, "Commands");
if (commands && cJSON_IsString(commands)) {
return true;
}
Comment on lines +580 to +590
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_direct_commands()/get_all_categories_json() currently assume each issue type is a JSON object containing a string field named "Commands". However, the existing remote_debugger.json schema used by the command executor stores issue types as arrays (see getIssueCommandInfo in src/rrdJsonParser.c:302-320), so has_direct_commands() will return false for all real categories and rrd_GetHandler will likely return an empty object/array. Please update the parsing to match the actual profile JSON schema (or point rrd_GetHandler at the correct file/schema).

Suggested change
* @brief Check if a category has direct commands (not nested structure)
*/
bool has_direct_commands(cJSON *category)
{
cJSON *item = NULL;
cJSON_ArrayForEach(item, category) {
if (cJSON_IsObject(item)) {
cJSON *commands = cJSON_GetObjectItem(item, "Commands");
if (commands && cJSON_IsString(commands)) {
return true;
}
* @brief Check whether an issue-type entry contains direct commands.
*
* The active profile schema stores issue types as arrays of command entries.
* Keep compatibility with the older object-based form that used a "Commands"
* string field.
*/
static bool issue_type_has_direct_commands(cJSON *issueType)
{
if(issueType == NULL)
{
return false;
}
if(cJSON_IsArray(issueType))
{
return cJSON_GetArraySize(issueType) > 0;
}
if(cJSON_IsObject(issueType))
{
cJSON *commands = cJSON_GetObjectItem(issueType, "Commands");
if(commands && cJSON_IsString(commands))
{
return true;
}
}
return false;
}
/**
* @brief Check if a category has direct commands (not nested structure)
*/
bool has_direct_commands(cJSON *category)
{
cJSON *item = NULL;
if(category == NULL)
{
return false;
}
cJSON_ArrayForEach(item, category) {
if(issue_type_has_direct_commands(item)) {
return true;

Copilot uses AI. Check for mistakes.
}
Comment on lines +588 to +591
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The has_direct_commands detection logic only finds a Commands string directly under each child object. The existing profile parsing code uses a different schema (issue types map to arrays of values/commands, e.g. typeX: [ 42, "cmd" ] in rrdJsonParser.c:302-338), so this will return false and cause get_all_categories_json/get_specific_category_json to return empty results for the current profile format. Update this helper to recognize the actual profile structure (or remove the gate) so the RBUS get handler returns meaningful category lists.

Suggested change
if (commands && cJSON_IsString(commands)) {
return true;
}
}
if (commands) {
if (cJSON_IsString(commands)) {
return true;
}
if (cJSON_IsArray(commands)) {
cJSON *command_item = NULL;
cJSON_ArrayForEach(command_item, commands) {
if (cJSON_IsString(command_item)) {
return true;
}
}
}
}
}
/*
* Current profile format stores issue types directly as arrays,
* e.g. "typeX": [ 42, "cmd" ]. Recognize that schema as well.
*/
if (cJSON_IsArray(item)) {
cJSON *array_item = NULL;
cJSON_ArrayForEach(array_item, item) {
if (cJSON_IsString(array_item)) {
return true;
}
}
}

Copilot uses AI. Check for mistakes.
}
return false;
}

/**
* @brief Read and validate JSON profile file
*/
char* read_profile_json_file(const char* filename, long* file_size)
{
FILE *fp = fopen(filename, "rb");
if (!fp) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Unable to read profile file from %s\n", __FUNCTION__, __LINE__, filename);
return NULL;
}

fseek(fp, 0L, SEEK_END);
long fileSz = ftell(fp);
rewind(fp);

if (fileSz <= 0 || fileSz >= MAX_PROFILE_JSON_SIZE) {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Invalid file size: %ld\n", __FUNCTION__, __LINE__, fileSz);
fclose(fp);
return NULL;
}
Comment on lines +609 to +615
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read_profile_json_file() is called from unit tests with a null filename, but the implementation calls fopen(filename, ...) and logs filename with "%s" unconditionally. Passing NULL will crash (and file_size is also dereferenced without a NULL check). Add guards like if (!filename || !file_size) return NULL; and ensure *file_size is set to 0 on failure.

Copilot uses AI. Check for mistakes.

char *jsonBuffer = malloc(fileSz + 1);
if (!jsonBuffer) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Memory allocation failed for JSON buffer\n", __FUNCTION__, __LINE__);
fclose(fp);
return NULL;
}

size_t bytesRead = fread(jsonBuffer, 1U, (size_t)fileSz, fp);
jsonBuffer[bytesRead] = '\0';
fclose(fp);

*file_size = fileSz;
return jsonBuffer;
}

/**
* @brief Generate JSON for all categories
*/
char* get_all_categories_json(cJSON* json)
{
cJSON *response = cJSON_CreateObject();

cJSON *category = NULL;
cJSON_ArrayForEach(category, json) {
if (cJSON_IsObject(category) && category->string) {
if (has_direct_commands(category)) {
// Create array for this category's issue types
cJSON *issueTypesArray = cJSON_CreateArray();
cJSON *issueType = NULL;
cJSON_ArrayForEach(issueType, category) {
if (cJSON_IsObject(issueType) && issueType->string) {
cJSON_AddItemToArray(issueTypesArray, cJSON_CreateString(issueType->string));
}
}

// Add this category and its issue types to response
if (cJSON_GetArraySize(issueTypesArray) > 0) {
cJSON_AddItemToObject(response, category->string, issueTypesArray);
} else {
cJSON_Delete(issueTypesArray);
Comment on lines +645 to +656
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_all_categories_json() assumes json is non-NULL and uses cJSON_ArrayForEach(category, json), which will crash when json == NULL. There is a unit test that calls get_all_categories_json(nullptr). Handle NULL input explicitly (e.g., return "{}" or NULL) and update the test to assert the expected behavior.

Copilot uses AI. Check for mistakes.
}
}
}
}

char *result_str = cJSON_Print(response);
cJSON_Delete(response);
return result_str;
}

/**
* @brief Generate JSON for specific category
*/
char* get_specific_category_json(cJSON* json, const char* category_name)
{
cJSON *category = cJSON_GetObjectItem(json, category_name);
if (!category || !cJSON_IsObject(category)) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Category %s not found, falling back to all categories\n", __FUNCTION__, __LINE__, category_name);
return get_all_categories_json(json);
}

if (!has_direct_commands(category)) {
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Category %s has nested structure, returning empty\n",
__FUNCTION__, __LINE__, category_name);
return cJSON_Print(cJSON_CreateArray());
}

cJSON *issueTypes = cJSON_CreateArray();
cJSON *issueType = NULL;
cJSON_ArrayForEach(issueType, category) {
if (cJSON_IsObject(issueType) && issueType->string) {
Comment on lines +679 to +687
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_specific_category_json() calls cJSON_GetObjectItem(json, category_name) without checking json/category_name for NULL, and on the not-found path returns cJSON_Print(cJSON_CreateArray()) without deleting the created array (memory leak). Add NULL checks and avoid leaking the temporary cJSON by creating->printing->deleting before returning.

Copilot uses AI. Check for mistakes.
cJSON_AddItemToArray(issueTypes, cJSON_CreateString(issueType->string));
}
}

char *result_str = cJSON_Print(issueTypes);
cJSON_Delete(issueTypes);
return result_str;
}

/**
* @brief Set RBUS property response with JSON string
*/
rbusError_t set_rbus_response(rbusProperty_t prop, const char* json_str)
{
if (!json_str) {
return RBUS_ERROR_BUS_ERROR;
}

rbusValue_t rbusValue;
rbusValue_Init(&rbusValue);
rbusValue_SetString(rbusValue, json_str);
rbusProperty_SetValue(prop, rbusValue);
rbusValue_Release(rbusValue);

RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Successfully returned profile data\n", __FUNCTION__, __LINE__);
return RBUS_ERROR_SUCCESS;
}

/**
* @brief Get handler for RDK Remote Debugger profile data retrieval
*/
rbusError_t rrd_GetHandler(rbusHandle_t handle, rbusProperty_t prop, rbusGetHandlerOptions_t* opts)
{
(void)handle;
(void)opts;

char const* propertyName = rbusProperty_GetName(prop);
Comment on lines +710 to +724
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_rbus_response() ignores return codes from rbusValue_Init / rbusValue_SetString and doesn’t validate prop. If rbusValue_Init fails (or prop is NULL), the function can misbehave or crash while still returning SUCCESS. Check for NULL/failed return values and propagate an appropriate RBUS error code.

Copilot uses AI. Check for mistakes.
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Get handler called for [%s]\n", __FUNCTION__, __LINE__, propertyName);

if(strcmp(propertyName, RRD_GET_PROFILE_EVENT) != 0) {
return RBUS_ERROR_INVALID_INPUT;
}

const char *filename = "/etc/rrd/remote_debugger.json";
long file_size;

// Read JSON file
char *jsonBuffer = read_profile_json_file(filename, &file_size);
if (!jsonBuffer) {
return RBUS_ERROR_BUS_ERROR;
}

// Parse JSON
cJSON *json = cJSON_Parse(jsonBuffer);
if (!json) {
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Failed to parse JSON from %s\n", __FUNCTION__, __LINE__, filename);
free(jsonBuffer);
return RBUS_ERROR_BUS_ERROR;
}

RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: JSON parsed successfully, processing categories\n", __FUNCTION__, __LINE__);

// Generate appropriate JSON response
char *result_str = NULL;
if (strlen(RRDProfileCategory) == 0 || strcmp(RRDProfileCategory, "all") == 0) {
result_str = get_all_categories_json(json);
} else {
result_str = get_specific_category_json(json, RRDProfileCategory);
}

// Set RBUS response
rbusError_t error = set_rbus_response(prop, result_str);

// Log success if getHandler completed successfully
if (error == RBUS_ERROR_SUCCESS) {
RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "[%s:%d]: getHandler completed successfully for property [%s] with category [%s]\n",
__FUNCTION__, __LINE__, propertyName, RRDProfileCategory);
}

// Cleanup
cJSON_Delete(json);
free(jsonBuffer);
free(result_str);

return error;
}
15 changes: 15 additions & 0 deletions src/rrdInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C"
#include "rrdCommon.h"
#if !defined(GTEST_ENABLE)
#include "rbus.h"
#include <cjson/cJSON.h>
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#include <cjson/cJSON.h> is inconsistent with the rest of the codebase, which includes cJSON as "cJSON.h" (e.g., src/rrdJsonParser.h:29, src/rrdCommandSanity.h:28). Using a different include path risks breaking builds depending on include search paths; align this include with the existing convention or ensure the build explicitly provides the cjson/cJSON.h path.

Suggested change
#include <cjson/cJSON.h>
#include "cJSON.h"

Copilot uses AI. Check for mistakes.
#ifdef IARMBUS_SUPPORT
#include "libIARM.h"
#include "libIBus.h"
Comment on lines 30 to 35
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The profile helper-function declarations (and the cJSON include they require) are wrapped in #if !defined(GTEST_ENABLE), which makes them unavailable to unit-test builds that define GTEST_ENABLE. If unit tests call these helpers, this forces ad-hoc forward declarations elsewhere or reliance on non-standard compile flags. Consider moving the helper declarations (and either a cJSON forward declaration or the include) outside the !GTEST_ENABLE guard, or splitting the guard so only the production-only rbus.h include is conditional.

Copilot uses AI. Check for mistakes.
Expand All @@ -45,6 +46,11 @@ extern "C"
#define RRD_PROCESS_NAME "remotedebugger"
#define RRD_RBUS_TIMEOUT 60

// RDK Remote Debugger profile data parameter definitions
#define RRD_SET_PROFILE_EVENT "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.setProfileData"
#define RRD_GET_PROFILE_EVENT "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.getProfileData"
#define RRD_PROFILE_CATEGORY_FILE "/tmp/rrd_profile_category"
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The profile category is persisted under /tmp (RRD_PROFILE_CATEGORY_FILE). If this process runs with elevated privileges, writing to a fixed path in a world-writable directory via fopen("w") is vulnerable to symlink/hardlink attacks (clobbering arbitrary files). Consider storing this state under a protected directory (e.g., /var/run//opt) or use a secure open() pattern (O_NOFOLLOW, O_CREAT|O_TRUNC, 0600) and then fdopen().

Suggested change
#define RRD_PROFILE_CATEGORY_FILE "/tmp/rrd_profile_category"
#define RRD_PROFILE_CATEGORY_FILE "/var/run/rrd_profile_category"

Copilot uses AI. Check for mistakes.

/*Enum for IARM Events*/
typedef enum _RemoteDebugger_EventId_t {
IARM_BUS_RDK_REMOTE_DEBUGGER_ISSUETYPE = 0,
Expand All @@ -57,6 +63,13 @@ typedef enum _RemoteDebugger_EventId_t {
void _remoteDebuggerEventHandler(rbusHandle_t handle, rbusEvent_t const* event, rbusEventSubscription_t* subscription);
void _remoteDebuggerWebCfgDataEventHandler(rbusHandle_t handle, rbusEvent_t const* event, rbusEventSubscription_t* subscription);
void _rdmDownloadEventHandler(rbusHandle_t handle, rbusEvent_t const* event, rbusEventSubscription_t* subscription);

// Helper functions for profile data processing
bool has_direct_commands(cJSON *category);
char* read_profile_json_file(const char* filename, long* file_size);
char* get_all_categories_json(cJSON* json);
char* get_specific_category_json(cJSON* json, const char* category_name);
rbusError_t set_rbus_response(rbusProperty_t prop, const char* json_str);
#endif
#if defined(IARMBUS_SUPPORT) || defined(GTEST_ENABLE)
int RRD_IARM_subscribe(void);
Expand All @@ -73,6 +86,8 @@ void RRD_data_buff_deAlloc(data_buf *sbuf);
void RRDMsgDeliver(int msgqid, data_buf *sbuf);
int RRD_subscribe(void);
int RRD_unsubscribe(void);
rbusError_t rrd_SetHandler(rbusHandle_t handle, rbusProperty_t property, rbusSetHandlerOptions_t* opts);
rbusError_t rrd_GetHandler(rbusHandle_t handle, rbusProperty_t prop, rbusGetHandlerOptions_t* opts);
Comment on lines 88 to +90
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rrd_SetHandler / rrd_GetHandler are declared unconditionally but their parameter types come from RBUS headers, which are excluded when GTEST_ENABLE is defined. This makes rrdInterface.h non-self-contained for GTest builds unless callers include the mocks first. Wrap these declarations in #if !defined(GTEST_ENABLE) (like the other RBUS-only declarations) or provide forward declarations/typedefs so the header compiles on its own.

Suggested change
int RRD_unsubscribe(void);
rbusError_t rrd_SetHandler(rbusHandle_t handle, rbusProperty_t property, rbusSetHandlerOptions_t* opts);
rbusError_t rrd_GetHandler(rbusHandle_t handle, rbusProperty_t prop, rbusGetHandlerOptions_t* opts);
int RRD_unsubscribe(void);
#if !defined(GTEST_ENABLE)
rbusError_t rrd_SetHandler(rbusHandle_t handle, rbusProperty_t property, rbusSetHandlerOptions_t* opts);
rbusError_t rrd_GetHandler(rbusHandle_t handle, rbusProperty_t prop, rbusGetHandlerOptions_t* opts);
#endif

Copilot uses AI. Check for mistakes.

#ifdef __cplusplus
}
Expand Down
Loading
Loading