Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b1394e3
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
yogeswaransky Sep 7, 2025
8a064a9
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 9, 2025
2d6de88
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
yogeswaransky Sep 12, 2025
ca243b7
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 14, 2025
897810a
Merge branch 'topic/RDK-58546' of https://github.com/rdkcentral/telem…
Sep 14, 2025
3c9ca7d
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 15, 2025
58b8a84
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 15, 2025
b5d7e55
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 15, 2025
f0456c7
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
yogeswaransky Sep 16, 2025
7412d7d
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
yogeswaransky Sep 16, 2025
0ff8c66
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
0fdb6ef
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
12fe3ef
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
c058501
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
e9f88cc
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
977ded3
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
0950a57
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 17, 2025
d6a8de5
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 18, 2025
c62e1d5
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 18, 2025
462d472
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 19, 2025
410cfee
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 19, 2025
153f170
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
e2971ef
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
353dfcd
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
91d5030
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
731a7d0
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
c05c410
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
8bc58d9
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
1707e57
RDK-58546: [POC] T2 Thread And Curl Connection Pool Addition For Effi…
Sep 22, 2025
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
327 changes: 22 additions & 305 deletions source/protocol/http/curlinterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "t2MtlsUtils.h"
#include "t2log_wrapper.h"
#include "busInterface.h"
#include "../xconf-client/multicurlinterface.h"
#ifdef LIBRDKCERTSEL_BUILD
#include "rdkcertselector.h"
#define FILESCHEME "file://"
Expand All @@ -58,18 +59,20 @@ typedef struct
} childResponse ;

#ifdef LIBRDKCERTSEL_BUILD
#if 0
static rdkcertselector_h curlCertSelector = NULL;
static rdkcertselector_h curlRcvryCertSelector = NULL;
#endif
#endif

#if defined(ENABLE_RDKB_SUPPORT) && !defined(RDKB_EXTENDER)

#if defined(WAN_FAILOVER_SUPPORTED) || defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)
static char waninterface[256];
#endif
#endif
static pthread_once_t curlFileMutexOnce = PTHREAD_ONCE_INIT;
static pthread_mutex_t curlFileMutex;
//static pthread_once_t curlFileMutexOnce = PTHREAD_ONCE_INIT;
//static pthread_mutex_t curlFileMutex;

typedef enum _ADDRESS_TYPE
{
Expand All @@ -78,18 +81,22 @@ typedef enum _ADDRESS_TYPE
ADDR_IPV6
} ADDRESS_TYPE;

#if 0
static void sendOverHTTPInit()
{
pthread_mutex_init(&curlFileMutex, NULL);
}



static size_t writeToFile(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t written = fwrite(ptr, size, nmemb, (FILE *) stream);
return written;
}
#endif

#if 0
static T2ERROR setHeader(CURL *curl, const char* destURL, struct curl_slist **headerList, childResponse *childCurlResponse)
{

Expand Down Expand Up @@ -306,328 +313,38 @@ static void curlCertSelectorInit()
}
#endif

#endif

T2ERROR sendReportOverHTTP(char *httpUrl, char *payload, pid_t* outForkedPid)
{
CURL *curl = NULL;
FILE *fp = NULL;
CURLcode code = CURLE_OK;
T2ERROR ret = T2ERROR_FAILURE;
childResponse childCurlResponse = {0};
struct curl_slist *headerList = NULL;
CURLcode curl_code = CURLE_OK;
#ifdef LIBRDKCERTSEL_BUILD
rdkcertselector_h thisCertSel = NULL;
rdkcertselectorStatus_t curlGetCertStatus;
char *pCertURI = NULL;
char *pEngine = NULL;
bool state_red_enable = false;
#endif
char *pCertFile = NULL;
char *pCertPC = NULL;
#ifdef LIBRDKCONFIG_BUILD
size_t sKey = 0;
#endif
long http_code;
bool mtls_enable = false;
pid_t childPid;
int sharedPipeFds[2];

T2Debug("%s ++in\n", __FUNCTION__);
T2Info("%s ++in\n", __FUNCTION__);
if(httpUrl == NULL || payload == NULL)
{
return ret;
}
if(pipe(sharedPipeFds) != 0)
{
T2Error("Failed to create pipe !!! exiting...\n");
T2Debug("%s --out\n", __FUNCTION__);
return ret;
}
#ifdef LIBRDKCERTSEL_BUILD
curlCertSelectorInit();
state_red_enable = isStateRedEnabled();
T2Info("%s: state_red_enable: %d\n", __func__, state_red_enable );

if (state_red_enable)
{
thisCertSel = curlRcvryCertSelector;
}
else
{
thisCertSel = curlCertSelector;
}
#endif
#if defined(ENABLE_RDKB_SUPPORT) && !defined(RDKB_EXTENDER)

#if defined(WAN_FAILOVER_SUPPORTED) || defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)
char *paramVal = NULL;
memset(waninterface, 0, sizeof(waninterface));
snprintf(waninterface, sizeof(waninterface), "%s", INTERFACE);
// Use new dedicated POST API
ret = http_pool_post(httpUrl, payload);

if(T2ERROR_SUCCESS == getParameterValue(TR181_DEVICE_CURRENT_WAN_IFNAME, &paramVal))
if(ret == T2ERROR_SUCCESS)
{
if(strlen(paramVal) > 0)
{
memset(waninterface, 0, sizeof(waninterface));
snprintf(waninterface, sizeof(waninterface), "%s", paramVal);
}

free(paramVal);
paramVal = NULL;
T2Info("Report Sent Successfully over HTTP using connection pool\n");
}
else
{
T2Error("Failed to get Value for %s\n", TR181_DEVICE_CURRENT_WAN_IFNAME);
T2Error("Failed to send report using connection pool\n");
}
#endif
#endif
mtls_enable = isMtlsEnabled();
#ifndef LIBRDKCERTSEL_BUILD
if(mtls_enable == true && T2ERROR_SUCCESS != getMtlsCerts(&pCertFile, &pCertPC))
{
T2Error("mTLS_cert get failed\n");
if(NULL != pCertFile)
{
free(pCertFile);
}
if(NULL != pCertPC)
{
#ifdef LIBRDKCONFIG_BUILD
sKey = strlen(pCertPC);
if (rdkconfig_free((unsigned char**)&pCertPC, sKey) == RDKCONFIG_FAIL)
{
return T2ERROR_FAILURE;
}
#else
free(pCertPC);
#endif
}
return ret;
}
#endif
// Block the userdefined signal handlers before fork
pthread_sigmask(SIG_BLOCK, &blocking_signal, NULL);
if((childPid = fork()) < 0)
{
T2Error("Failed to fork !!! exiting...\n");
// Unblock the userdefined signal handler
#ifndef LIBRDKCERTSEL_BUILD
if(NULL != pCertFile)
{
free(pCertFile);
}
if(NULL != pCertPC)
{
#ifdef LIBRDKCONFIG_BUILD
sKey = strlen(pCertPC);
if (rdkconfig_free((unsigned char**)&pCertPC, sKey) == RDKCONFIG_FAIL)
{
return T2ERROR_FAILURE;
}
#else
free(pCertPC);
#endif
}
#endif
pthread_sigmask(SIG_UNBLOCK, &blocking_signal, NULL);
T2Debug("%s --out\n", __FUNCTION__);
return T2ERROR_FAILURE;
}

/**
* Openssl has growing RSS which gets cleaned up only with OPENSSL_cleanup .
* This cleanup is not thread safe and classified as run once per application life cycle.
* Forking the libcurl calls so that it executes and terminates to release memory per execution.
*/
if(childPid == 0)
{
curl = curl_easy_init();
if(curl)
{
childCurlResponse.curlStatus = true;
if(setHeader(curl, httpUrl, &headerList, &childCurlResponse) != T2ERROR_SUCCESS)
{
curl_easy_cleanup(curl);
goto child_cleanReturn;
}
if (setPayload(curl, payload, &childCurlResponse) != T2ERROR_SUCCESS)
{
curl_easy_cleanup(curl); // CID 189985: Resource leak
goto child_cleanReturn;
}
#ifdef LIBRDKCERTSEL_BUILD
pEngine = rdkcertselector_getEngine(thisCertSel);
if(pEngine != NULL)
{
code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine);
}
else
{
code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
}
if(code != CURLE_OK)
{
curl_easy_cleanup(curl);
goto child_cleanReturn;
}
do
{
pCertFile = NULL;
pCertPC = NULL;
pCertURI = NULL;
curlGetCertStatus = rdkcertselector_getCert(thisCertSel, &pCertURI, &pCertPC);
if(curlGetCertStatus != certselectorOk)
{
T2Error("%s, T2:Failed to retrieve the certificate.\n", __func__);
curlCertSelectorFree();
curl_easy_cleanup(curl);
goto child_cleanReturn;
}
else
{
// skip past file scheme in URI
pCertFile = pCertURI;
if ( strncmp( pCertFile, FILESCHEME, sizeof(FILESCHEME) - 1 ) == 0 )
{
pCertFile += (sizeof(FILESCHEME) - 1);
}
#endif
if((mtls_enable == true) && (setMtlsHeaders(curl, pCertFile, pCertPC, &childCurlResponse) != T2ERROR_SUCCESS))
{
curl_easy_cleanup(curl); // CID 189985: Resource leak
goto child_cleanReturn;
}
pthread_once(&curlFileMutexOnce, sendOverHTTPInit);
pthread_mutex_lock(&curlFileMutex);

fp = fopen(CURL_OUTPUT_FILE, "wb");
if(fp)
{
/* CID 143029 Unchecked return value from library */
code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)fp);
if(code != CURLE_OK)
{
// This might not be working we need to review this
childCurlResponse.curlSetopCode = code;
}
curl_code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if(curl_code != CURLE_OK || http_code != 200)
{
#ifdef LIBRDKCERTSEL_BUILD
T2Error("%s: Failed to establish connection using xPKI certificate: %s, curl failed: %d\n", __func__, pCertFile, curl_code);
#endif
fprintf(stderr, "curl failed: %s\n", curl_easy_strerror(curl_code));
childCurlResponse.lineNumber = __LINE__;
}
else
{
T2Info("%s: Using xpki Certs connection certname: %s\n", __func__, pCertFile);
childCurlResponse.lineNumber = __LINE__;
}
childCurlResponse.curlResponse = curl_code;
childCurlResponse.http_code = http_code;

fclose(fp);
}
pthread_mutex_unlock(&curlFileMutex);
#ifdef LIBRDKCERTSEL_BUILD
}
}
while(rdkcertselector_setCurlStatus(thisCertSel, curl_code, (const char*)httpUrl) == TRY_ANOTHER);
#endif
curl_slist_free_all(headerList);
curl_easy_cleanup(curl);
}
else
{
childCurlResponse.curlStatus = false;
}

child_cleanReturn :
#ifndef LIBRDKCERTSEL_BUILD
if(NULL != pCertFile)
{
free(pCertFile);
}

if(NULL != pCertPC)
{
#ifdef LIBRDKCONFIG_BUILD
sKey = strlen(pCertPC);
if (rdkconfig_free((unsigned char**)&pCertPC, sKey) == RDKCONFIG_FAIL)
{
return T2ERROR_FAILURE;
}
#else
free(pCertPC);
#endif
}
#endif
close(sharedPipeFds[0]);
if( -1 == write(sharedPipeFds[1], &childCurlResponse, sizeof(childResponse)))
{
fprintf(stderr, "unable to write to shared pipe from pid : %d \n", getpid());
T2Error("unable to write \n");
}
close(sharedPipeFds[1]);
exit(0);

}
else
// Set outForkedPid to 0 since we're not forking anymore
if(outForkedPid)
{
T2ERROR ret = T2ERROR_FAILURE;
if(outForkedPid)
{
*outForkedPid = childPid ;
}
// Use waitpid insted of wait we can have multiple child process
waitpid(childPid, NULL, 0);
// Unblock the userdefined signal handlers before fork
pthread_sigmask(SIG_UNBLOCK, &blocking_signal, NULL);
// Get the return status via IPC from child process
if ( -1 == close(sharedPipeFds[1]))
{
T2Error("Failed in close \n");
}
if( -1 == read(sharedPipeFds[0], &childCurlResponse, sizeof(childResponse)))
{
T2Error("unable to read from the pipe \n");
}
if ( -1 == close(sharedPipeFds[0]))
{
T2Error("Failed in close the pipe\n");
}
#ifndef LIBRDKCERTSEL_BUILD
if(NULL != pCertFile)
{
free(pCertFile);
}
if(NULL != pCertPC)
{
#ifdef LIBRDKCONFIG_BUILD
sKey = strlen(pCertPC);
if (rdkconfig_free((unsigned char**)&pCertPC, sKey) == RDKCONFIG_FAIL)
{
return T2ERROR_FAILURE;
}
#else
free(pCertPC);
#endif
}
#endif
T2Info("The return status from the child with pid %d is CurlStatus : %d\n", childPid, childCurlResponse.curlStatus);
//if(childCurlResponse.curlStatus == CURLE_OK) commenting this as we are observing childCurlResponse.curlStatus as 1, from line with CID 143029 Unchecked return value from library
T2Info("The return status from the child with pid %d SetopCode: %s; ResponseCode : %s; HTTP_CODE : %ld; Line Number : %d \n", childPid, curl_easy_strerror(childCurlResponse.curlSetopCode), curl_easy_strerror(childCurlResponse.curlResponse), childCurlResponse.http_code, childCurlResponse.lineNumber);
if (childCurlResponse.http_code == 200 || childCurlResponse.curlResponse == CURLE_OK)
{
ret = T2ERROR_SUCCESS;
T2Info("Report Sent Successfully over HTTP : %ld\n", childCurlResponse.http_code);
}
T2Debug("%s --out\n", __FUNCTION__);
return ret;
*outForkedPid = 0;
}

T2Info("%s --out\n", __FUNCTION__);
return ret;
}

T2ERROR sendCachedReportsOverHTTP(char *httpUrl, Vector *reportList)
Expand Down
Loading
Loading