diff --git a/src/webcfg.h b/src/webcfg.h index 33b02b32..3a484317 100644 --- a/src/webcfg.h +++ b/src/webcfg.h @@ -25,8 +25,8 @@ /* Macros */ /*----------------------------------------------------------------------------*/ #define MAX_BUF_SIZE 256 -#define MAX_URL_LENGTH 768 #define MAX_PARAMETERNAME_LENGTH 512 +#define MAX_LBUFF_SIZE 8192 #ifdef BUILD_YOCTO #define DEVICE_PROPS_FILE "/etc/device.properties" diff --git a/src/webcfg_generic_pc.c b/src/webcfg_generic_pc.c index c09b3c25..e85c370d 100644 --- a/src/webcfg_generic_pc.c +++ b/src/webcfg_generic_pc.c @@ -122,7 +122,7 @@ char *getPartnerID(void) char *getAccountID(void) { - char *AI=strdup("unkown"); + char *AI=strdup("unknown"); return AI; } diff --git a/src/webcfg_multipart.c b/src/webcfg_multipart.c index ad84b6d2..aa9f0a08 100644 --- a/src/webcfg_multipart.c +++ b/src/webcfg_multipart.c @@ -205,8 +205,6 @@ WEBCFG_STATUS webcfg_http_request(char **configData, int r_count, int status, lo char *ct = NULL; char *webConfigURL = NULL; char *transID = NULL; - char *subdoclist = NULL; - char docList[512] = {'\0'}; char configURL[256] = { 0 }; char c[] = "{mac}"; int rv = 0; @@ -216,7 +214,6 @@ WEBCFG_STATUS webcfg_http_request(char **configData, int r_count, int status, lo struct token_data data; data.size = 0; void * dataVal = NULL; - char syncURL[MAX_URL_LENGTH]={'\0'}; char docname_upper[64]={'\0'}; curl = curl_easy_init(); @@ -231,17 +228,12 @@ WEBCFG_STATUS webcfg_http_request(char **configData, int r_count, int status, lo return WEBCFG_FAILURE; } data.data[0] = '\0'; - createCurlHeader(list, &headers_list, status, &transID, &subdoclist); + createCurlHeader(list, &headers_list, status, &transID); if(transID !=NULL) { *transaction_id = strdup(transID); WEBCFG_FREE(transID); } - if(subdoclist !=NULL) - { - strncpy(docList, subdoclist, sizeof(docList)-1); - WEBCFG_FREE(subdoclist); - } WebcfgInfo("The get_global_supplementarySync() is %d\n", get_global_supplementarySync()); if(get_global_supplementarySync() == 0) { @@ -318,17 +310,6 @@ WEBCFG_STATUS webcfg_http_request(char **configData, int r_count, int status, lo } WebcfgDebug("ConfigURL fetched is %s\n", webConfigURL); - if(!get_global_supplementarySync()) - { - if(strlen(docList) > 0) - { - WebcfgDebug("docList is %s\n", docList); - snprintf(syncURL, MAX_URL_LENGTH, "%s?group_id=%s", webConfigURL, docList); - WEBCFG_FREE(webConfigURL); - WebcfgDebug("syncURL is %s\n", syncURL); - webConfigURL =strdup( syncURL); - } - } if(webConfigURL !=NULL) { WebcfgInfo("Webconfig root ConfigURL is %s\n", webConfigURL); @@ -1464,7 +1445,7 @@ void derive_root_doc_version_string(char **rootVersion, uint32_t *root_ver, int /* Traverse through db list to get versions and doclist of all docs with root. e.g. IF-NONE-MATCH: 123,44317,66317,77317 where 123 is root version. e.g. root,ble,lan,mesh,moca -Currently versionsList length is fixed to 512 which can support up to 45 docs. +Currently versionsList length is fixed to 8192 which can support up to 512 docs. This can be increased if required. VersionList and docList are fetched at once from DB to fix version and docList mismatch when DB is updated.*/ void refreshConfigVersionList(char *versionsList, int http_status, char *docsList) @@ -1476,7 +1457,7 @@ void refreshConfigVersionList(char *versionsList, int http_status, char *docsLis WEBCFG_STATUS retStatus = WEBCFG_SUCCESS; //initialize to default value "0". - snprintf(versionsList, 512, "%s", "0"); + snprintf(versionsList, MAX_LBUFF_SIZE, "%s", "0"); derive_root_doc_version_string(&root_str, &root_version, http_status); WebcfgDebug("update root_version %lu rootString %s to DB\n", (long)root_version, root_str); @@ -1495,7 +1476,7 @@ void refreshConfigVersionList(char *versionsList, int http_status, char *docsLis if(root_str!=NULL && strlen(root_str) >0) { WebcfgDebug("update root_str %s to versionsList\n", root_str); - snprintf(versionsList, 512, "%s", root_str); + snprintf(versionsList, MAX_LBUFF_SIZE, "%s", root_str); WEBCFG_FREE(root_str); } else @@ -1505,7 +1486,7 @@ void refreshConfigVersionList(char *versionsList, int http_status, char *docsLis } WebcfgInfo("versionsList is %s\n", versionsList); - snprintf(docsList, 512, "%s", "root"); + snprintf(docsList, MAX_LBUFF_SIZE, "%s", "root"); WebcfgDebug("docsList is %s\n", docsList); while (NULL != temp) @@ -1519,7 +1500,7 @@ void refreshConfigVersionList(char *versionsList, int http_status, char *docsLis WEBCFG_FREE(versionsList_tmp); //Fetch docsList and version together to fix docs & version mismatch from DB docsList_tmp = strdup(docsList); - snprintf(docsList, 512, "%s,%s",docsList_tmp, temp->name); + snprintf(docsList, MAX_LBUFF_SIZE, "%s,%s",docsList_tmp, temp->name); WEBCFG_FREE(docsList_tmp); } } @@ -1539,12 +1520,13 @@ void refreshConfigVersionList(char *versionsList, int http_status, char *docsLis //NOTE: If new headers are added in webcfg curl flow add them in MQTT createMqttHeader also if necessary #if !defined FEATURE_SUPPORT_MQTTCM -void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, int status, char ** trans_uuid, char **subdocList) +void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, int status, char ** trans_uuid) { char *version_header = NULL; char *auth_header = NULL; char *status_header=NULL; char *schema_header=NULL; + char *doc_header = NULL; char *bootTime = NULL, *bootTime_header = NULL; char *FwVersion = NULL, *FwVersion_header=NULL; char *supportedDocs = NULL; @@ -1562,8 +1544,8 @@ void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, char *currentTime_header=NULL; char *uuid_header = NULL; char *transaction_uuid = NULL; - char version[512]={'\0'}; - char docList[512]={'\0'}; + char version[MAX_LBUFF_SIZE]={'\0'}; + char docList[MAX_LBUFF_SIZE]={'\0'}; size_t supported_doc_size = 0; size_t supported_version_size = 0; size_t supplementary_docs_size = 0; @@ -1584,16 +1566,24 @@ void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, if(!get_global_supplementarySync()) { - version_header = (char *) malloc(sizeof(char)*MAX_BUF_SIZE); + version_header = (char *) malloc(sizeof(char) * (MAX_LBUFF_SIZE + strlen("IF-NONE-MATCH:") + 1)); if(version_header !=NULL) { refreshConfigVersionList(version, 0, docList); - snprintf(version_header, MAX_BUF_SIZE, "IF-NONE-MATCH:%s", ((strlen(version)!=0) ? version : "0")); + snprintf(version_header, MAX_LBUFF_SIZE + strlen("IF-NONE-MATCH:") + 1, "IF-NONE-MATCH:%s", ((strlen(version)!=0) ? version : "0")); WebcfgInfo("version_header formed %s\n", version_header); WebcfgInfo("docList fetched %s\n", docList); - *subdocList = strdup(docList); list = curl_slist_append(list, version_header); WEBCFG_FREE(version_header); + + doc_header = (char *)malloc(sizeof(char) * (MAX_LBUFF_SIZE + strlen("Doc-Name: ") + 1)); + if (doc_header != NULL) + { + snprintf(doc_header, MAX_LBUFF_SIZE + strlen("Doc-Name: ") + 1, "Doc-Name: %s", docList); + list = curl_slist_append(list, doc_header); + WebcfgInfo("doc_header formed %s\n", doc_header); + WEBCFG_FREE(doc_header); + } } WebcfgInfo("Post none retain header formed POST-NONE-RETAIN: true\n"); list = curl_slist_append(list, "POST-NONE-RETAIN: true"); diff --git a/src/webcfg_multipart.h b/src/webcfg_multipart.h index 4f63c468..c5f40423 100644 --- a/src/webcfg_multipart.h +++ b/src/webcfg_multipart.h @@ -95,7 +95,7 @@ WEBCFG_STATUS deleteFromMpList(char* doc_name); void addToMpList(uint32_t etag, char *name_space, char *data, size_t data_size); void delete_mp_doc(); #if !defined FEATURE_SUPPORT_MQTTCM -void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, int status, char ** trans_uuid,char **subdocList); +void createCurlHeader( struct curl_slist *list, struct curl_slist **header_list, int status, char ** trans_uuid); #endif char *replaceMacWord(const char *s, const char *macW, const char *deviceMACW); void checkValidURL(char **s); diff --git a/tests/test_generic_pc.c b/tests/test_generic_pc.c index 8e22d655..6b328761 100644 --- a/tests/test_generic_pc.c +++ b/tests/test_generic_pc.c @@ -260,7 +260,7 @@ void test_getAccountID() { char *pString = "test"; pString = getAccountID(); - CU_ASSERT_STRING_EQUAL(pString, "unkown"); + CU_ASSERT_STRING_EQUAL(pString, "unknown"); } void test_getPartnerID() @@ -377,4 +377,4 @@ int main( int argc, char *argv[] ) return rv; } - \ No newline at end of file + diff --git a/tests/test_multipart_unittest.c b/tests/test_multipart_unittest.c index 24e2a0e1..12cc19dc 100644 --- a/tests/test_multipart_unittest.c +++ b/tests/test_multipart_unittest.c @@ -55,6 +55,9 @@ rbusHandle_t handle; #define WEBCFG_BLOB_PARAM "Device.DeviceInfo.Test" +#define NUM_SUBDOCS 512 +#define SUBDOC_SIZE 16 + int numLoops; #define MAX_HEADER_LEN 4096 @@ -316,6 +319,47 @@ rbusError_t webcfgBlobElement1SetHandler(rbusHandle_t handle, rbusProperty_t pro } #endif +void populate_db_with_subdocs() +{ + webconfig_db_data_t *head = NULL; + webconfig_db_data_t *current = NULL; + + for (int i = 0; i < NUM_SUBDOCS; i++) { + webconfig_db_data_t *new_node = (webconfig_db_data_t *)malloc(sizeof(webconfig_db_data_t)); + if (!new_node) { + perror("malloc failed"); + return; + } + + memset(new_node, 0, sizeof(webconfig_db_data_t)); + + new_node->name = (char *)malloc(SUBDOC_SIZE); + if (!new_node->name) { + perror("malloc failed"); + free(new_node); + return; + } + + if (i == 0) { + snprintf(new_node->name, SUBDOC_SIZE - 1, "root"); + } else { + snprintf(new_node->name, SUBDOC_SIZE - 1, "subdoc_%d", i); + } + new_node->version = i; + new_node->next = NULL; + + if (head == NULL) { + head = new_node; + current = head; + } else { + current->next = new_node; + current = current->next; + } + } + + set_global_db_node(head); +} + void test_generate_trans_uuid(){ char *transaction_uuid = NULL; @@ -355,11 +399,10 @@ void test_createHeader(){ struct curl_slist *list = NULL; struct curl_slist *headers_list = NULL; char *transID = NULL; - char *subdoclist = NULL; int status=0; curl = curl_easy_init(); CU_ASSERT_PTR_NOT_NULL(curl); - createCurlHeader(list, &headers_list, status, &transID, &subdoclist); + createCurlHeader(list, &headers_list, status, &transID); CU_ASSERT_PTR_NOT_NULL(transID); CU_ASSERT_PTR_NOT_NULL(headers_list); @@ -368,11 +411,193 @@ void test_createHeader(){ setsupportedVersion("1234-v0"); set_global_supplementarySync(1); setsupplementaryDocs("telemetry"); - createCurlHeader(list, &headers_list, status, &transID, &subdoclist); + createCurlHeader(list, &headers_list, status, &transID); CU_ASSERT_PTR_NOT_NULL(transID); CU_ASSERT_PTR_NOT_NULL(headers_list); } +void test_createHeader_doc_header_max_data() { + CURL *curl; + struct curl_slist *list = NULL; + struct curl_slist *headers_list = NULL; + char *transID = NULL; + int status = 0; + + curl = curl_easy_init(); + CU_ASSERT_PTR_NOT_NULL(curl); + + set_global_supplementarySync(0); + + populate_db_with_subdocs(); + + createCurlHeader(list, &headers_list, status, &transID); + CU_ASSERT_PTR_NOT_NULL(transID); + CU_ASSERT_PTR_NOT_NULL(headers_list); + + struct curl_slist *temp = headers_list; + int subdoc_found = 0; + + while (temp) + { + WebcfgInfo(" Checking header: %s\n", temp->data); + if (strstr(temp->data, "Doc-Name:") == temp->data) + { + subdoc_found = 1; + break; + } + temp = temp->next; + } + + if (!subdoc_found) + WebcfgInfo(" 'Doc-Name' header NOT found!\n"); + else + WebcfgInfo(" 'Doc-Name' header found!\n"); + CU_ASSERT_TRUE(subdoc_found); + + if (transID) { + free(transID); + transID = NULL; + } + + if (headers_list) { + curl_slist_free_all(headers_list); + headers_list = NULL; + } + + if (curl) { + curl_easy_cleanup(curl); + curl = NULL; + } + + webconfig_db_data_t *db_head = get_global_db_node(); + webconfig_db_data_t *next = NULL; + + while (db_head) { + next = db_head->next; + webcfgdb_destroy(db_head); + db_head = next; + } + + set_global_db_node(NULL); +} + +void test_createHeader_primary_sync() { + CURL *curl; + struct curl_slist *list = NULL; + struct curl_slist *headers_list = NULL; + char *transID = NULL; + int status = 0; + + curl = curl_easy_init(); + CU_ASSERT_PTR_NOT_NULL(curl); + set_global_supplementarySync(0); + + createCurlHeader(list, &headers_list, status, &transID); + CU_ASSERT_PTR_NOT_NULL(transID); + CU_ASSERT_PTR_NOT_NULL(headers_list); + + const char *expected_headers[] = { + "IF-NONE-MATCH:", "Doc-Name:", "POST-NONE-RETAIN: true" + }; + const int num_expected_headers = sizeof(expected_headers) / sizeof(expected_headers[0]); + int found_headers[num_expected_headers]; + memset(found_headers, 0, sizeof(found_headers)); + + struct curl_slist *temp = headers_list; + WebcfgInfo("Checking headers in headers_list for primary sync:\n"); + while (temp) + { + for (int i = 0; i < num_expected_headers; i++) + { + if (strncmp(temp->data, expected_headers[i], strlen(expected_headers[i])) == 0) + { + WebcfgInfo(" --> Found header: '%s'\n", expected_headers[i]); + found_headers[i] = 1; + } + } + temp = temp->next; + } + + for (int i = 0; i < num_expected_headers; i++) + { + if (!found_headers[i]) printf(" --> Missing header: %s\n", expected_headers[i]); + CU_ASSERT_TRUE(found_headers[i]); + } + + // Cleanup + if (transID) { + free(transID); + transID = NULL; + } + if (headers_list) { + curl_slist_free_all(headers_list); + headers_list = NULL; + } + if (curl) { + curl_easy_cleanup(curl); + curl = NULL; + } +} + +void test_createHeader_supplementary_sync() { + CURL *curl; + struct curl_slist *list = NULL; + struct curl_slist *headers_list = NULL; + char *transID = NULL; + int status = 0; + + curl = curl_easy_init(); + CU_ASSERT_PTR_NOT_NULL(curl); + set_global_supplementarySync(1); + + createCurlHeader(list, &headers_list, status, &transID); + CU_ASSERT_PTR_NOT_NULL(transID); + CU_ASSERT_PTR_NOT_NULL(headers_list); + + const char *expected_headers[] = { + "X-System-SupplementaryService-Sync:", "X-System-Telemetry-Profile-Version:", + "X-System-PartnerID:", "X-System-AccountID:", "X-System-Wan-Mac:" + }; + int num_expected_headers = sizeof(expected_headers) / sizeof(expected_headers[0]); + int found_headers[num_expected_headers]; + memset(found_headers, 0, sizeof(found_headers)); + + struct curl_slist *temp = headers_list; + WebcfgInfo("Checking headers in headers_list for supplementary sync:\n"); + + while (temp) + { + for (int i = 0; i < num_expected_headers; i++) + { + if (strncmp(temp->data, expected_headers[i], strlen(expected_headers[i])) == 0) + { + WebcfgInfo(" --> Found header: '%s'\n", expected_headers[i]); + found_headers[i] = 1; + } + } + temp = temp->next; + } + + for (int i = 0; i < num_expected_headers; i++) + { + if (!found_headers[i]) WebcfgInfo(" --> Missing header: %s\n", expected_headers[i]); + CU_ASSERT_TRUE(found_headers[i]); + } + + if (transID) { + free(transID); + transID = NULL; + } + if (headers_list) { + curl_slist_free_all(headers_list); + headers_list = NULL; + } + if (curl) { + curl_easy_cleanup(curl); + curl = NULL; + } +} + void test_validateParam() { param_t *reqParam = NULL; int paramCount = 1; @@ -556,6 +781,7 @@ void test_updateRootVersionToDB(){ tmpData->retry_count = 0; tmpData->error_code = 0; tmpData->error_details = strdup("none"); + tmpData->cloud_trans_id = NULL; tmpData->next = NULL; set_global_tmp_node(tmpData); set_global_ETAG("123"); @@ -707,6 +933,7 @@ void test_deleteRootAndMultipartDocs(){ tmpData->retry_count = 0; tmpData->error_code = 0; tmpData->error_details = strdup("none"); + tmpData->cloud_trans_id = NULL; tmpData->next = NULL; set_global_tmp_node(tmpData); int m=deleteRootAndMultipartDocs(); @@ -1235,6 +1462,9 @@ void add_suites( CU_pSuite *suite ) CU_add_test( *suite, "test checkValidURL_ValidURL", test_checkValidURL_ValidURL); CU_add_test( *suite, "test checkValidURL_InvalidURL", test_checkValidURL_InvalidURL); CU_add_test( *suite, "test createCurlHeader", test_createHeader); + CU_add_test( *suite, "test createHeader_doc_header_max_data", test_createHeader_doc_header_max_data); + CU_add_test( *suite, "test createHeader_primary_sync", test_createHeader_primary_sync); + CU_add_test( *suite, "test createHeader_supplementary_sync", test_createHeader_supplementary_sync); CU_add_test( *suite, "test validateParam", test_validateParam); CU_add_test( *suite, "test checkRootUpdate", test_checkRootUpdate); CU_add_test( *suite, "test checkRootDelete", test_checkRootDelete);