From 88d20b35a3d6fc1837b00a2ffcce77857a650b9f Mon Sep 17 00:00:00 2001 From: aelhosni Date: Thu, 30 Jul 2026 17:16:24 +0200 Subject: [PATCH] RDKBDEV-3472: Add collection and send timestamps to reports Add the collection timestamp (ts) during report generation and the send timestamp (sts) immediately before HTTP transmission. Store both timestamps as separate objects inside the Report array and gate the implementation with T2_ENABLE_STS_TS_TIMESTAMP. Preserve the original payload if JSON parsing or timestamp injection fails, and release the modified payload after transmission. Signed-off-by: aelhosni --- configure.ac | 19 +++++++++++ source/bulkdata/Makefile.am | 4 +++ source/bulkdata/profile.c | 29 ++++++++++++++++ source/protocol/http/Makefile.am | 4 +++ source/protocol/http/curlinterface.c | 50 ++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+) diff --git a/configure.ac b/configure.ac index 88424e12c..0c04f2365 100644 --- a/configure.ac +++ b/configure.ac @@ -170,6 +170,25 @@ AC_ARG_ENABLE([support-typing-fields], AM_CONDITIONAL([ENABLE_SUPPORT_TYPING_FIELDS], [test x$ENABLE_SUPPORT_TYPING_FIELDS = xtrue]) +ENABLE_T2_ENABLE_STS_TS_TIMESTAMP=false + +AC_ARG_ENABLE([t2-enable-sts-ts-timestamp], + [AS_HELP_STRING( + [--enable-t2-enable-sts-ts-timestamp], + [enable T2_ENABLE_STS_TS_TIMESTAMP (default is no)] + )], + [ + case "${enableval}" in + yes) ENABLE_T2_ENABLE_STS_TS_TIMESTAMP=true ;; + no) ENABLE_T2_ENABLE_STS_TS_TIMESTAMP=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-t2-enable-sts-ts-timestamp]) ;; + esac + ] +) + +AM_CONDITIONAL([ENABLE_T2_ENABLE_STS_TS_TIMESTAMP], + [test "x${ENABLE_T2_ENABLE_STS_TS_TIMESTAMP}" = "xtrue"]) + #privacy control flag IS_PRIVACYCONTROL_ENABLED=false AC_ARG_ENABLE([privacycontrol], diff --git a/source/bulkdata/Makefile.am b/source/bulkdata/Makefile.am index 78a5690ee..b122cddee 100644 --- a/source/bulkdata/Makefile.am +++ b/source/bulkdata/Makefile.am @@ -61,3 +61,7 @@ endif if IS_LIBRDKCERTSEL_ENABLED libbulkdata_la_CFLAGS = $(LIBRDKCERTSEL_FLAG) endif + +if ENABLE_T2_ENABLE_STS_TS_TIMESTAMP +libbulkdata_la_CPPFLAGS += -DT2_ENABLE_STS_TS_TIMESTAMP +endif diff --git a/source/bulkdata/profile.c b/source/bulkdata/profile.c index 029c75a8d..5127bd649 100644 --- a/source/bulkdata/profile.c +++ b/source/bulkdata/profile.c @@ -559,6 +559,35 @@ static void* CollectAndReport(void* data) { cJSON_AddItemToArray(valArray, triggercondition); } +#ifdef T2_ENABLE_STS_TS_TIMESTAMP + /* Add the collection timestamp as a separate object in Report[]. */ + if(valArray != NULL && cJSON_IsArray(valArray)) + { + struct timespec collectionTime; + if(clock_gettime(CLOCK_REALTIME, &collectionTime) == 0) + { + long long collectionTimeMs = + (long long)collectionTime.tv_sec * 1000LL + + collectionTime.tv_nsec / 1000000LL; + cJSON *timestamp = cJSON_CreateObject(); + if(timestamp != NULL) + { + if(cJSON_AddNumberToObject(timestamp, "ts", + (double)collectionTimeMs) != NULL) + { + if(!cJSON_AddItemToArray(valArray, timestamp)) + { + cJSON_Delete(timestamp); + } + } + else + { + cJSON_Delete(timestamp); + } + } + } + } +#endif ret = prepareJSONReport(profile->jsonReportObj, &jsonReport); destroyJSONReport(profile->jsonReportObj); profile->jsonReportObj = NULL; diff --git a/source/protocol/http/Makefile.am b/source/protocol/http/Makefile.am index 086ec6304..fc2fcda1d 100644 --- a/source/protocol/http/Makefile.am +++ b/source/protocol/http/Makefile.am @@ -34,3 +34,7 @@ libhttp_la_CPPFLAGS = -fPIC -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/dbus-1.0 \ -I${top_srcdir}/source/bulkdata \ -I${top_srcdir}/source/utils +if ENABLE_T2_ENABLE_STS_TS_TIMESTAMP +libhttp_la_CPPFLAGS += -DT2_ENABLE_STS_TS_TIMESTAMP +libhttp_la_LDFLAGS += -lcjson +endif diff --git a/source/protocol/http/curlinterface.c b/source/protocol/http/curlinterface.c index 695fa828a..b35d88ee5 100644 --- a/source/protocol/http/curlinterface.c +++ b/source/protocol/http/curlinterface.c @@ -31,6 +31,10 @@ #include #include #include +#ifdef T2_ENABLE_STS_TS_TIMESTAMP +#include +#include +#endif #include "curlinterface.h" #include "reportprofiles.h" @@ -73,6 +77,9 @@ typedef enum _ADDRESS_TYPE T2ERROR sendReportOverHTTP(char *httpUrl, char *payload) { T2ERROR ret = T2ERROR_FAILURE; +#ifdef T2_ENABLE_STS_TS_TIMESTAMP + char *payloadWithSts = NULL; +#endif T2Debug("%s ++in\n", __FUNCTION__); if(httpUrl == NULL || payload == NULL) @@ -80,7 +87,50 @@ T2ERROR sendReportOverHTTP(char *httpUrl, char *payload) return ret; } // Use new dedicated POST API +#ifdef T2_ENABLE_STS_TS_TIMESTAMP + cJSON *root = cJSON_Parse(payload); + if(root != NULL) + { + cJSON *report = cJSON_GetObjectItemCaseSensitive(root, "Report"); + if(report != NULL && cJSON_IsArray(report)) + { + struct timespec sendTime; + if(clock_gettime(CLOCK_REALTIME, &sendTime) == 0) + { + long long sendTimeMs = + (long long)sendTime.tv_sec * 1000LL + + sendTime.tv_nsec / 1000000LL; + cJSON *timestamp = cJSON_CreateObject(); + if(timestamp != NULL) + { + if(cJSON_AddNumberToObject(timestamp, "sts", + (double)sendTimeMs) != NULL) + { + if(cJSON_AddItemToArray(report, timestamp)) + { + payloadWithSts = cJSON_PrintUnformatted(root); + } + else + { + cJSON_Delete(timestamp); + } + } + else + { + cJSON_Delete(timestamp); + } + } + } + } + cJSON_Delete(root); + } + + ret = http_pool_post(httpUrl, + payloadWithSts != NULL ? payloadWithSts : payload); + free(payloadWithSts); +#else ret = http_pool_post(httpUrl, payload); +#endif if(ret == T2ERROR_SUCCESS) {