diff --git a/.gitignore b/.gitignore index bd4668c..903b29b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ *.log *.xml *.so -*.txt *.orig bin/* !bin/Makefile.am @@ -43,3 +42,4 @@ CMakeCache.txt CMakeFiles/ cmake_install.cmake install_manifest.txt +/report diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bb0a2a1..2cc3e01 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,4 +70,6 @@ run_functional_test: - funl-test-memory-report.xml - funl-test-result.log - funl-test-debug.log + - memory-report.xml + - memory-report-download.xml - icwmpd_debug.txt diff --git a/gitlab-ci/functional-test.sh b/gitlab-ci/functional-test.sh index a541391..bae0817 100755 --- a/gitlab-ci/functional-test.sh +++ b/gitlab-ci/functional-test.sh @@ -8,21 +8,6 @@ pwd trap cleanup EXIT trap cleanup SIGINT -function check_valgrind_xml() { - echo "Checking memory leaks..." - grep -q "UninitCondition" memory-report.xml - error_on_zero $? - - grep -q "Leak_PossiblyLost" memory-report.xml - error_on_zero $? - - grep -q "Leak_DefinitelyLost" memory-report.xml - error_on_zero $? - - grep -q "Leak_StillReachable" memory-report.xml - error_on_zero $? -} - date +%s > timestamp.log echo "Compiling icmwp" build_icwmp @@ -53,12 +38,13 @@ echo "## Running script verification of functionalities ##" echo > ./funl-test-result.log echo > ./funl-test-debug.log test_num=0 -for test in $(ls -I "common.sh" -I "verify_custom_notifications.sh" test/script/); do +for test in `cat test/script/test_seq.txt`; do ret=0 test_num=$(( test_num + 1 )) echo "#### Start $test ####" >> "$icwmp_master_log" - if ./test/script/"${test}"; then + ./test/script/${test} + if [ "$?" -eq 0 ]; then echo "ok ${test_num} - ${test}" >> ./funl-test-result.log remove_icwmp_log echo "#### $test Done ####" >> "$icwmp_master_log" @@ -74,6 +60,7 @@ done echo "Stop all services" supervisorctl stop icwmpd +sleep 10 check_valgrind_xml cp test/files/etc/config/users /etc/config/ @@ -81,7 +68,8 @@ cp test/files/etc/config/wireless /etc/config/ echo "Verify Custom notifications" echo "#### Start custom_notifications ####" >> "$icwmp_master_log" -if ./test/script/verify_custom_notifications.sh; then +./test/script/verify_custom_notifications.sh +if [ "$?" -eq 0 ]; then echo "ok - verify_custom_notifications" >> ./funl-test-result.log remove_icwmp_log echo "#### Done custom_notifications ####" >> "$icwmp_master_log" @@ -104,6 +92,7 @@ cp ./memory-report.xml ./funl-test-memory-report.xml #report part exec_cmd tap-junit --input ./funl-test-result.log --output report +sleep 10 check_valgrind_xml echo "Functional test :: PASS" diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index c09bf23..c8fab6a 100644 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -148,15 +148,19 @@ function install_uspd() function check_valgrind_xml() { echo "Checking memory leaks..." + echo "checking UninitCondition" grep -q "UninitCondition" memory-report.xml error_on_zero $? + echo "checking Leak_PossiblyLost" grep -q "Leak_PossiblyLost" memory-report.xml error_on_zero $? + echo "checking Leak_DefinitelyLost" grep -q "Leak_DefinitelyLost" memory-report.xml error_on_zero $? + echo "checking Leak_StillReachable" grep -q "Leak_StillReachable" memory-report.xml error_on_zero $? } diff --git a/src/backupSession.c b/src/backupSession.c index ff7dc41..51ed945 100644 --- a/src/backupSession.c +++ b/src/backupSession.c @@ -22,9 +22,9 @@ #include "cwmp_du_state.h" #include "notifications.h" #include "xml.h" +#include "cwmp_event.h" static mxml_node_t *bkp_tree = NULL; -pthread_mutex_t mutex_backup_session = PTHREAD_MUTEX_INITIALIZER; enum backup_attributes_types { @@ -176,12 +176,10 @@ void bkp_session_save() FILE *fp; if (!bkp_tree) return; - pthread_mutex_lock(&mutex_backup_session); fp = fopen(CWMP_BKP_FILE, "w"); mxmlSaveFile(bkp_tree, fp, MXML_NO_CALLBACK); fclose(fp); sync(); - pthread_mutex_unlock(&mutex_backup_session); } mxml_node_t *bkp_session_insert(mxml_node_t *tree, char *name, char *value) @@ -236,7 +234,6 @@ mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char char event_idx[32]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(parent_name, sizeof(parent_name), "%s_event", status); snprintf(event_id, sizeof(event_id), "%d", id); snprintf(event_idx, sizeof(event_idx), "%d", index); @@ -249,7 +246,6 @@ mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char bkp_session_insert(b, "id", event_id); bkp_session_insert(b, "command_key", command_key); } - pthread_mutex_unlock(&mutex_backup_session); return b; } @@ -260,7 +256,6 @@ void bkp_session_delete_event(int id, char *status) char event_id[32]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(parent_name, sizeof(parent_name), "%s_event", status); snprintf(event_id, sizeof(event_id), "%d", id); keys[0].name = "id"; @@ -268,34 +263,28 @@ void bkp_session_delete_event(int id, char *status) b = bkp_session_node_found(bkp_tree, parent_name, keys, 1); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_parameter(mxml_node_t *b, char *name) { - pthread_mutex_lock(&mutex_backup_session); bkp_session_insert(b, "parameter", name); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_simple_insert(char *parent, char *child, char *value) { mxml_node_t *b = bkp_tree; - pthread_mutex_lock(&mutex_backup_session); b = mxmlFindElement(b, b, parent, NULL, NULL, MXML_DESCEND); if (b) mxmlDelete(b); b = bkp_session_insert(bkp_tree, parent, NULL); bkp_session_insert(b, child, value); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_simple_insert_in_parent(char *parent, char *child, char *value) { mxml_node_t *n, *b = bkp_tree; - pthread_mutex_lock(&mutex_backup_session); n = mxmlFindElement(b, b, parent, NULL, NULL, MXML_DESCEND); if (!n) n = bkp_session_insert(bkp_tree, parent, NULL); @@ -303,14 +292,12 @@ void bkp_session_simple_insert_in_parent(char *parent, char *child, char *value) if (b) mxmlDelete(b); bkp_session_insert(n, child, value); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_move_inform_to_inform_send() { mxml_node_t *b = bkp_tree; - pthread_mutex_lock(&mutex_backup_session); while (b) { mxml_node_t *p = mxmlGetParent(b); if (mxmlGetType(b) == MXML_ELEMENT && !strcmp(mxmlGetElement(b), "queue_event") && mxmlGetType(p) == MXML_ELEMENT && !strcmp(mxmlGetElement(p), "cwmp")) @@ -318,14 +305,12 @@ void bkp_session_move_inform_to_inform_send() b = mxmlWalkNext(b, bkp_tree, MXML_DESCEND); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_move_inform_to_inform_queue() { mxml_node_t *b = bkp_tree; - pthread_mutex_lock(&mutex_backup_session); while (b) { mxml_node_t *p = mxmlGetParent(b); if (mxmlGetType(b) == MXML_ELEMENT && !strcmp(mxmlGetElement(b), "send_event") && mxmlGetType(p) == MXML_ELEMENT && !strcmp(mxmlGetElement(p), "cwmp")) @@ -333,7 +318,6 @@ void bkp_session_move_inform_to_inform_queue() b = mxmlWalkNext(b, bkp_tree, MXML_DESCEND); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_schedule_inform(time_t time, char *command_key) @@ -341,7 +325,6 @@ void bkp_session_insert_schedule_inform(time_t time, char *command_key) char schedule_time[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)time); struct search_keywords sched_inf_insert_keys[2] = { { "command_key", command_key }, { "time", schedule_time } }; b = bkp_session_node_found(bkp_tree, "schedule_inform", sched_inf_insert_keys, 2); @@ -350,7 +333,6 @@ void bkp_session_insert_schedule_inform(time_t time, char *command_key) bkp_session_insert(b, "command_key", command_key); bkp_session_insert(b, "time", schedule_time); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_schedule_inform(time_t time, char *command_key) @@ -358,13 +340,11 @@ void bkp_session_delete_schedule_inform(time_t time, char *command_key) char schedule_time[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)time); struct search_keywords sched_inf_del_keys[2] = { { "command_key", command_key }, { "time", schedule_time } }; b = bkp_session_node_found(bkp_tree, "schedule_inform", sched_inf_del_keys, 2); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_download(struct download *pdownload) @@ -373,7 +353,6 @@ void bkp_session_insert_download(struct download *pdownload) char file_size[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pdownload->scheduled_time); snprintf(file_size, sizeof(file_size), "%d", pdownload->file_size); struct search_keywords download_insert_keys[7] = { { "url", pdownload->url }, { "command_key", pdownload->command_key }, { "file_type", pdownload->file_type }, { "username", pdownload->username }, { "password", pdownload->password }, { "file_size", file_size }, { "time", schedule_time } }; @@ -389,7 +368,6 @@ void bkp_session_insert_download(struct download *pdownload) bkp_session_insert(b, "file_size", file_size); bkp_session_insert(b, "time", schedule_time); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_schedule_download(struct download *pschedule_download) @@ -400,7 +378,6 @@ void bkp_session_insert_schedule_download(struct download *pschedule_download) char maxretrie[2][128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(file_size, sizeof(file_size), "%d", pschedule_download->file_size); for (i = 0; i < 2; i++) { snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)pschedule_download->timewindowstruct[i].windowstart); @@ -444,80 +421,6 @@ void bkp_session_insert_schedule_download(struct download *pschedule_download) bkp_session_insert(b, "usermessage2", pschedule_download->timewindowstruct[1].usermessage); bkp_session_insert(b, "maxretrie2", maxretrie[1]); } - pthread_mutex_unlock(&mutex_backup_session); -} - -void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download) -{ - char delay[4][128]; - int i; - char maxretrie[2][128]; - mxml_node_t *b; - - pthread_mutex_lock(&mutex_backup_session); - - for (i = 0; i < 2; i++) { - snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowstart); - snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowend); - snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", papply_schedule_download->timeintervals[i].maxretries); - } - - struct search_keywords sched_download_insert_app_keys[9] = { { "command_key", papply_schedule_download->command_key }, - { "file_type", papply_schedule_download->file_type }, - { "start_time", papply_schedule_download->start_time }, - { "windowstart1", delay[0] }, - { "windowend1", delay[1] }, - { "maxretrie1", maxretrie[0] }, - { "windowstart2", delay[2] }, - { "windowend2", delay[3] }, - { "maxretrie2", maxretrie[1] } }; - - b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_insert_app_keys, 9); - if (!b) { - CWMP_LOG(INFO, "New schedule download key %s file", papply_schedule_download->command_key); - b = bkp_session_insert(bkp_tree, "apply_schedule_download", NULL); - bkp_session_insert(b, "start_time", papply_schedule_download->start_time); - bkp_session_insert(b, "command_key", papply_schedule_download->command_key); - bkp_session_insert(b, "file_type", papply_schedule_download->file_type); - bkp_session_insert(b, "windowstart1", delay[0]); - bkp_session_insert(b, "windowend1", delay[1]); - bkp_session_insert(b, "maxretrie1", maxretrie[0]); - - bkp_session_insert(b, "windowstart2", delay[2]); - bkp_session_insert(b, "windowend2", delay[3]); - bkp_session_insert(b, "maxretrie2", maxretrie[1]); - } - pthread_mutex_unlock(&mutex_backup_session); -} - -void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *ps_download) //TODO -{ - char delay[4][128]; - char maxretrie[2][128]; - int i; - mxml_node_t *b; - - pthread_mutex_lock(&mutex_backup_session); - for (i = 0; i < 2; i++) { - snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowstart); - snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowend); - snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", ps_download->timeintervals[i].maxretries); - } - struct search_keywords sched_download_del_app_keys[9] = { { "start_time", ps_download->start_time }, - { "command_key", ps_download->command_key }, - { "file_type", ps_download->file_type }, - { "windowstart1", delay[0] }, - { "windowend1", delay[1] }, - { "maxretrie1", maxretrie[0] }, - { "windowstart2", delay[2] }, - { "windowend2", delay[3] }, - { "maxretrie2", maxretrie[1] } }; - - b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_del_app_keys, 9); - - if (b) - mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state) @@ -526,7 +429,6 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state char schedule_time[128]; mxml_node_t *b, *n; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pchange_du_state->timeout); b = bkp_session_insert(bkp_tree, "change_du_state", NULL); bkp_session_insert(b, "command_key", pchange_du_state->command_key); @@ -553,7 +455,6 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state bkp_session_insert(n, "executionenvref", p->executionenvref); } } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_change_du_state(struct change_du_state *pchange_du_state) @@ -561,13 +462,11 @@ void bkp_session_delete_change_du_state(struct change_du_state *pchange_du_state char schedule_time[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pchange_du_state->timeout); struct search_keywords cds_del_keys[2] = { { "command_key", pchange_du_state->command_key }, { "time", schedule_time } }; b = bkp_session_node_found(bkp_tree, "change_du_state", cds_del_keys, 2); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_upload(struct upload *pupload) @@ -575,7 +474,6 @@ void bkp_session_insert_upload(struct upload *pupload) char schedule_time[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pupload->scheduled_time); struct search_keywords upload_insert_keys[6] = { { "url", pupload->url }, { "command_key", pupload->command_key }, { "username", pupload->username }, { "password", pupload->password }, { "time", schedule_time }, { "file_type", pupload->file_type } }; @@ -589,7 +487,6 @@ void bkp_session_insert_upload(struct upload *pupload) bkp_session_insert(b, "password", pupload->password); bkp_session_insert(b, "time", schedule_time); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_download(struct download *pdownload) { @@ -597,7 +494,6 @@ void bkp_session_delete_download(struct download *pdownload) char file_size[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pdownload->scheduled_time); snprintf(file_size, sizeof(file_size), "%d", pdownload->file_size); struct search_keywords download_del_keys[7] = { { "url", pdownload->url }, { "command_key", pdownload->command_key }, { "file_type", pdownload->file_type }, { "username", pdownload->username }, { "password", pdownload->password }, { "file_size", file_size }, { "time", schedule_time } }; @@ -605,7 +501,6 @@ void bkp_session_delete_download(struct download *pdownload) b = bkp_session_node_found(bkp_tree, "download", download_del_keys, 7); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_schedule_download(struct download *pschedule_download_delete) @@ -616,7 +511,6 @@ void bkp_session_delete_schedule_download(struct download *pschedule_download_de int i; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(file_size, sizeof(file_size), "%d", pschedule_download_delete->file_size); for (i = 0; i < 2; i++) { snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)pschedule_download_delete->timewindowstruct[i].windowstart); @@ -644,20 +538,17 @@ void bkp_session_delete_schedule_download(struct download *pschedule_download_de if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_upload(struct upload *pupload) { char schedule_time[128]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pupload->scheduled_time); struct search_keywords upload_del_keys[6] = { { "url", pupload->url }, { "command_key", pupload->command_key }, { "file_type", pupload->file_type }, { "username", pupload->username }, { "password", pupload->password }, { "time", schedule_time } }; b = bkp_session_node_found(bkp_tree, "upload", upload_del_keys, 6); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete) @@ -666,7 +557,6 @@ void bkp_session_insert_du_state_change_complete(struct du_state_change_complete struct opresult *p = NULL; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pdu_state_change_complete->timeout); b = bkp_session_insert(bkp_tree, "du_state_change_complete", NULL); bkp_session_insert(b, "command_key", pdu_state_change_complete->command_key); @@ -686,7 +576,6 @@ void bkp_session_insert_du_state_change_complete(struct du_state_change_complete bkp_session_insert(n, "complete_time", p->complete_time); bkp_session_insert(n, "fault", fault_code); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete) @@ -694,14 +583,12 @@ void bkp_session_delete_du_state_change_complete(struct du_state_change_complete mxml_node_t *b; char schedule_time[128]; - pthread_mutex_lock(&mutex_backup_session); snprintf(schedule_time, sizeof(schedule_time), "%lld", (long long int)pdu_state_change_complete->timeout); struct search_keywords cds_complete_keys[2] = { { "command_key", pdu_state_change_complete->command_key }, { "time", schedule_time } }; b = bkp_session_node_found(bkp_tree, "du_state_change_complete", cds_complete_keys, 2); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_complete) { @@ -710,7 +597,6 @@ void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_co char type[16]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(fault_code, sizeof(fault_code), "%d", ptransfer_complete->fault_code); keys[0].name = "command_key"; keys[0].value = ptransfer_complete->command_key; @@ -733,7 +619,6 @@ void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_co bkp_session_insert(b, "fault_code", fault_code); bkp_session_insert(b, "type", type); } - pthread_mutex_unlock(&mutex_backup_session); } void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_complete) @@ -742,7 +627,6 @@ void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_co char type[16]; mxml_node_t *b; - pthread_mutex_lock(&mutex_backup_session); snprintf(fault_code, sizeof(fault_code), "%d", ptransfer_complete->fault_code); snprintf(type, sizeof(type), "%d", ptransfer_complete->type); struct search_keywords trans_comp_del_keys[5] = { { "command_key", ptransfer_complete->command_key }, { "start_time", ptransfer_complete->start_time }, { "complete_time", ptransfer_complete->complete_time }, { "fault_code", fault_code }, { "type", type } }; @@ -750,14 +634,13 @@ void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_co b = bkp_session_node_found(bkp_tree, "transfer_complete", trans_comp_del_keys, 5); if (b) mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); } -int save_acs_bkp_config(struct cwmp *cwmp) +int save_acs_bkp_config() { struct config *conf; - conf = &(cwmp->conf); + conf = &(cwmp_main->conf); bkp_session_simple_insert("acs", "url", conf->acsurl); bkp_session_save(); return CWMP_OK; @@ -786,7 +669,7 @@ char *load_child_value(mxml_node_t *tree, char *sub_name) return value; } -void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp) +void load_queue_event(mxml_node_t *tree) { char *command_key = NULL; mxml_node_t *b = tree, *c; @@ -809,7 +692,7 @@ void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp) */ if (idx != -1) { if (EVENT_CONST[idx].RETRY & EVENT_RETRY_AFTER_REBOOT) { - event_container_save = cwmp_add_event_container(cwmp, idx, ((command_key != NULL) ? command_key : "")); + event_container_save = cwmp_add_event_container(idx, ((command_key != NULL) ? command_key : "")); if (event_container_save != NULL) { event_container_save->id = id; } @@ -837,7 +720,7 @@ void load_schedule_inform(mxml_node_t *tree) char *command_key = NULL; time_t scheduled_time = 0; struct schedule_inform *schedule_inform = NULL; - struct list_head *ilist; + struct list_head *ilist = NULL; struct backup_attributes bkp_attrs = { .command_key = &command_key, .time = &scheduled_time }; load_specific_backup_attributes(tree, &bkp_attrs); @@ -872,6 +755,7 @@ void load_download(mxml_node_t *tree) .file_size = &download_request->file_size, .time = &download_request->scheduled_time }; load_specific_backup_attributes(tree, &bkp_attrs); + download_request->handler_timer.cb = cwmp_start_download; list_for_each (ilist, &(list_download)) { idownload_request = list_entry(ilist, struct download, list); @@ -882,6 +766,7 @@ void load_download(mxml_node_t *tree) list_add(&(download_request->list), ilist->prev); if (download_request->scheduled_time != 0) count_download_queue++; + cwmp_set_end_session(END_SESSION_DOWNLOAD); } void load_schedule_download(mxml_node_t *tree) @@ -923,30 +808,6 @@ void load_schedule_download(mxml_node_t *tree) count_download_queue++; } -void load_apply_schedule_download(mxml_node_t *tree) -{ - struct apply_schedule_download *download_request = NULL; - - download_request = calloc(1, sizeof(struct apply_schedule_download)); - - struct backup_attributes bkp_attrs = { - .command_key = &download_request->command_key, - .file_type = &download_request->file_type, - .start_time = &download_request->start_time, - .windowstart1 = &download_request->timeintervals[0].windowstart, - .windowend1 = &download_request->timeintervals[0].windowend, - .maxretrie1 = &download_request->timeintervals[0].maxretries, - .windowstart2 = &download_request->timeintervals[1].windowstart, - .windowend2 = &download_request->timeintervals[1].windowend, - .maxretrie2 = &download_request->timeintervals[1].maxretries, - }; - load_specific_backup_attributes(tree, &bkp_attrs); - - list_add_tail(&(download_request->list), &(list_apply_schedule_download)); - if (download_request->timeintervals[0].windowstart != 0) - count_download_queue++; -} - void load_upload(mxml_node_t *tree) { struct upload *upload_request = NULL; @@ -1012,7 +873,7 @@ void load_change_du_state(mxml_node_t *tree) list_add_tail(&(change_du_state_request->list_operation), &(list_change_du_state)); } -void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp) +void load_du_state_change_complete(mxml_node_t *tree) { mxml_node_t *b = tree; struct du_state_change_complete *du_state_change_complete_request = NULL; @@ -1046,10 +907,10 @@ void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp) } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } - cwmp_root_cause_changedustate_complete(cwmp, du_state_change_complete_request); + cwmp_root_cause_changedustate_complete(du_state_change_complete_request); } -void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp) +void load_transfer_complete(mxml_node_t *tree) { struct transfer_complete *ptransfer_complete; @@ -1063,19 +924,17 @@ void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp) .type = &ptransfer_complete->type }; load_specific_backup_attributes(tree, &bkp_attrs); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - sotfware_version_value_change(cwmp, ptransfer_complete); + cwmp_root_cause_transfer_complete(ptransfer_complete); + sotfware_version_value_change(ptransfer_complete); } void bkp_session_create_file() { FILE *pFile; - pthread_mutex_lock(&mutex_backup_session); pFile = fopen(CWMP_BKP_FILE, "w"); if (pFile == NULL) { CWMP_LOG(ERROR, "Unable to create %s file", CWMP_BKP_FILE); - pthread_mutex_unlock(&mutex_backup_session); return; } fprintf(pFile, "%s", CWMP_BACKUP_SESSION); @@ -1083,7 +942,6 @@ void bkp_session_create_file() MXML_DELETE(bkp_tree); bkp_tree = mxmlLoadString(NULL, CWMP_BACKUP_SESSION, MXML_OPAQUE_CALLBACK); fclose(pFile); - pthread_mutex_unlock(&mutex_backup_session); } int bkp_session_check_file() @@ -1109,16 +967,16 @@ int bkp_session_check_file() return 0; } -int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load) +int cwmp_init_backup_session(char **ret, enum backup_loading load) { int error; if (bkp_session_check_file()) return 0; - error = cwmp_load_saved_session(cwmp, ret, load); + error = cwmp_load_saved_session(ret, load); return error; } -int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading load) +int cwmp_load_saved_session(char **ret, enum backup_loading load) { mxml_node_t *b; @@ -1153,23 +1011,21 @@ int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading l } if (load == ALL) { if (ntype == MXML_ELEMENT && strcmp(elem_name, "queue_event") == 0) { - load_queue_event(b, cwmp); + load_queue_event(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "download") == 0) { load_download(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "upload") == 0) { load_upload(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "transfer_complete") == 0) { - load_transfer_complete(b, cwmp); + load_transfer_complete(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "schedule_inform") == 0) { load_schedule_inform(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "change_du_state") == 0) { load_change_du_state(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "du_state_change_complete") == 0) { - load_du_state_change_complete(b, cwmp); + load_du_state_change_complete(b); } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "schedule_download") == 0) { load_schedule_download(b); - } else if (ntype == MXML_ELEMENT && strcmp(elem_name, "apply_schedule_download") == 0) { - load_apply_schedule_download(b); } } b = mxmlWalkNext(b, bkp_tree, MXML_NO_DESCEND); diff --git a/src/backupSession.h b/src/backupSession.h index c55fb01..cdacc90 100644 --- a/src/backupSession.h +++ b/src/backupSession.h @@ -14,7 +14,7 @@ #ifndef _BACKUPSESSION_H__ #define _BACKUPSESSION_H__ -#include "xml_utils.h" +#include #include "common.h" #define RPC_NO_STATUS -1 @@ -37,11 +37,9 @@ struct search_keywords { char *value; }; -extern pthread_mutex_t mutex_backup_session; - -int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load); +int cwmp_init_backup_session(char **ret, enum backup_loading load); void bkp_session_save(); -int cwmp_load_saved_session(struct cwmp *cwmp, char **acsurl, enum backup_loading load); +int cwmp_load_saved_session(char **acsurl, enum backup_loading load); mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char *status); void bkp_session_delete_event(int id, char *status); void bkp_session_simple_insert_in_parent(char *parent, char *child, char *value); @@ -59,11 +57,9 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state void bkp_session_delete_change_du_state(struct change_du_state *pchange_du_state); void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_complete); void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_complete); -int save_acs_bkp_config(struct cwmp *cwmp); +int save_acs_bkp_config(); void bkp_session_insert_schedule_download(struct download *pschedule_download); -void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download); -void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *papply_schedule_download); void bkp_session_delete_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete); void bkp_session_delete_schedule_download(struct download *pschedule_download); void bkp_session_insert_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete); diff --git a/src/common.c b/src/common.c index f122ef2..db2e9f4 100755 --- a/src/common.c +++ b/src/common.c @@ -24,9 +24,10 @@ #include "log.h" char *commandKey = NULL; -bool thread_end = false; +bool cwmp_stop = false; long int flashsize = 256000000; -struct cwmp cwmp_main = { 0 }; +struct cwmp *cwmp_main = NULL; +struct session_timer_event *global_session_event = NULL; static int nbre_services = 0; static char *list_services[MAX_NBRE_SERVICES] = { 0 }; LIST_HEAD(cwmp_memory_list); @@ -260,6 +261,45 @@ void get_firewall_zone_name_by_wan_iface(char *if_wan, char **zone_name) } } + +int get_firewall_restart_state(char **state) +{ + cwmp_uci_reinit(); + return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state); +} + +// wait till firewall restart is not complete or 5 sec, whichever is less +void check_firewall_restart_state() +{ + int count = 0; + bool init = false; + + do { + char *state = NULL; + + if (get_firewall_restart_state(&state) != CWMP_OK) + break; + + if (state != NULL && strcmp(state, "init") == 0) { + init = true; + FREE(state); + break; + } + + usleep(500 * 1000); + FREE(state); + count++; + } while(count < 10); + + // mark the firewall restart as done + g_firewall_restart = false; + if (init == false) { // In case of timeout reset the firewall_restart flag + CWMP_LOG(ERROR, "Firewall restart took longer than usual"); + cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init"); + cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + } +} + /* * Reboot */ @@ -640,9 +680,8 @@ char *string_to_hex(const unsigned char *str, size_t size) return NULL; } - if (size == 0) { + if (size == 0) return hex; - } for (i = 0; i < size; i++) snprintf(hex + (i * 2), 3, "%02X", str[i]); @@ -690,10 +729,10 @@ void ubus_network_interface_callback(struct ubus_request *req __attribute__((unu // Only update the interface if its not empty if (CWMP_STRLEN(l3_device)) { - cwmp_main.conf.interface = strdup(l3_device); + cwmp_main->conf.interface = strdup(l3_device); } - CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main.conf.interface); + CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main->conf.interface); } int get_connection_interface(char *iface) @@ -708,7 +747,7 @@ int get_connection_interface(char *iface) char ubus_obj[100] = {0}; snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", iface); - FREE(cwmp_main.conf.interface); + FREE(cwmp_main->conf.interface); int e = icwmp_ubus_invoke(ubus_obj, "status", b.head, ubus_network_interface_callback, NULL); blob_buf_free(&b); @@ -716,7 +755,7 @@ int get_connection_interface(char *iface) if (e != 0) { return -1; } - if (cwmp_main.conf.interface == NULL) { + if (cwmp_main->conf.interface == NULL) { return -1; } return CWMP_OK; @@ -801,3 +840,46 @@ bool match_reg_exp(char *reg_exp, char *param_name) return true; } + +void cwmp_invoke_intf_reset(char *path) +{ + if (path == NULL) + return; + + CWMP_LOG(INFO, "Reset interface: %s", path); + struct blob_buf b = { 0 }; + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + bb_add_string(&b, "path", path); + bb_add_string(&b, "action", "Reset()"); + + icwmp_ubus_invoke(USP_OBJECT_NAME, "operate", b.head, NULL, NULL); + blob_buf_free(&b); + + return; +} + +int get_month_days(struct tm time) +{ + if (time.tm_mon == 2) + return (time.tm_year % 4 == 0 ) ? 29 : 28; + if (((time.tm_mon % 2 == 0) && (time.tm_mon <= 7)) || ((time.tm_mon % 2 == 1) && (time.tm_mon > 7))) + return 30; + if (((time.tm_mon % 2 == 1) && (time.tm_mon <= 7)) || ((time.tm_mon % 2 == 0) && (time.tm_mon > 7))) + return 31; + return 30; +} + +void add_day_to_time(struct tm *time) +{ + int month_days = get_month_days(*time); + if (time->tm_mon == month_days) { + time->tm_mday = 1; + if (time->tm_mon == 12) { + time->tm_mon = 1; + time->tm_year = time->tm_year + 1; + } else + time->tm_mon = time->tm_mon + 1; + } else + time->tm_mday = time->tm_mday + 1; +} diff --git a/src/common.h b/src/common.h index 6a1aeb0..8e3be91 100644 --- a/src/common.h +++ b/src/common.h @@ -12,11 +12,16 @@ #ifndef __CCOMMON_H #define __CCOMMON_H -#include #include #include +#include +#include +#include +#include +#include #include #include +#include #ifndef FREE #define FREE(x) do { if(x) {free(x); x = NULL;} } while (0) @@ -54,7 +59,7 @@ #define DEFAULT_RETRY_MAX_INTERVAL 60 #define DEFAULT_AMD_VERSION 5 #define DEFAULT_INSTANCE_MODE 0 -#define DEFAULT_SESSION_TIMEOUT 300 +#define DEFAULT_SESSION_TIMEOUT 60 #define MAX_NBRE_SERVICES 256 #define FIREWALL_CWMP "/etc/firewall.cwmp" #define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp" @@ -69,7 +74,12 @@ for (elt = strtok_r(buffer_str, delim, &tmpchr); elt != NULL; elt = strtok_r(NULL, delim, &tmpchr)) extern char *commandKey; -extern bool thread_end; +extern bool cwmp_stop; +extern struct uloop_timeout session_timer; +extern struct uloop_timeout periodic_session_timer; +extern struct uloop_timeout retry_session_timer; +extern bool g_firewall_restart; +extern struct list_head intf_reset_list; typedef struct env { unsigned short boot; @@ -126,42 +136,30 @@ struct deviceid { char *softwareversion; }; -typedef struct session_status { - time_t last_start_time; - time_t last_end_time; - int last_status; - time_t next_periodic; - time_t next_retry; - unsigned int success_session; - unsigned int failure_session; -} session_status; - typedef struct cwmp { struct env env; struct config conf; struct deviceid deviceid; - struct list_head head_session_queue; - pthread_mutex_t mutex_session_queue; - struct session *session_send; + struct session *session; bool cwmp_cr_event; bool init_complete; - pthread_mutex_t mutex_session_send; - pthread_cond_t threshold_session_send; - pthread_mutex_t mutex_periodic; - pthread_mutex_t mutex_notify_periodic; - pthread_cond_t threshold_periodic; - pthread_cond_t threshold_notify_periodic; - pthread_cond_t threshold_handle_notify; + bool prev_periodic_enable; + bool prev_heartbeat_enable; + bool heart_session; + bool diag_session; + int prev_periodic_interval; + int prev_heartbeat_interval; int count_handle_notify; int retry_count_session; - struct list_head *head_event_container; FILE *pid_file; time_t start_time; - struct session_status session_status; + time_t prev_periodic_time; + time_t prev_heartbeat_time; unsigned int cwmp_id; int event_id; int cr_socket_desc; int cwmp_period; + long int heart_session_interval; time_t cwmp_periodic_time; bool cwmp_periodic_enable; bool custom_notify_active; @@ -174,6 +172,11 @@ enum action { RESTART, }; +enum auth_type_enum { + AUTH_BASIC, + AUTH_DIGEST +}; + enum cwmp_start { CWMP_START_BOOT = 1, CWMP_START_PERIODIC = 2 @@ -368,15 +371,15 @@ enum client_server_faults { struct rpc_cpe_method { const char *name; - int (*handler)(struct session *session, struct rpc *rpc); + int (*handler)(struct rpc *rpc); int amd; }; struct rpc_acs_method { const char *name; - int (*prepare_message)(struct cwmp *cwmp, struct session *session, struct rpc *rpc); - int (*parse_response)(struct cwmp *cwmp, struct session *session, struct rpc *rpc); - int (*extra_clean)(struct session *session, struct rpc *rpc); + int (*prepare_message)(struct rpc *rpc); + int (*parse_response)(struct rpc *rpc); + int (*extra_clean)(struct rpc *rpc); int acs_support; }; @@ -389,6 +392,7 @@ typedef struct FAULT_CPE { typedef struct schedule_inform { struct list_head list; + struct uloop_timeout handler_timer ; time_t scheduled_time; char *commandKey; } schedule_inform; @@ -403,6 +407,7 @@ typedef struct timewindow { typedef struct download { struct list_head list; + struct uloop_timeout handler_timer; time_t scheduled_time; int file_size; char *command_key; @@ -419,16 +424,9 @@ typedef struct timeinterval { int maxretries; } timeinterval; -typedef struct apply_schedule_download { - struct list_head list; - char *start_time; - char *command_key; - char *file_type; - struct timeinterval timeintervals[2]; -} apply_schedule_download; - typedef struct change_du_state { struct list_head list; + struct uloop_timeout handler_timer; time_t timeout; char *command_key; struct list_head list_operation; @@ -447,6 +445,7 @@ typedef struct operations { typedef struct upload { struct list_head list; + struct uloop_timeout handler_timer ; time_t scheduled_time; char *file_type; char *command_key; @@ -494,10 +493,11 @@ typedef struct intf_reset_node { struct list_head list; } intf_reset_node; -extern struct cwmp cwmp_main; +extern struct cwmp *cwmp_main; extern long int flashsize; extern struct FAULT_CPE FAULT_CPE_ARRAY[]; extern struct cwmp_namespaces ns; +extern struct session_timer_event *global_session_event; void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *param_data, char *param_type, int notification, bool writable); void delete_dm_parameter_from_list(struct cwmp_dm_parameter *dm_parameter); @@ -541,11 +541,11 @@ int get_connection_interface(); char *get_time(time_t t_time); bool is_obj_excluded(const char *object_name); time_t convert_datetime_to_timestamp(char *value); -int cwmp_get_retry_interval(struct cwmp *cwmp, bool heart_beat); -int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session); int run_session_end_func(void); void set_interface_reset_request(char *param_name, char *value); bool uci_str_to_bool(char *value); bool match_reg_exp(char *reg_exp, char *param_name); - +void cwmp_invoke_intf_reset(char *path); +void check_firewall_restart_state(); +void add_day_to_time(struct tm *time); #endif diff --git a/src/config.c b/src/config.c index 2dc8a87..8cd2879 100755 --- a/src/config.c +++ b/src/config.c @@ -172,7 +172,7 @@ static char* get_value_from_uci_option(struct uci_option *tb) { return NULL; } -static void config_get_cpe_elements(struct config *conf, struct uci_section *s) +static void config_get_cpe_elements(struct uci_section *s) { enum { UCI_CPE_UBUS_SOCKET_PATH, @@ -202,8 +202,8 @@ static void config_get_cpe_elements(struct config *conf, struct uci_section *s) struct uci_option *cpe_tb[__MAX_NUM_UCI_CPE_ATTRS] = {0}; uci_parse_section(s, cpe_opts, __MAX_NUM_UCI_CPE_ATTRS, cpe_tb); - conf->ubus_socket = CWMP_STRDUP(get_value_from_uci_option(cpe_tb[UCI_CPE_UBUS_SOCKET_PATH])); - CWMP_LOG(DEBUG, "CWMP CONFIG - ubus socket: %s", conf->ubus_socket ? conf->ubus_socket : ""); + cwmp_main->conf.ubus_socket = CWMP_STRDUP(get_value_from_uci_option(cpe_tb[UCI_CPE_UBUS_SOCKET_PATH])); + CWMP_LOG(DEBUG, "CWMP CONFIG - ubus socket: %s", cwmp_main->conf.ubus_socket ? cwmp_main->conf.ubus_socket : ""); log_set_log_file_name(get_value_from_uci_option(cpe_tb[UCI_CPE_LOG_FILE_NAME])); @@ -217,25 +217,25 @@ static void config_get_cpe_elements(struct config *conf, struct uci_section *s) log_set_on_syslog(get_value_from_uci_option(cpe_tb[UCI_CPE_ENABLE_SYSLOG])); - conf->amd_version = DEFAULT_AMD_VERSION; + cwmp_main->conf.amd_version = DEFAULT_AMD_VERSION; char *version = get_value_from_uci_option(cpe_tb[UCI_CPE_AMD_VERSION]); if (version != NULL) { int a = atoi(version); if (a >= 1 && a <= 6) { - conf->amd_version = a; + cwmp_main->conf.amd_version = a; } } - conf->supported_amd_version = conf->amd_version; - CWMP_LOG(DEBUG, "CWMP CONFIG - amendement version: %d", conf->amd_version); + cwmp_main->conf.supported_amd_version = cwmp_main->conf.amd_version; + CWMP_LOG(DEBUG, "CWMP CONFIG - amendement version: %d", cwmp_main->conf.amd_version); if (cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE]) { - conf->default_wan_iface = strdup(get_value_from_uci_option(cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE])); + cwmp_main->conf.default_wan_iface = strdup(get_value_from_uci_option(cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE])); } else { - conf->default_wan_iface = strdup("wan"); + cwmp_main->conf.default_wan_iface = strdup("wan"); } - CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", conf->default_wan_iface); + CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main->conf.default_wan_iface); } -static void config_get_acs_elements(struct config *conf, struct uci_section *s) +static void config_get_acs_elements(struct uci_section *s) { enum { UCI_ACS_IPV6_ENABLE, @@ -256,20 +256,20 @@ static void config_get_acs_elements(struct config *conf, struct uci_section *s) memset(acs_tb, 0, sizeof(acs_tb)); uci_parse_section(s, acs_opts, __MAX_NUM_UCI_ACS_ATTRS, acs_tb); - conf->ipv6_enable = uci_str_to_bool(get_value_from_uci_option(acs_tb[UCI_ACS_IPV6_ENABLE])); - CWMP_LOG(DEBUG, "CWMP CONFIG - ipv6 enable: %d", conf->ipv6_enable); + cwmp_main->conf.ipv6_enable = uci_str_to_bool(get_value_from_uci_option(acs_tb[UCI_ACS_IPV6_ENABLE])); + CWMP_LOG(DEBUG, "CWMP CONFIG - ipv6 enable: %d", cwmp_main->conf.ipv6_enable); - conf->acs_ssl_capath = CWMP_STRDUP(get_value_from_uci_option(acs_tb[UCI_ACS_SSL_CAPATH])); - CWMP_LOG(DEBUG, "CWMP CONFIG - acs ssl cpath: %s", conf->acs_ssl_capath ? conf->acs_ssl_capath : ""); + cwmp_main->conf.acs_ssl_capath = CWMP_STRDUP(get_value_from_uci_option(acs_tb[UCI_ACS_SSL_CAPATH])); + CWMP_LOG(DEBUG, "CWMP CONFIG - acs ssl cpath: %s", cwmp_main->conf.acs_ssl_capath ? cwmp_main->conf.acs_ssl_capath : ""); - conf->http_disable_100continue = uci_str_to_bool(get_value_from_uci_option(acs_tb[HTTP_DISABLE_100CONTINUE])); - CWMP_LOG(DEBUG, "CWMP CONFIG - http disable 100continue: %d", conf->http_disable_100continue); + cwmp_main->conf.http_disable_100continue = uci_str_to_bool(get_value_from_uci_option(acs_tb[HTTP_DISABLE_100CONTINUE])); + CWMP_LOG(DEBUG, "CWMP CONFIG - http disable 100continue: %d", cwmp_main->conf.http_disable_100continue); - conf->insecure_enable = uci_str_to_bool(get_value_from_uci_option(acs_tb[UCI_ACS_INSECURE_ENABLE])); - CWMP_LOG(DEBUG, "CWMP CONFIG - acs insecure enable: %d", conf->insecure_enable); + cwmp_main->conf.insecure_enable = uci_str_to_bool(get_value_from_uci_option(acs_tb[UCI_ACS_INSECURE_ENABLE])); + CWMP_LOG(DEBUG, "CWMP CONFIG - acs insecure enable: %d", cwmp_main->conf.insecure_enable); } -int get_preinit_config(struct config *conf) +int get_preinit_config() { struct uci_context *ctx; struct uci_package *pkg; @@ -287,9 +287,9 @@ int get_preinit_config(struct config *conf) uci_foreach_element(&pkg->sections, e) { struct uci_section *s = uci_to_section(e); if (strcmp(s->type, "acs") == 0) { - config_get_acs_elements(conf, s); + config_get_acs_elements(s); } else if (strcmp(s->type, "cpe") == 0) { - config_get_cpe_elements(conf, s); + config_get_cpe_elements(s); } } @@ -308,7 +308,7 @@ static char* get_alternate_option_value(bool discovery_enable, char *acs_val, ch return NULL; } -int get_global_config(struct config *conf) +int get_global_config() { int error; char *value = NULL, *value2 = NULL, *value3 = NULL; @@ -322,9 +322,9 @@ int get_global_config(struct config *conf) } FREE(value); - error = get_connection_interface(conf->default_wan_iface); + error = get_connection_interface(cwmp_main->conf.default_wan_iface); if (error != CWMP_OK) { - CWMP_LOG(DEBUG, "Failed to get interface [%s] details", conf->default_wan_iface); + CWMP_LOG(DEBUG, "Failed to get interface [%s] details", cwmp_main->conf.default_wan_iface); return error; } @@ -334,8 +334,8 @@ int get_global_config(struct config *conf) // now read the vendor info from ifstatus before reading the DHCP_ACS_URL from uci if (error == CWMP_OK && value != NULL) { discovery_enable = uci_str_to_bool(value); - if (discovery_enable == true && conf->default_wan_iface != NULL) { - get_dhcp_vendor_info(conf->default_wan_iface); + if (discovery_enable == true && cwmp_main->conf.default_wan_iface != NULL) { + get_dhcp_vendor_info(cwmp_main->conf.default_wan_iface); } } FREE(value); @@ -343,20 +343,20 @@ int get_global_config(struct config *conf) uci_get_value(UCI_ACS_URL_PATH, &value2); uci_get_value(UCI_DHCP_ACS_URL, &value3); - FREE(conf->acsurl); - conf->acsurl = CWMP_STRDUP(get_alternate_option_value(discovery_enable, value2, value3)); + FREE(cwmp_main->conf.acsurl); + cwmp_main->conf.acsurl = CWMP_STRDUP(get_alternate_option_value(discovery_enable, value2, value3)); FREE(value2); FREE(value3); - if (conf->acsurl == NULL) { + if (cwmp_main->conf.acsurl == NULL) { return CWMP_GEN_ERR; } if ((error = uci_get_value(UCI_ACS_USERID_PATH, &value)) == CWMP_OK) { if (value != NULL) { - FREE(conf->acs_userid); - conf->acs_userid = strdup(value); + FREE(cwmp_main->conf.acs_userid); + cwmp_main->conf.acs_userid = strdup(value); FREE(value); } } else { @@ -365,8 +365,8 @@ int get_global_config(struct config *conf) if ((error = uci_get_value(UCI_ACS_PASSWD_PATH, &value)) == CWMP_OK) { if (value != NULL) { - FREE(conf->acs_passwd); - conf->acs_passwd = strdup(value); + FREE(cwmp_main->conf.acs_passwd); + cwmp_main->conf.acs_passwd = strdup(value); FREE(value); } } else { @@ -374,31 +374,30 @@ int get_global_config(struct config *conf) } if ((error = uci_get_value(UCI_ACS_COMPRESSION, &value)) == CWMP_OK) { - conf->compression = COMP_NONE; - if (conf->amd_version >= AMD_5 && value != NULL) { + cwmp_main->conf.compression = COMP_NONE; + if (cwmp_main->conf.amd_version >= AMD_5 && value != NULL) { if (0 == strcasecmp(value, "gzip")) { - conf->compression = COMP_GZIP; + cwmp_main->conf.compression = COMP_GZIP; } else if (0 == strcasecmp(value, "deflate")) { - conf->compression = COMP_DEFLATE; + cwmp_main->conf.compression = COMP_DEFLATE; } else { - conf->compression = COMP_NONE; + cwmp_main->conf.compression = COMP_NONE; } } FREE(value); - } else { - conf->compression = COMP_NONE; - } + } else + cwmp_main->conf.compression = COMP_NONE; - conf->retry_min_wait_interval = DEFAULT_RETRY_MINIMUM_WAIT_INTERVAL; + cwmp_main->conf.retry_min_wait_interval = DEFAULT_RETRY_MINIMUM_WAIT_INTERVAL; uci_get_value(UCI_ACS_RETRY_MIN_WAIT_INTERVAL, &value2); uci_get_value(UCI_DHCP_ACS_RETRY_MIN_WAIT_INTERVAL, &value3); char *op_interval = get_alternate_option_value(discovery_enable, value2, value3); if (op_interval != NULL) { - if (conf->amd_version >= AMD_3) { + if (cwmp_main->conf.amd_version >= AMD_3) { int a = atoi(op_interval); if (a <= 65535 && a >= 1) { - conf->retry_min_wait_interval = a; + cwmp_main->conf.retry_min_wait_interval = a; } } } @@ -406,16 +405,16 @@ int get_global_config(struct config *conf) FREE(value2); FREE(value3); - conf->retry_interval_multiplier = DEFAULT_RETRY_INTERVAL_MULTIPLIER; + cwmp_main->conf.retry_interval_multiplier = DEFAULT_RETRY_INTERVAL_MULTIPLIER; uci_get_value(UCI_ACS_RETRY_INTERVAL_MULTIPLIER, &value2); uci_get_value(UCI_DHCP_ACS_RETRY_INTERVAL_MULTIPLIER, &value3); char *op_multi = get_alternate_option_value(discovery_enable, value2, value3); if (op_multi != NULL) { - if (conf->amd_version >= AMD_3) { + if (cwmp_main->conf.amd_version >= AMD_3) { int a = atoi(op_multi); if (a <= 65535 && a >= 1000) { - conf->retry_interval_multiplier = a; + cwmp_main->conf.retry_interval_multiplier = a; } } } @@ -424,24 +423,23 @@ int get_global_config(struct config *conf) FREE(value3); if ((error = uci_get_value(UCI_CPE_USERID_PATH, &value)) == CWMP_OK) { - FREE(conf->cpe_userid); + FREE(cwmp_main->conf.cpe_userid); if (value != NULL) { - conf->cpe_userid = strdup(value); + cwmp_main->conf.cpe_userid = strdup(value); FREE(value); - } else { - conf->cpe_userid = strdup(""); - } + } else + cwmp_main->conf.cpe_userid = strdup(""); } else { return error; } if ((error = uci_get_value(UCI_CPE_PASSWD_PATH, &value)) == CWMP_OK) { - FREE(conf->cpe_passwd); + FREE(cwmp_main->conf.cpe_passwd); if (value != NULL) { - conf->cpe_passwd = strdup(value); + cwmp_main->conf.cpe_passwd = strdup(value); FREE(value); } else { - conf->cpe_passwd = strdup(""); + cwmp_main->conf.cpe_passwd = strdup(""); } } else { return error; @@ -457,25 +455,25 @@ int get_global_config(struct config *conf) if (a == 0) { CWMP_LOG(INFO, "Set the connection request port to the default value: %d", DEFAULT_CONNECTION_REQUEST_PORT); - conf->connection_request_port = DEFAULT_CONNECTION_REQUEST_PORT; + cwmp_main->conf.connection_request_port = DEFAULT_CONNECTION_REQUEST_PORT; } else { - conf->connection_request_port = a; + cwmp_main->conf.connection_request_port = a; } } else { return error; } if ((error = uci_get_value(UCI_CPE_CRPATH_PATH, &value)) == CWMP_OK) { - FREE(conf->connection_request_path); + FREE(cwmp_main->conf.connection_request_path); if (value == NULL) - conf->connection_request_path = strdup("/"); + cwmp_main->conf.connection_request_path = strdup("/"); else { if (value[0] == '/') - conf->connection_request_path = strdup(value); + cwmp_main->conf.connection_request_path = strdup(value); else { char cr_path[512]; snprintf(cr_path, sizeof(cr_path), "/%s", value); - conf->connection_request_path = strdup(cr_path); + cwmp_main->conf.connection_request_path = strdup(cr_path); } FREE(value); } @@ -489,7 +487,7 @@ int get_global_config(struct config *conf) a = uci_str_to_bool(value); FREE(value); } - conf->periodic_notify_enable = a; + cwmp_main->conf.periodic_notify_enable = a; } else { return error; } @@ -504,9 +502,9 @@ int get_global_config(struct config *conf) if (a == 0) { CWMP_LOG(INFO, "Set notify period to the default value: %d", DEFAULT_NOTIFY_PERIOD); - conf->periodic_notify_interval = DEFAULT_NOTIFY_PERIOD; + cwmp_main->conf.periodic_notify_interval = DEFAULT_NOTIFY_PERIOD; } else { - conf->periodic_notify_interval = a; + cwmp_main->conf.periodic_notify_interval = a; } } else { return error; @@ -514,18 +512,16 @@ int get_global_config(struct config *conf) if ((error = uci_get_value(UCI_PERIODIC_INFORM_TIME_PATH, &value)) == CWMP_OK) { if (value != NULL) { - conf->time = convert_datetime_to_timestamp(value); + cwmp_main->conf.time = convert_datetime_to_timestamp(value); FREE(value); - } else { - conf->time = 0; - } - } else { + } else + cwmp_main->conf.time = 0; + } else return error; - } char *entropy = generate_random_string(sizeof(unsigned int)); if (entropy != NULL) { - conf->periodic_entropy = (unsigned int)strtoul(entropy, NULL, 16); + cwmp_main->conf.periodic_entropy = (unsigned int)strtoul(entropy, NULL, 16); free(entropy); } @@ -538,17 +534,17 @@ int get_global_config(struct config *conf) } if (a >= PERIOD_INFORM_MIN) { - conf->period = a; + cwmp_main->conf.period = a; } else { CWMP_LOG(ERROR, "Period interval of periodic inform should be > %ds. Set to default: %ds", PERIOD_INFORM_MIN, PERIOD_INFORM_DEFAULT); - conf->period = PERIOD_INFORM_DEFAULT; + cwmp_main->conf.period = PERIOD_INFORM_DEFAULT; } } else { return error; } if ((error = uci_get_value(UCI_PERIODIC_INFORM_ENABLE_PATH, &value)) == CWMP_OK) { - conf->periodic_enable = uci_str_to_bool(value); + cwmp_main->conf.periodic_enable = uci_str_to_bool(value); FREE(value); } else { return error; @@ -557,24 +553,24 @@ int get_global_config(struct config *conf) if ((error = uci_get_value(UCI_CPE_INSTANCE_MODE, &value)) == CWMP_OK) { if (value != NULL) { if (0 == strcmp(value, "InstanceNumber")) { - conf->instance_mode = INSTANCE_MODE_NUMBER; + cwmp_main->conf.instance_mode = INSTANCE_MODE_NUMBER; } else { - conf->instance_mode = INSTANCE_MODE_ALIAS; + cwmp_main->conf.instance_mode = INSTANCE_MODE_ALIAS; } FREE(value); } else { - conf->instance_mode = DEFAULT_INSTANCE_MODE; + cwmp_main->conf.instance_mode = DEFAULT_INSTANCE_MODE; } } else { return error; } if ((error = uci_get_value(UCI_CPE_SESSION_TIMEOUT, &value)) == CWMP_OK) { - conf->session_timeout = DEFAULT_SESSION_TIMEOUT; + cwmp_main->conf.session_timeout = DEFAULT_SESSION_TIMEOUT; if (value != NULL) { int a = atoi(value); if (a >= 1) { - conf->session_timeout = a; + cwmp_main->conf.session_timeout = a; } FREE(value); } @@ -583,19 +579,19 @@ int get_global_config(struct config *conf) } if ((error = uci_get_value(LW_NOTIFICATION_ENABLE, &value)) == CWMP_OK) { - conf->lw_notification_enable = uci_str_to_bool(value); + cwmp_main->conf.lw_notification_enable = uci_str_to_bool(value); FREE(value); } else { return error; } if ((error = uci_get_value(LW_NOTIFICATION_HOSTNAME, &value)) == CWMP_OK) { - FREE(conf->lw_notification_hostname); + FREE(cwmp_main->conf.lw_notification_hostname); if (value != NULL) { - conf->lw_notification_hostname = strdup(value); + cwmp_main->conf.lw_notification_hostname = strdup(value); FREE(value); } else { - conf->lw_notification_hostname = strdup(conf->acsurl ? conf->acsurl : ""); + cwmp_main->conf.lw_notification_hostname = strdup(cwmp_main->conf.acsurl ? cwmp_main->conf.acsurl : ""); } } else { return error; @@ -604,10 +600,10 @@ int get_global_config(struct config *conf) if ((error = uci_get_value(LW_NOTIFICATION_PORT, &value)) == CWMP_OK) { if (value != NULL) { int a = atoi(value); - conf->lw_notification_port = a; + cwmp_main->conf.lw_notification_port = a; FREE(value); } else { - conf->lw_notification_port = DEFAULT_LWN_PORT; + cwmp_main->conf.lw_notification_port = DEFAULT_LWN_PORT; } } else { return error; @@ -615,10 +611,10 @@ int get_global_config(struct config *conf) if (uci_get_value(UCI_CPE_SCHEDULE_REBOOT, &value) == CWMP_OK) { if (value != NULL) { - conf->schedule_reboot = convert_datetime_to_timestamp(value); + cwmp_main->conf.schedule_reboot = convert_datetime_to_timestamp(value); FREE(value); } else { - conf->schedule_reboot = 0; + cwmp_main->conf.schedule_reboot = 0; } } else { return error; @@ -632,22 +628,22 @@ int get_global_config(struct config *conf) FREE(value); } - conf->delay_reboot = delay; + cwmp_main->conf.delay_reboot = delay; } else { return error; } if (uci_get_value(UCI_CPE_JSON_CUSTOM_NOTIFY_FILE, &value) == CWMP_OK) { - FREE(conf->custom_notify_json); + FREE(cwmp_main->conf.custom_notify_json); if (value != NULL) { - conf->custom_notify_json = strdup(value); + cwmp_main->conf.custom_notify_json = strdup(value); FREE(value); } else { - conf->custom_notify_json = NULL; + cwmp_main->conf.custom_notify_json = NULL; } } if ((error = uci_get_value(UCI_ACS_HEARTBEAT_ENABLE, &value)) == CWMP_OK) { - conf->heart_beat_enable = uci_str_to_bool(value); + cwmp_main->conf.heart_beat_enable = uci_str_to_bool(value); FREE(value); } else { return error; @@ -660,17 +656,17 @@ int get_global_config(struct config *conf) a = atoi(value); FREE(value); } - conf->heartbeat_interval = a; + cwmp_main->conf.heartbeat_interval = a; } else { return error; } if ((error = uci_get_value(UCI_ACS_HEARTBEAT_TIME, &value)) == CWMP_OK) { if (value != NULL) { - conf->heart_time = convert_datetime_to_timestamp(value); + cwmp_main->conf.heart_time = convert_datetime_to_timestamp(value); FREE(value); } else { - conf->heart_time = 0; + cwmp_main->conf.heart_time = 0; } } else { return error; @@ -678,20 +674,20 @@ int get_global_config(struct config *conf) return CWMP_OK; } -int global_conf_init(struct cwmp *cwmp) +int global_conf_init() { int error = CWMP_OK; pthread_mutex_lock(&mutex_config_load); - if ((error = get_global_config(&(cwmp->conf)))) { - cwmp->init_complete = false; + if ((error = get_global_config(&(cwmp_main->conf)))) { + cwmp_main->init_complete = false; goto end; } - cwmp->init_complete = true; + cwmp_main->init_complete = true; /* Launch reboot methods if needed */ - launch_reboot_methods(cwmp); + launch_reboot_methods(); end: pthread_mutex_unlock(&mutex_config_load); @@ -699,34 +695,34 @@ end: return error; } -void cwmp_config_load(struct cwmp *cwmp) +void cwmp_config_load() { int ret; cwmp_uci_reinit(); - ret = global_conf_init(cwmp); - while (ret != CWMP_OK && thread_end != true) { + ret = global_conf_init(); + while (ret != CWMP_OK && cwmp_stop != true) { CWMP_LOG(DEBUG, "Error reading uci ret = %d", ret); sleep(UCI_OPTION_READ_INTERVAL); cwmp_uci_reinit(); - ret = global_conf_init(cwmp); + ret = global_conf_init(); } } -int cwmp_get_deviceid(struct cwmp *cwmp) +int cwmp_get_deviceid() { - cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp->deviceid.manufacturer); - cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp->deviceid.serialnumber); - cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp->deviceid.productclass); - cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp->deviceid.oui); - cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp->deviceid.softwareversion); + cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp_main->deviceid.manufacturer); + cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp_main->deviceid.serialnumber); + cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp_main->deviceid.productclass); + cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp_main->deviceid.oui); + cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp_main->deviceid.softwareversion); return CWMP_OK; } -int cwmp_config_reload(struct cwmp *cwmp) +int cwmp_config_reload() { - memset(&cwmp->env, 0, sizeof(struct env)); - int err = global_conf_init(cwmp); + memset(&cwmp_main->env, 0, sizeof(struct env)); + int err = global_conf_init(); if (err != CWMP_OK) return err; diff --git a/src/config.h b/src/config.h index 1336e4d..cef643d 100755 --- a/src/config.h +++ b/src/config.h @@ -17,10 +17,10 @@ extern pthread_mutex_t mutex_config_load; -int global_conf_init(struct cwmp *cwmp); -int get_global_config(struct config *conf); -int cwmp_get_deviceid(struct cwmp *cwmp); -int cwmp_config_reload(struct cwmp *cwmp); -int get_preinit_config(struct config *conf); -void cwmp_config_load(struct cwmp *cwmp); +int global_conf_init(); +int get_global_config(); +int cwmp_get_deviceid(); +int cwmp_config_reload(); +int get_preinit_config(); +void cwmp_config_load(); #endif diff --git a/src/cwmp.c b/src/cwmp.c index 27d4e9f..76f2215 100644 --- a/src/cwmp.c +++ b/src/cwmp.c @@ -39,40 +39,11 @@ #include "datamodel_interface.h" #include "cwmp_du_state.h" #include "heartbeat.h" +#include "cwmp_http.h" -static pthread_t periodic_event_thread; -static pthread_t scheduleInform_thread; -static pthread_t change_du_state_thread; -static pthread_t download_thread; -static pthread_t schedule_download_thread; -static pthread_t apply_schedule_download_thread; -static pthread_t upload_thread; -static pthread_t ubus_thread; -static pthread_t http_cr_server_thread; -static pthread_t periodic_check_notify; -static pthread_t heart_beat_session_thread; bool g_firewall_restart = false; -static struct ubus_context *ctx = NULL; struct list_head intf_reset_list; -static void cwmp_invoke_intf_reset(char *path) -{ - if (path == NULL) - return; - - CWMP_LOG(INFO, "Reset interface: %s", path); - struct blob_buf b = { 0 }; - memset(&b, 0, sizeof(struct blob_buf)); - blob_buf_init(&b, 0); - bb_add_string(&b, "path", path); - bb_add_string(&b, "action", "Reset()"); - - icwmp_ubus_invoke(USP_OBJECT_NAME, "operate", b.head, NULL, NULL); - blob_buf_free(&b); - - return; -} - static bool interface_reset_req(char *param_name, char *value) { if (param_name == NULL || value == NULL) @@ -121,475 +92,6 @@ void set_interface_reset_request(char *param_name, char *value) list_add_tail(&node->list, &intf_reset_list); } -int cwmp_get_retry_interval(struct cwmp *cwmp, bool heart_beat) -{ - unsigned int retry_count = 0; - double min = 0; - double max = 0; - int m = cwmp->conf.retry_min_wait_interval; - int k = cwmp->conf.retry_interval_multiplier; - int exp; - if (heart_beat) - exp = heart_beat_retry_count_session; - else - exp = cwmp->retry_count_session; - if (exp == 0) - return MAX_INT32; - if (exp > 10) - exp = 10; - min = pow(((double)k / 1000), (double)(exp - 1)) * m; - max = pow(((double)k / 1000), (double)exp) * m; - char *rand = generate_random_string(4); - if (rand) { - unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16); - retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min; - free(rand); - } - return (retry_count); -} - -static int cwmp_rpc_cpe_handle_message(struct session *session, struct rpc *rpc_cpe) -{ - if (xml_prepare_msg_out(session)) - return -1; - - if (rpc_cpe_methods[rpc_cpe->type].handler(session, rpc_cpe)) - return -1; - - if (xml_set_cwmp_id_rpc_cpe(session)) - return -1; - - return 0; -} - -static void cwmp_prepare_value_change(struct cwmp *cwmp) -{ - struct event_container *event_container; - if (list_value_change.next == &(list_value_change)) - return; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - if (!event_container) - goto end; - pthread_mutex_lock(&(mutex_value_change)); - list_splice_init(&(list_value_change), &(event_container->head_dm_parameter)); - pthread_mutex_unlock(&(mutex_value_change)); - cwmp_save_event_container(event_container); - -end: - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); -} - -int get_firewall_restart_state(char **state) -{ - cwmp_uci_reinit(); - return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state); -} - -// wait till firewall restart is not complete or 5 sec, whichever is less -void check_firewall_restart_state() -{ - int count = 0; - bool init = false; - - do { - char *state = NULL; - - if (get_firewall_restart_state(&state) != CWMP_OK) - break; - - if (state != NULL && strcmp(state, "init") == 0) { - init = true; - FREE(state); - break; - } - - usleep(500 * 1000); - FREE(state); - count++; - } while(count < 10); - - // mark the firewall restart as done - g_firewall_restart = false; - if (init == false) { // In case of timeout reset the firewall_restart flag - CWMP_LOG(ERROR, "Firewall restart took longer than usual"); - cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init"); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - } -} - -int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session) -{ - struct list_head *ilist; - struct rpc *rpc_acs, *rpc_cpe; - - if (icwmp_http_client_init(cwmp) || thread_end) { - CWMP_LOG(INFO, "Initializing http client failed"); - goto retry; - } - - while (1) { - list_for_each (ilist, &(session->head_rpc_acs)) { - rpc_acs = list_entry(ilist, struct rpc, list); - if ((rpc_acs->type != RPC_ACS_INFORM) && (rpc_acs_methods[rpc_acs->type].acs_support == RPC_ACS_NOT_SUPPORT)) { - CWMP_LOG(WARNING, "The RPC method %s is not included in the RPCs list supported by the ACS", rpc_acs_methods[rpc_acs->type].name); - continue; - } - if (!rpc_acs->type || thread_end) - goto retry; - - CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name); - if (rpc_acs_methods[rpc_acs->type].prepare_message(cwmp, session, rpc_acs) || thread_end) - goto retry; - - if (xml_set_cwmp_id(session) || thread_end) - goto retry; - - CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name); - if (xml_send_message(cwmp, session, rpc_acs) || thread_end) - goto retry; - - CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); - if (rpc_acs_methods[rpc_acs->type].parse_response || thread_end) - if (rpc_acs_methods[rpc_acs->type].parse_response(cwmp, session, rpc_acs)) - goto retry; - - ilist = ilist->prev; - if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL) - rpc_acs_methods[rpc_acs->type].extra_clean(session, rpc_acs); - cwmp_session_rpc_destructor(rpc_acs); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - if (session->hold_request || thread_end) - break; - } - - // If restart service caused firewall restart, wait for firewall restart to complete - if (g_firewall_restart == true) - check_firewall_restart_state(); - - CWMP_LOG(INFO, "Send empty message to the ACS"); - if (xml_send_message(cwmp, session, NULL) || thread_end) - goto retry; - if (!session->tree_in || thread_end) - goto next; - - CWMP_LOG(INFO, "Receive request from the ACS"); - if (xml_handle_message(session) || thread_end) - goto retry; - - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list); - if (!rpc_cpe->type || thread_end) - goto retry; - - CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); - if (cwmp_rpc_cpe_handle_message(session, rpc_cpe) || thread_end) - goto retry; - MXML_DELETE(session->tree_in); - - CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); - if (xml_send_message(cwmp, session, rpc_cpe) || thread_end) - goto retry; - MXML_DELETE(session->tree_out); - - cwmp_session_rpc_destructor(rpc_cpe); - if (!session->tree_in || thread_end) - break; - - CWMP_LOG(INFO, "Receive request from the ACS"); - if (xml_handle_message(session) || thread_end) - goto retry; - } - - next: - if (session->head_rpc_acs.next == &(session->head_rpc_acs)) - break; - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - } - - session->error = CWMP_OK; - goto end; - -retry: - CWMP_LOG(INFO, "Failed"); - session->error = CWMP_RETRY_SESSION; - event_remove_noretry_event_container(session, cwmp); - -end: - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - icwmp_http_client_exit(); - xml_exit(); - return session->error; -} - -int run_session_end_func(void) -{ - if (end_session_flag & END_SESSION_RESTART_SERVICES) { - CWMP_LOG(INFO, "Restart modified services"); - icwmp_restart_services(); - } - - if (end_session_flag & END_SESSION_RELOAD) { - CWMP_LOG(INFO, "Config reload: end session request"); - cwmp_uci_reinit(); - if (cwmp_apply_acs_changes() != CWMP_OK) { - CWMP_LOG(ERROR, "config reload failed at session end"); - } - check_trigger_heartbeat_session(); - } - - if (end_session_flag & END_SESSION_INIT_NOTIFY) { - CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify"); - reinit_list_param_notify(); - } - - if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) { - CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file"); - cwmp_update_enabled_notify_file(); - } - - if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request"); - cwmp_nslookup_diagnostics(); - } - - if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request"); - cwmp_traceroute_diagnostics(); - } - - if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request"); - cwmp_udp_echo_diagnostics(); - } - - if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request"); - cwmp_serverselection_diagnostics(); - } - - if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request"); - cwmp_ip_ping_diagnostics(); - } - - if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing download diagnostic: end session request"); - cwmp_download_diagnostics(); - } - - if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing upload diagnostic: end session request"); - cwmp_upload_diagnostics(); - } - - if (end_session_flag & END_SESSION_REBOOT) { - CWMP_LOG(INFO, "Executing Reboot: end session request"); - cwmp_reboot(commandKey); - exit(EXIT_SUCCESS); - } - - if (end_session_flag & END_SESSION_FACTORY_RESET) { - CWMP_LOG(INFO, "Executing factory reset: end session request"); - cwmp_factory_reset(); - exit(EXIT_SUCCESS); - } - - if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) { - CWMP_LOG(INFO, "Executing factory reset soft: end session request"); - cwmp_factory_reset(); - exit(EXIT_SUCCESS); - } - - // check if any interface reset request exists then take action - intf_reset_node *iter = NULL, *node = NULL; - list_for_each_entry_safe(iter, node, &intf_reset_list, list) { - CWMP_LOG(INFO, "Executing interface reset: end session request"); - cwmp_invoke_intf_reset(iter->path); - list_del(&iter->list); - free(iter); - } - - INIT_LIST_HEAD(&intf_reset_list); - - cwmp_uci_exit(); - icwmp_cleanmem(); - end_session_flag = 0; - return CWMP_OK; -} - -static void cwmp_schedule_session(struct cwmp *cwmp) -{ - int t; - struct timespec time_to_wait = { 0, 0 }; - bool retry = false; - char *exec_download = NULL; - int is_notify = 0; - - cwmp->cwmp_cr_event = 0; - while (1) { - struct list_head *ilist; - struct session *session; - int error; - - pthread_mutex_lock(&(cwmp->mutex_session_send)); - ilist = (&(cwmp->head_session_queue))->next; - while ((ilist == &(cwmp->head_session_queue)) || retry) { - t = cwmp_get_retry_interval(cwmp, 0); - time_to_wait.tv_sec = time(NULL) + t; - CWMP_LOG(INFO, "Waiting the next session"); - - if (thread_end) { - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - pthread_cond_timedwait(&(cwmp->threshold_session_send), &(cwmp->mutex_session_send), &time_to_wait); - - if (thread_end) { - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - ilist = (&(cwmp->head_session_queue))->next; - retry = false; - } - pthread_mutex_lock(&mutex_heartbeat_session); - if (cwmp->session_status.last_status == SESSION_FAILURE) { - cwmp_config_load(cwmp); - if (thread_end) { - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - } - - session = list_entry(ilist, struct session, list); - if (file_exists(DM_ENABLED_NOTIFY)) { - if (!event_exist_in_list(cwmp, EVENT_IDX_4VALUE_CHANGE)) - is_notify = check_value_change(); - } - if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp->custom_notify_active) { - cwmp->custom_notify_active = false; - cwmp_update_enabled_notify_file(); - } - cwmp_prepare_value_change(cwmp); - clean_list_value_change(); - if ((error = cwmp_move_session_to_session_send(cwmp, session))) { - CWMP_LOG(EMERG, "FATAL error in the mutex process in the session scheduler!"); - exit(EXIT_FAILURE); - } - - cwmp->session_status.last_end_time = 0; - cwmp->session_status.last_start_time = time(NULL); - cwmp->session_status.last_status = SESSION_RUNNING; - cwmp->session_status.next_retry = 0; - - if (file_exists(fc_cookies)) - remove(fc_cookies); - cwmp_uci_init(); - CWMP_LOG(INFO, "Start session"); - - uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download); - if (exec_download && strcmp(exec_download, "1") == 0) { - CWMP_LOG(INFO, "Firmware downloaded and applied successfully"); - cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - } - FREE(exec_download); - error = cwmp_schedule_rpc(cwmp, session); - CWMP_LOG(INFO, "End session"); - cwmp_uci_exit(); - - if (thread_end) { - event_remove_all_event_container(session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - if (session->error == CWMP_RETRY_SESSION && (!list_empty(&(session->head_event_container)) || (list_empty(&(session->head_event_container)) && cwmp->cwmp_cr_event == 0))) { - cwmp_config_load(cwmp); - if (thread_end) { - event_remove_all_event_container(session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - run_session_end_func(); - error = cwmp_move_session_to_session_queue(cwmp, session); - CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp->retry_count_session, cwmp_get_retry_interval(cwmp, 0)); - retry = true; - cwmp->session_status.last_end_time = time(NULL); - cwmp->session_status.last_status = SESSION_FAILURE; - cwmp->session_status.next_retry = time(NULL) + cwmp_get_retry_interval(cwmp, 0); - cwmp->session_status.failure_session++; - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - continue; - } - event_remove_all_event_container(session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(session); - cwmp->session_send = NULL; - cwmp->retry_count_session = 0; - cwmp->session_status.last_end_time = time(NULL); - cwmp->session_status.last_status = SESSION_SUCCESS; - cwmp->session_status.next_retry = 0; - cwmp->session_status.success_session++; - pthread_cond_signal(&threasheld_retry_session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - } -} - -static void check_exit_timer_expiry(struct uloop_timeout *timeout) -{ - if (thread_end == true) { - uloop_end(); - } - - uloop_timeout_set(timeout, 1); -} - -static void *thread_uloop_run(void *v __attribute__((unused))) -{ - uloop_init(); - - ctx = ubus_connect(cwmp_main.conf.ubus_socket); - if (!ctx) - return NULL; - - ubus_add_uloop(ctx); - - if (icwmp_register_object(ctx)) - return NULL; - - struct uloop_timeout tm; - memset(&tm, 0, sizeof(tm)); - tm.cb = check_exit_timer_expiry; - uloop_timeout_set(&tm, 1); - - uloop_run(); - uloop_done(); - - return NULL; -} - -static void *thread_http_cr_server_listen(void *v __attribute__((unused))) -{ - icwmp_http_server_listen(); - return NULL; -} - int create_cwmp_var_state_files() { /* @@ -693,19 +195,30 @@ end: return 0; } -static int cwmp_init(struct cwmp *cwmp) +static int cwmp_init() { int error; + openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid()); + /* This is to initialize the global context in mxml, + * with out init mxml sometimes segfaults, when calling the destructor. + */ + mxml_error(NULL); + + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + cwmp_main->init_complete = false; + error = get_preinit_config(); + if (error) { + return error; + } + icwmp_init_list_services(); - cwmp->event_id = 0; - cwmp->cwmp_period = 0; - cwmp->cwmp_periodic_time = 0; - cwmp->cwmp_periodic_enable = false; /* Only One instance should run*/ - cwmp->pid_file = fopen("/var/run/icwmpd.pid", "w+"); - fcntl(fileno(cwmp->pid_file), F_SETFD, fcntl(fileno(cwmp->pid_file), F_GETFD) | FD_CLOEXEC); - int rc = flock(fileno(cwmp->pid_file), LOCK_EX | LOCK_NB); + cwmp_main->pid_file = fopen("/var/run/icwmpd.pid", "w+"); + fcntl(fileno(cwmp_main->pid_file), F_SETFD, fcntl(fileno(cwmp_main->pid_file), F_GETFD) | FD_CLOEXEC); + int rc = flock(fileno(cwmp_main->pid_file), LOCK_EX | LOCK_NB); + if (rc) { if (EWOULDBLOCK != errno) { char *piderr = "PID file creation failed: Quit the daemon!"; @@ -715,95 +228,96 @@ static int cwmp_init(struct cwmp *cwmp) } else exit(EXIT_SUCCESS); } - if (cwmp->pid_file) - fclose(cwmp->pid_file); - - pthread_mutex_init(&cwmp->mutex_periodic, NULL); - pthread_mutex_init(&cwmp->mutex_session_queue, NULL); - pthread_mutex_init(&cwmp->mutex_session_send, NULL); - pthread_mutex_init(&mutex_heartbeat_session, NULL); - pthread_mutex_init(&mutex_heartbeat, NULL); - INIT_LIST_HEAD(&(cwmp->head_session_queue)); + if (cwmp_main->pid_file) + fclose(cwmp_main->pid_file); if ((error = create_cwmp_var_state_files())) return error; CWMP_LOG(DEBUG, "Loading icwmpd configuration"); - cwmp_config_load(cwmp); + cwmp_config_load(); - if (thread_end == true) + cwmp_main->prev_periodic_enable = cwmp_main->conf.periodic_enable; + cwmp_main->prev_periodic_interval = cwmp_main->conf.period; + cwmp_main->prev_periodic_time = cwmp_main->conf.time; + cwmp_main->prev_heartbeat_enable = cwmp_main->conf.heart_beat_enable; + cwmp_main->prev_heartbeat_interval = cwmp_main->conf.heartbeat_interval; + cwmp_main->prev_heartbeat_time = cwmp_main->conf.heart_time; + cwmp_main->heart_session = false; + cwmp_main->diag_session = false; + if (cwmp_stop == true) return CWMP_GEN_ERR; CWMP_LOG(DEBUG, "Successfully load icwmpd configuration"); - cwmp_get_deviceid(cwmp); - load_custom_notify_json(cwmp); + cwmp_get_deviceid(); + load_custom_notify_json(); init_list_param_notify(); + create_cwmp_session_structure(); get_nonce_key(); memset(&intf_reset_list, 0, sizeof(struct list_head)); INIT_LIST_HEAD(&intf_reset_list); + cwmp_main->start_time = time(NULL); + cwmp_main->event_id = 0; + cwmp_main->cwmp_period = 0; + cwmp_main->cwmp_periodic_time = 0; + cwmp_main->cwmp_periodic_enable = false; return CWMP_OK; } -static void cwmp_free(struct cwmp *cwmp) +static void cwmp_free() { - FREE(cwmp->deviceid.manufacturer); - FREE(cwmp->deviceid.serialnumber); - FREE(cwmp->deviceid.productclass); - FREE(cwmp->deviceid.oui); - FREE(cwmp->deviceid.softwareversion); - FREE(cwmp->conf.lw_notification_hostname); - FREE(cwmp->conf.ip); - FREE(cwmp->conf.ipv6); - FREE(cwmp->conf.acsurl); - FREE(cwmp->conf.acs_userid); - FREE(cwmp->conf.acs_passwd); - FREE(cwmp->conf.interface); - FREE(cwmp->conf.cpe_userid); - FREE(cwmp->conf.cpe_passwd); - FREE(cwmp->conf.ubus_socket); - FREE(cwmp->conf.connection_request_path); - FREE(cwmp->conf.default_wan_iface); - FREE(cwmp->conf.custom_notify_json); + http_server_stop(); + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.custom_notify_json); FREE(nonce_key); clean_list_param_notify(); bkp_tree_clean(); - - if (ctx) { - icwmp_delete_object(ctx); - ubus_free(ctx); - } - + icwmp_uloop_ubus_exit(); icwmp_cleanmem(); cwmp_uci_exit(); + rpc_exit(); + clean_cwmp_session_structure(); + FREE(cwmp_main); + CWMP_LOG(INFO, "EXIT ICWMP"); + closelog(); } -static void icwmp_signal_handler(int signal_num) +void cwmp_exit() { - if (signal_num == SIGINT || signal_num == SIGTERM) { - thread_end = true; + cwmp_stop = true; - CWMP_LOG(INFO, "Received signal %d", signal_num); + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) + http_set_timeout(); - if (cwmp_main.session_status.last_status == SESSION_RUNNING) - http_set_timeout(); + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_cancel(&periodic_session_timer); + uloop_timeout_cancel(&session_timer); + uloop_timeout_cancel(&heartbeat_session_timer); + uloop_end(); + shutdown(cwmp_main->cr_socket_desc, SHUT_RDWR); + FREE(global_session_event); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); - pthread_cond_signal(&(cwmp_main.threshold_periodic)); - pthread_cond_signal(&(cwmp_main.threshold_notify_periodic)); - pthread_cond_signal(&threshold_schedule_inform); - pthread_cond_signal(&threshold_download); - pthread_cond_signal(&threshold_change_du_state); - pthread_cond_signal(&threshold_schedule_download); - pthread_cond_signal(&threshold_apply_schedule_download); - pthread_cond_signal(&threshold_upload); - pthread_cond_signal(&threshold_heartbeat_session); - pthread_cond_signal(&threasheld_retry_session); - - shutdown(cwmp_main.cr_socket_desc, SHUT_RDWR); - } + /* Free all memory allocation */ + cwmp_free(); } -static void configure_var_state(struct cwmp *cwmp) +static void configure_var_state() { char *zone_name = NULL; @@ -814,7 +328,7 @@ static void configure_var_state(struct cwmp *cwmp) cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG); cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG); - get_firewall_zone_name_by_wan_iface(cwmp->conf.default_wan_iface, &zone_name); + get_firewall_zone_name_by_wan_iface(cwmp_main->conf.default_wan_iface, &zone_name); cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan"); cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); @@ -822,133 +336,47 @@ static void configure_var_state(struct cwmp *cwmp) int main(int argc, char **argv) { - struct sigaction act; int error; struct env env; - memset(&cwmp_main, 0, sizeof(struct cwmp)); - openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - - /* This is to initialize the global context in mxml, - * with out init mxml sometimes segfaults, when calling the destructor. - */ - mxml_error(NULL); - - cwmp_main.init_complete = false; - error = wait_for_usp_raw_object(); if (error) return error; + if ((error = cwmp_init())) + return error; + memset(&env, 0, sizeof(struct env)); if ((error = global_env_init(argc, argv, &env))) return error; - memcpy(&(cwmp_main.env), &env, sizeof(struct env)); + memcpy(&(cwmp_main->env), &env, sizeof(struct env)); - error = get_preinit_config(&(cwmp_main.conf)); - if (error) { - return error; - } - - error = pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the ubus thread!"); - } - - if ((error = cwmp_init(&cwmp_main))) { - thread_end = true; - pthread_join(ubus_thread, NULL); - cwmp_free(&cwmp_main); - return error; - } - - CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid()); - cwmp_main.start_time = time(NULL); - - if ((error = cwmp_init_backup_session(&cwmp_main, NULL, ALL))) + if ((error = cwmp_init_backup_session(NULL, ALL))) return error; - if ((error = cwmp_root_cause_events(&cwmp_main))) + if ((error = cwmp_root_cause_events())) return error; - configure_var_state(&cwmp_main); + configure_var_state(); icwmp_http_server_init(); - memset(&act, 0, sizeof(act)); - act.sa_handler = icwmp_signal_handler; - sigaction(SIGINT, &act, 0); - sigaction(SIGTERM, &act, 0); + uloop_init(); - error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the http connection request server thread!"); - } + icwmp_uloop_ubus_init(); - error = pthread_create(&periodic_event_thread, NULL, &thread_event_periodic, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the periodic event thread!"); - } + trigger_cwmp_session_timer(); - error = pthread_create(&periodic_check_notify, NULL, &thread_periodic_check_notify, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the periodic check notify thread!"); - } + intiate_heartbeat_procedures(); - error = pthread_create(&heart_beat_session_thread, NULL, &thread_heartbeat_session, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating heartbeat session thread!"); - } + initiate_cwmp_periodic_session_feature(); - error = pthread_create(&scheduleInform_thread, NULL, &thread_cwmp_rpc_cpe_scheduleInform, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the scheduled inform thread!"); - } + http_server_start(); - error = pthread_create(&download_thread, NULL, &thread_cwmp_rpc_cpe_download, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the download thread!"); - } + uloop_run(); + uloop_done(); - error = pthread_create(&change_du_state_thread, NULL, &thread_cwmp_rpc_cpe_change_du_state, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the state change thread!"); - } + cwmp_exit(); - error = pthread_create(&schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_schedule_download, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the schedule download thread!"); - } - - error = pthread_create(&apply_schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_apply_schedule_download, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the schedule download thread!"); - } - - error = pthread_create(&upload_thread, NULL, &thread_cwmp_rpc_cpe_upload, (void *)&cwmp_main); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the download thread!"); - } - - cwmp_schedule_session(&cwmp_main); - - /* Join all threads */ - pthread_join(periodic_event_thread, NULL); - pthread_join(periodic_check_notify, NULL); - pthread_join(scheduleInform_thread, NULL); - pthread_join(download_thread, NULL); - pthread_join(upload_thread, NULL); - pthread_join(schedule_download_thread, NULL); - pthread_join(apply_schedule_download_thread, NULL); - pthread_join(change_du_state_thread, NULL); - pthread_join(http_cr_server_thread, NULL); - pthread_join(ubus_thread, NULL); - pthread_join(heart_beat_session_thread, NULL); - - /* Free all memory allocation */ - cwmp_free(&cwmp_main); - - CWMP_LOG(INFO, "EXIT ICWMP"); - closelog(); return CWMP_OK; } diff --git a/src/cwmp_du_state.c b/src/cwmp_du_state.c index 99d71c9..f554697 100644 --- a/src/cwmp_du_state.c +++ b/src/cwmp_du_state.c @@ -19,10 +19,9 @@ #include "datamodel_interface.h" #include "backupSession.h" #include "event.h" +#include "session.h" LIST_HEAD(list_change_du_state); -pthread_mutex_t mutex_change_du_state = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_change_du_state; void ubus_du_state_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) { @@ -323,198 +322,194 @@ int get_du_version(char *du_ref, char **version) return cwmp_get_leaf_value(version_param_path, version); } -void *thread_cwmp_rpc_cpe_change_du_state(void *v) +int change_du_state_fault(struct change_du_state *pchange_du_state, struct du_state_change_complete **pdu_state_change_complete) +{ + int error = FAULT_CPE_NO_FAULT; + struct operations *p, *q; + + *pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete)); + if (*pdu_state_change_complete == NULL) + return FAULT_CPE_INTERNAL_ERROR; + + error = FAULT_CPE_DOWNLOAD_FAILURE; + INIT_LIST_HEAD(&((*pdu_state_change_complete)->list_opresult)); + (*pdu_state_change_complete)->command_key = strdup(pchange_du_state->command_key ? pchange_du_state->command_key : ""); + (*pdu_state_change_complete)->timeout = pchange_du_state->timeout; + list_for_each_entry_safe (p, q, &pchange_du_state->list_operation, list) { + struct opresult *res = calloc(1, sizeof(struct opresult)); + list_add_tail(&(res->list), &((*pdu_state_change_complete)->list_opresult)); + res->uuid = strdup(p->uuid); + res->version = strdup(p->version); + res->current_state = strdup("Failed"); + res->start_time = strdup(get_time(time(NULL))); + res->complete_time = strdup(res->start_time); + res->fault = error; + } + bkp_session_insert_du_state_change_complete(*pdu_state_change_complete); + bkp_session_save(); + //cwmp_root_cause_changedustate_complete(*pdu_state_change_complete); + list_del(&(pchange_du_state->list)); + cwmp_free_change_du_state_request(pchange_du_state); + return FAULT_CPE_NO_FAULT; +} + +void change_du_state_execute(struct uloop_timeout *utimeout) { - struct cwmp *cwmp = (struct cwmp *)v; - struct timespec change_du_state_timeout = { 50, 0 }; int error = FAULT_CPE_NO_FAULT; - struct du_state_change_complete *pdu_state_change_complete; - long int time_of_grace = 216000; char *package_version = NULL; char *package_name = NULL; char *package_env = NULL; struct operations *p, *q; struct opresult *res; + struct du_state_change_complete *pdu_state_change_complete; char *du_ref = NULL; + //struct session_timer_event cdu_inform_event = {.session_timer_evt = {.cb = cwmp_schedule_session_with_event}, .event = CDU_Evt}; + struct session_timer_event *cdu_inform_event = calloc(1, sizeof(struct session_timer_event)); + struct change_du_state *pchange_du_state = container_of(utimeout, struct change_du_state, handler_timer); - for (;;) { + time_t current_time = time(NULL); + time_t timeout = current_time - pchange_du_state->timeout; - if (thread_end) + if ((timeout >= 0) && (timeout > CDU_TIMEOUT)) { + int err = change_du_state_fault(pchange_du_state, &pdu_state_change_complete); + if (err) { + CWMP_LOG(ERROR, "Not able to create CDU Change Complete fault because of an internal error"); + return; + } + goto end; + } + + pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete)); + if (pdu_state_change_complete == NULL) { + return; + } + + error = FAULT_CPE_NO_FAULT; + INIT_LIST_HEAD(&(pdu_state_change_complete->list_opresult)); + pdu_state_change_complete->command_key = strdup(pchange_du_state->command_key); + pdu_state_change_complete->timeout = pchange_du_state->timeout; + + list_for_each_entry_safe (p, q, &pchange_du_state->list_operation, list) { + res = calloc(1, sizeof(struct opresult)); + list_add_tail(&(res->list), &(pdu_state_change_complete->list_opresult)); + switch (p->type) { + case DU_INSTALL: + if (!environment_exists(p->executionenvref)) { + res->fault = FAULT_CPE_INTERNAL_ERROR; + break; + } + + error = cwmp_launch_du_install(p->url, p->uuid, p->username, p->password, get_exec_env_name(p->executionenvref), get_exec_env_id(p->executionenvref), &res); + + package_name = get_package_name_by_url(p->url); + + if (error == FAULT_CPE_NO_FAULT) { + du_ref = (package_name && p->executionenvref) ? get_deployment_unit_reference(package_name, p->executionenvref) : NULL; + get_du_version(du_ref, &package_version); + res->du_ref = strdup(du_ref ? du_ref : ""); + res->uuid = strdup(p->uuid ? p->uuid : ""); + res->current_state = strdup("Installed"); + res->resolved = 1; + res->version = strdup(package_version); + FREE(du_ref); + } else { + res->uuid = strdup(p->uuid ? p->uuid : ""); + res->current_state = strdup("Failed"); + res->resolved = 0; + } + + res->complete_time = strdup(get_time(time(NULL))); + res->fault = error; + FREE(du_ref); + FREE(package_version); break; - if (list_change_du_state.next != &(list_change_du_state)) { - struct change_du_state *pchange_du_state = list_entry(list_change_du_state.next, struct change_du_state, list); - time_t current_time = time(NULL); - time_t timeout = current_time - pchange_du_state->timeout; - if ((timeout >= 0) && (timeout > time_of_grace)) { - pthread_mutex_lock(&mutex_change_du_state); - pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete)); - if (pdu_state_change_complete != NULL) { - error = FAULT_CPE_DOWNLOAD_FAILURE; - INIT_LIST_HEAD(&(pdu_state_change_complete->list_opresult)); - pdu_state_change_complete->command_key = strdup(pchange_du_state->command_key ? pchange_du_state->command_key : ""); - pdu_state_change_complete->timeout = pchange_du_state->timeout; - list_for_each_entry_safe (p, q, &pchange_du_state->list_operation, list) { - res = calloc(1, sizeof(struct opresult)); - list_add_tail(&(res->list), &(pdu_state_change_complete->list_opresult)); - res->uuid = strdup(p->uuid); - res->version = strdup(p->version); - res->current_state = strdup("Failed"); - res->start_time = strdup(get_time(time(NULL))); - res->complete_time = strdup(res->start_time); - res->fault = error; - } - bkp_session_insert_du_state_change_complete(pdu_state_change_complete); - bkp_session_save(); - cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete); - } - list_del(&(pchange_du_state->list)); - cwmp_free_change_du_state_request(pchange_du_state); - pthread_mutex_unlock(&mutex_change_du_state); - continue; + case DU_UPDATE: + if (p->url == NULL || p->uuid == NULL || *(p->url) == '\0' || *(p->uuid) == '\0') { + error = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; + break; } - if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete)); - if (pdu_state_change_complete != NULL) { - error = FAULT_CPE_NO_FAULT; - INIT_LIST_HEAD(&(pdu_state_change_complete->list_opresult)); - pdu_state_change_complete->command_key = strdup(pchange_du_state->command_key); - pdu_state_change_complete->timeout = pchange_du_state->timeout; + du_ref = get_deployment_unit_by_uuid(p->uuid); + if (du_ref == NULL) { + error = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; + break; + } + char *execenv = calloc(40, sizeof(char)); - list_for_each_entry_safe (p, q, &pchange_du_state->list_operation, list) { - res = calloc(1, sizeof(struct opresult)); - list_add_tail(&(res->list), &(pdu_state_change_complete->list_opresult)); - switch (p->type) { - case DU_INSTALL: - if (!environment_exists(p->executionenvref)) { - res->fault = FAULT_CPE_INTERNAL_ERROR; - break; - } + snprintf(execenv, 40, "Device.SoftwareModules.ExecEnv.%s.", du_ref); + error = cwmp_launch_du_update(p->uuid, p->url, p->username, p->password, get_exec_env_name(execenv), get_exec_env_id(execenv), &res); - error = cwmp_launch_du_install(p->url, p->uuid, p->username, p->password, get_exec_env_name(p->executionenvref), get_exec_env_id(p->executionenvref), &res); + res->uuid = strdup(p->uuid ? p->uuid : ""); - package_name = get_package_name_by_url(p->url); - - if (error == FAULT_CPE_NO_FAULT) { - du_ref = (package_name && p->executionenvref) ? get_deployment_unit_reference(package_name, p->executionenvref) : NULL; - get_du_version(du_ref, &package_version); - res->du_ref = strdup(""); - res->uuid = strdup(""); - res->current_state = strdup("Installed"); - res->resolved = 1; - res->version = strdup(""); - FREE(du_ref); - } else { - res->uuid = strdup(p->uuid ? p->uuid : ""); - res->current_state = strdup("Failed"); - res->resolved = 0; - } - - res->complete_time = strdup(get_time(time(NULL))); - res->fault = error; - break; - - case DU_UPDATE: - if (p->url == NULL || p->uuid == NULL || *(p->url) == '\0' || *(p->uuid) == '\0') { - error = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; - break; - } - - du_ref = get_deployment_unit_by_uuid(p->uuid); - if (du_ref == NULL) { - error = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; - break; - } - char *execenv = calloc(40, sizeof(char)); - - snprintf(execenv, 40, "Device.SoftwareModules.ExecEnv.%s.", du_ref); - error = cwmp_launch_du_update(p->uuid, p->url, p->username, p->password, get_exec_env_name(execenv), get_exec_env_id(execenv), &res); - - res->uuid = strdup(p->uuid ? p->uuid : ""); - - if (error == FAULT_CPE_NO_FAULT) { - res->current_state = strdup("Installed"); - res->resolved = 1; - } else { - res->current_state = strdup("Failed"); - res->resolved = 0; - } - - get_du_version(du_ref, &package_version); - res->version = strdup(package_version ? package_version : ""); - res->du_ref = strdup(du_ref ? du_ref : ""); - res->complete_time = strdup(get_time(time(NULL))); - res->fault = error; - FREE(du_ref); - break; - - case DU_UNINSTALL: - if (p->uuid == NULL || *(p->uuid) == '\0' || !environment_exists(p->executionenvref)) { - res->fault = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; - break; - } - - get_deployment_unit_name_version(p->uuid, &package_name, &package_version, &package_env); - if (!package_name || *package_name == '\0' || !package_version || *package_version == '\0' || !package_env || *package_env == '\0') { - res->fault = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; - break; - } - du_ref = (package_name && package_env) ? get_deployment_unit_reference(package_name, package_env) : NULL; - get_du_version(du_ref, &package_version); - error = cwmp_launch_du_uninstall(package_name, get_exec_env_name(package_env), get_exec_env_id(package_env), &res); - if (error == FAULT_CPE_NO_FAULT) { - res->current_state = strdup("Uninstalled"); - res->resolved = 1; - } else { - res->current_state = strdup("Installed"); - res->resolved = 0; - } - - res->du_ref = strdup(du_ref ? du_ref : ""); - res->uuid = strdup(p->uuid); - res->version = strdup(package_version); - res->complete_time = strdup(get_time(time(NULL))); - res->fault = error; - FREE(du_ref); - FREE(package_name); - FREE(package_version); - FREE(package_env); - break; - } - } - - bkp_session_delete_change_du_state(pchange_du_state); - bkp_session_save(); - bkp_session_insert_du_state_change_complete(pdu_state_change_complete); - bkp_session_save(); - cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete); - } + if (error == FAULT_CPE_NO_FAULT) { + res->current_state = strdup("Installed"); + res->resolved = 1; + } else { + res->current_state = strdup("Failed"); + res->resolved = 0; } - pthread_mutex_lock(&mutex_change_du_state); - pthread_cond_timedwait(&threshold_change_du_state, &mutex_change_du_state, &change_du_state_timeout); - pthread_mutex_unlock(&mutex_change_du_state); + get_du_version(du_ref, &package_version); + res->version = strdup(package_version ? package_version : ""); + res->du_ref = strdup(du_ref ? du_ref : ""); + res->complete_time = strdup(get_time(time(NULL))); + res->fault = error; + FREE(du_ref); + FREE(package_version); + break; - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); + case DU_UNINSTALL: + if (p->uuid == NULL || *(p->uuid) == '\0' || !environment_exists(p->executionenvref)) { + res->fault = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; + break; + } - pthread_mutex_lock(&mutex_change_du_state); - list_del(&(pchange_du_state->list)); - cwmp_free_change_du_state_request(pchange_du_state); - pthread_mutex_unlock(&mutex_change_du_state); - continue; - } else { - pthread_mutex_lock(&mutex_change_du_state); - pthread_cond_wait(&threshold_change_du_state, &mutex_change_du_state); - pthread_mutex_unlock(&mutex_change_du_state); + get_deployment_unit_name_version(p->uuid, &package_name, &package_version, &package_env); + if (!package_name || *package_name == '\0' || !package_version || *package_version == '\0' || !package_env || *package_env == '\0') { + res->fault = FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT; + break; + } + du_ref = (package_name && package_env) ? get_deployment_unit_reference(package_name, package_env) : NULL; + get_du_version(du_ref, &package_version); + error = cwmp_launch_du_uninstall(package_name, get_exec_env_name(package_env), get_exec_env_id(package_env), &res); + if (error == FAULT_CPE_NO_FAULT) { + res->current_state = strdup("Uninstalled"); + res->resolved = 1; + } else { + res->current_state = strdup("Installed"); + res->resolved = 0; + } + + res->du_ref = strdup(du_ref ? du_ref : ""); + res->uuid = strdup(p->uuid); + res->version = strdup(package_version); + res->complete_time = strdup(get_time(time(NULL))); + res->fault = error; + FREE(du_ref); + FREE(package_name); + FREE(package_version); + FREE(package_env); + break; } } - return NULL; + bkp_session_delete_change_du_state(pchange_du_state); + bkp_session_save(); + bkp_session_insert_du_state_change_complete(pdu_state_change_complete); + bkp_session_save(); + //cwmp_root_cause_changedustate_complete(pdu_state_change_complete); + + list_del(&(pchange_du_state->list)); + cwmp_free_change_du_state_request(pchange_du_state); +end: + cdu_inform_event->extra_data = pdu_state_change_complete; + cdu_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + cdu_inform_event->event = Schedule_Inform_Evt; + trigger_cwmp_session_timer_with_event(&cdu_inform_event->session_timer_evt); + } -int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session __attribute__((unused)), struct rpc *rpc) +int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc) { if (rpc->extra_data != NULL) { struct du_state_change_complete *p; @@ -547,3 +542,12 @@ int cwmp_free_change_du_state_request(struct change_du_state *change_du_state) } return CWMP_OK; } + +void apply_change_du_state() +{ + struct list_head *ilist; + list_for_each (ilist, &(list_change_du_state)) { + struct change_du_state *pchange_du_state = list_entry(ilist, struct change_du_state, list);; + uloop_timeout_set(&pchange_du_state->handler_timer, 10); + } +} diff --git a/src/cwmp_du_state.h b/src/cwmp_du_state.h index e356037..a5a638a 100644 --- a/src/cwmp_du_state.h +++ b/src/cwmp_du_state.h @@ -14,14 +14,15 @@ #include "common.h" +#define CDU_TIMEOUT 86400 //24 hours extern struct list_head list_change_du_state; -extern pthread_mutex_t mutex_change_du_state; -extern pthread_cond_t threshold_change_du_state; int cwmp_du_install(char *url, char *uuid, char *user, char *pass, char *env_name, int env_id, char **fault_code); int cwmp_du_update(char *url, char *uuid, char *user, char *pass, char *env_name, int env_id, char **fault_code); int cwmp_du_uninstall(char *package_name, char *env_name, int env_id, char **fault_code); -int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session, struct rpc *rpc); +int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc); void *thread_cwmp_rpc_cpe_change_du_state(void *v); int cwmp_free_change_du_state_request(struct change_du_state *change_du_state); +void change_du_state_execute(struct uloop_timeout *utimeout); +void apply_change_du_state(); #endif diff --git a/src/cwmp_event.c b/src/cwmp_event.c new file mode 100644 index 0000000..b96f78a --- /dev/null +++ b/src/cwmp_event.c @@ -0,0 +1,50 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + */ + +#include "cwmp_event.h" +#include "common.h" +#include "session.h" + +pthread_mutex_t add_event_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct event_container *__cwmp_add_event_container(int event_code, char *command_key) +{ + struct event_container *event_container = NULL; + list_for_each_entry(event_container, &cwmp_main->session->events, list) { + if (event_container->code == event_code) { + return event_container; + } + if (event_container->code > event_code) { + break; + } + } + event_container = calloc(1, sizeof(struct event_container)); + if (event_container == NULL) { + return NULL; + } + INIT_LIST_HEAD(&(event_container->head_dm_parameter)); + list_add_tail(&(event_container->list), &(cwmp_main->session->events)); + event_container->code = event_code; + event_container->command_key = command_key ? strdup(command_key) : strdup(""); + if ((cwmp_main->event_id < 0) || (cwmp_main->event_id >= MAX_INT_ID)) { + cwmp_main->event_id = 0; + } + cwmp_main->event_id++; + event_container->id = cwmp_main->event_id; + return event_container; +} + +struct event_container *cwmp_add_event_container(int event_code, char *command_key) +{ + pthread_mutex_lock(&add_event_mutex); + struct event_container *event = __cwmp_add_event_container(event_code, command_key); + pthread_mutex_unlock(&add_event_mutex); + return event; +} diff --git a/src/cwmp_event.h b/src/cwmp_event.h new file mode 100644 index 0000000..b4cc8d8 --- /dev/null +++ b/src/cwmp_event.h @@ -0,0 +1,5 @@ +#ifndef CWMP_EVENT_H +#define CWMP_EVENT_H +#include "event.h" +struct event_container *cwmp_add_event_container(int event_code, char *command_key); +#endif diff --git a/src/cwmp_http.c b/src/cwmp_http.c new file mode 100644 index 0000000..94a5c67 --- /dev/null +++ b/src/cwmp_http.c @@ -0,0 +1,51 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + */ + +#include +#include "common.h" +#include "cwmp_http.h" +#include "http.h" +#include "log.h" + +struct uloop_fd http_event6; + +pthread_t http_cr_server_thread; + +void http_server_listen_uloop(struct uloop_fd *ufd __attribute__((unused)), unsigned events __attribute__((unused))) +{ + icwmp_http_server_listen(); +} + +void http_server_start_uloop(void) +{ + icwmp_http_server_init(); + http_event6.fd = cwmp_main->cr_socket_desc; + http_event6.cb = http_server_listen_uloop; + uloop_fd_add(&http_event6, ULOOP_READ | ULOOP_EDGE_TRIGGER); +} + +static void *thread_http_cr_server_listen(void *v __attribute__((unused))) +{ + icwmp_http_server_listen(); + return NULL; +} + +void http_server_start(void) +{ + int error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL); + if (error < 0) { + CWMP_LOG(ERROR, "Error when creating the http connection request server thread!"); + } +} + +void http_server_stop(void) +{ + pthread_join(http_cr_server_thread, NULL); +} diff --git a/src/cwmp_http.h b/src/cwmp_http.h new file mode 100644 index 0000000..3323a31 --- /dev/null +++ b/src/cwmp_http.h @@ -0,0 +1,8 @@ +#ifndef CWMP_HTTP_H +#define CWMP_HTTP_H +#include "http.h" +extern pthread_t http_cr_server_thread; + +void http_server_start(void); +void http_server_stop(void); +#endif diff --git a/src/cwmp_uci.h b/src/cwmp_uci.h index 3af1296..a304aa1 100644 --- a/src/cwmp_uci.h +++ b/src/cwmp_uci.h @@ -15,7 +15,6 @@ #include -#include "common.h" //struct uci_context *cwmp_uci_ctx = ((void *)0); #define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery" diff --git a/src/datamodel_interface.c b/src/datamodel_interface.c index bb11cba..7fd1cc4 100755 --- a/src/datamodel_interface.c +++ b/src/datamodel_interface.c @@ -325,14 +325,13 @@ void ubus_get_single_parameter_callback(struct ubus_request *req, int type __att char *cwmp_get_single_parameter_value(char *parameter_name, struct cwmp_dm_parameter *dm_parameter) { int e; - struct cwmp *cwmp = &cwmp_main; struct blob_buf b = { 0 }; memset(&b, 0, sizeof(struct blob_buf)); blob_buf_init(&b, 0); bb_add_string(&b, "path", !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name); bb_add_string(&b, "proto", "cwmp"); - blobmsg_add_u32(&b, "instance_mode", cwmp->conf.instance_mode); + blobmsg_add_u32(&b, "instance_mode", cwmp_main->conf.instance_mode); e = icwmp_ubus_invoke(USP_OBJECT_NAME, "get", b.head, ubus_get_single_parameter_callback, dm_parameter); blob_buf_free(&b); @@ -411,7 +410,6 @@ void ubus_get_parameter_callback(struct ubus_request *req, int type __attribute_ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *parameters_list) { int e; - struct cwmp *cwmp = &cwmp_main; struct list_params_result get_result = { .parameters_list = parameters_list }; struct blob_buf b = { 0 }; char *param = CWMP_STRLEN(parameter_name) ? parameter_name : DM_ROOT_OBJ; @@ -420,7 +418,7 @@ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *paramete blob_buf_init(&b, 0); bb_add_string(&b, "path", param); bb_add_string(&b, "proto", "cwmp"); - blobmsg_add_u32(&b, "instance_mode", cwmp->conf.instance_mode); + blobmsg_add_u32(&b, "instance_mode", cwmp_main->conf.instance_mode); e = icwmp_ubus_invoke(USP_OBJECT_NAME, "get", b.head, ubus_get_parameter_callback, &get_result); blob_buf_free(&b); @@ -440,7 +438,6 @@ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *paramete char *cwmp_get_multiple_parameters_values(struct list_head *arg_params_list, struct list_head *parameters_list) { int e; - struct cwmp *cwmp = &cwmp_main; struct cwmp_dm_parameter *param_value = NULL; struct list_params_result get_result = { .parameters_list = parameters_list }; struct blob_buf b = { 0 }; @@ -454,7 +451,7 @@ char *cwmp_get_multiple_parameters_values(struct list_head *arg_params_list, str blobmsg_add_string(&b, NULL, param_value->name); } blobmsg_close_array(&b, arr); - blobmsg_add_u32(&b, "instance_mode", cwmp->conf.instance_mode); + blobmsg_add_u32(&b, "instance_mode", cwmp_main->conf.instance_mode); e = icwmp_ubus_invoke(USP_OBJECT_NAME, "getm_values", b.head, ubus_get_parameter_callback, &get_result ); blob_buf_free(&b); @@ -475,7 +472,6 @@ char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_h { int e; struct list_params_result get_result = { .parameters_list = parameters_list }; - struct cwmp *cwmp = &cwmp_main; struct blob_buf b = { 0 }; memset(&b, 0, sizeof(struct blob_buf)); @@ -483,7 +479,7 @@ char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_h bb_add_string(&b, "path", object_name); blobmsg_add_u8(&b, "next-level", next_level); bb_add_string(&b, "proto", "cwmp"); - blobmsg_add_u32(&b, "instance_mode", cwmp->conf.instance_mode); + blobmsg_add_u32(&b, "instance_mode", cwmp_main->conf.instance_mode); e = icwmp_ubus_invoke(USP_OBJECT_NAME, "object_names", b.head, ubus_get_parameter_callback, &get_result); blob_buf_free(&b); @@ -539,7 +535,6 @@ int cwmp_set_multiple_parameters_values(struct list_head *parameters_values_list int e; struct cwmp_dm_parameter *param_value = NULL; struct setm_values_res set_result = { .flag = flag, .faults_list = faults_list }; - struct cwmp *cwmp = &cwmp_main; struct blob_buf b = { 0 }; memset(&b, 0, sizeof(struct blob_buf)); @@ -557,7 +552,7 @@ int cwmp_set_multiple_parameters_values(struct list_head *parameters_values_list bb_add_string(&b, "key", parameter_key); blobmsg_add_u32(&b, "transaction_id", transaction_id); bb_add_string(&b, "proto", "cwmp"); - blobmsg_add_u32(&b, "instance_mode", cwmp->conf.instance_mode); + blobmsg_add_u32(&b, "instance_mode", cwmp_main->conf.instance_mode); e = icwmp_ubus_invoke(USP_OBJECT_NAME, "setm_values", b.head, ubus_setm_values_callback, &set_result); blob_buf_free(&b); @@ -615,7 +610,7 @@ static void prepare_add_delete_blobmsg(struct blob_buf *b, char *object_name, ch bb_add_string(b, "key", key); blobmsg_add_u32(b, "transaction_id", transaction_id); bb_add_string(b, "proto", "cwmp"); - blobmsg_add_u32(b, "instance_mode", cwmp_main.conf.instance_mode); + blobmsg_add_u32(b, "instance_mode", cwmp_main->conf.instance_mode); } char *cwmp_add_object(char *object_name, char *key, char **instance) diff --git a/src/diagnostic.c b/src/diagnostic.c index 5f119d6..2aab12e 100644 --- a/src/diagnostic.c +++ b/src/diagnostic.c @@ -176,7 +176,7 @@ int cwmp_download_diagnostics() return -1; CWMP_LOG(INFO, "Download diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -186,7 +186,7 @@ int cwmp_upload_diagnostics() return -1; CWMP_LOG(INFO, "Upload diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -196,7 +196,7 @@ int cwmp_ip_ping_diagnostics() return -1; CWMP_LOG(INFO, "IPPing diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -206,7 +206,7 @@ int cwmp_nslookup_diagnostics() return -1; CWMP_LOG(INFO, "Nslookup diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -216,7 +216,7 @@ int cwmp_traceroute_diagnostics() return -1; CWMP_LOG(INFO, "Trace Route diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -226,7 +226,7 @@ int cwmp_udp_echo_diagnostics() return -1; CWMP_LOG(INFO, "UDPEcho diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } @@ -236,6 +236,6 @@ int cwmp_serverselection_diagnostics() return -1; CWMP_LOG(INFO, "Server Selection diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_main->diag_session = true; return 0; } diff --git a/src/digauth.h b/src/digauth.h index ac85103..0f2a4ca 100644 --- a/src/digauth.h +++ b/src/digauth.h @@ -15,11 +15,11 @@ extern char *nonce_key; -int get_nonce_key(void); void strip_lead_trail_char(char *str, char ch); +int get_nonce_key(void); int validate_http_digest_auth(const char *http_meth, const char *uri, const char *hdr, const char *rlm, const char *usr, const char *psw, - unsigned int timeout, const char *req_host); + unsigned int timeout, const char *req_host); int http_authentication_failure_resp(FILE *fp, const char *http_meth, const char *uri, const char *rlm, const char *opq); diff --git a/src/download.c b/src/download.c index 3954d42..3aede39 100644 --- a/src/download.c +++ b/src/download.c @@ -18,17 +18,12 @@ #include "backupSession.h" #include "log.h" #include "event.h" +#include "common.h" +#include "subprocess.h" +#include "session.h" LIST_HEAD(list_download); LIST_HEAD(list_schedule_download); -LIST_HEAD(list_apply_schedule_download); - -pthread_mutex_t mutex_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_download; -pthread_mutex_t mutex_schedule_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_schedule_download; -pthread_mutex_t mutex_apply_schedule_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_apply_schedule_download; int count_download_queue = 0; @@ -69,6 +64,57 @@ int download_file(const char *file_path, const char *url, const char *username, return res_code; } +char *download_file_task_function(char *task) +{ + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return NULL; + } + const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL}; + blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + char *task_name = blobmsg_get_string(tb[0]); + if (!task_name || strcmp(task_name, "download") != 0) + return NULL; + char *file_path = blobmsg_get_string(tb[1]); + char *url = blobmsg_get_string(tb[2]); + char *username = blobmsg_get_string(tb[3]); + char *password = blobmsg_get_string(tb[4]); + + int http_code = download_file(file_path, url, username, password); + char *http_ret = (char *)malloc(4 * sizeof(char)); + snprintf(http_ret, 4, "%d", http_code); + http_ret[3] = 0; + return http_ret; +} + +int download_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password) +{ + subprocess_start(download_file_task_function); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "task", "download"); + blobmsg_add_string(&bbuf, "file_path", file_path ? file_path : ""); + blobmsg_add_string(&bbuf, "url", url ? url : ""); + blobmsg_add_string(&bbuf, "username", username ? username : ""); + blobmsg_add_string(&bbuf, "password", password ? password : ""); + char *download_task = blobmsg_format_json(bbuf.head, true); + blob_buf_free(&bbuf); + + if (download_task != NULL) { + char *ret = execute_task_in_subprocess(download_task); + return atoi(ret); + } + return 500; +} /* * Check if the downloaded image can be applied */ @@ -150,6 +196,64 @@ int get_available_bank_id() return bank_id; } +/* + * Get Bank Status + */ +void ubus_get_bank_status_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + int *bank_id = (int *)req->priv; + int *status = bank_id; + bool bank_found = false; + struct blob_attr *banks = NULL; + struct blob_attr *cur; + int rem; + + blobmsg_for_each_attr(cur, msg, rem) + { + if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY) { + banks = cur; + break; + } + } + + const struct blobmsg_policy p[8] = { { "name", BLOBMSG_TYPE_STRING }, { "id", BLOBMSG_TYPE_INT32 }, { "active", BLOBMSG_TYPE_BOOL }, { "upgrade", BLOBMSG_TYPE_BOOL }, + { "fwver", BLOBMSG_TYPE_STRING }, { "swver", BLOBMSG_TYPE_STRING }, { "fwver", BLOBMSG_TYPE_STRING }, { "status", BLOBMSG_TYPE_STRING } }; + + blobmsg_for_each_attr(cur, banks, rem) + { + struct blob_attr *tb[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + blobmsg_parse(p, 8, tb, blobmsg_data(cur), blobmsg_len(cur)); + if (!tb[0]) + continue; + + if (blobmsg_get_u32(tb[1]) == (uint32_t)*bank_id) { + bank_found = true; + if (strcmp(blobmsg_get_string(tb[7]), "Available") == 0 || strcmp(blobmsg_get_string(tb[7]), "Active")) + *status = 1; + else + *status = 0; + } + } + if (bank_found == false) + *status = 0; +} + +int get_applied_firmware_status(int *bank_id_status) +{ + int e; + struct blob_buf b = { 0 }; + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + + e = icwmp_ubus_invoke("fwbank", "dump", b.head, ubus_get_available_bank_callback, &bank_id_status); + + if (e != 0) { + CWMP_LOG(INFO, "fwbank dump ubus method failed: Ubus err code: %d", e); + } + blob_buf_free(&b); + return e; +} + /* * Apply the new firmware */ @@ -171,6 +275,24 @@ int cwmp_apply_firmware() return e; } +void wait_firmware_to_be_applied(int bank_id) +{ + int count = 0; + + do { + int bank_id_status = bank_id; + + if (get_applied_firmware_status(&bank_id_status) != CWMP_OK) + break; + + if (bank_id_status == 1) + break; + + usleep(1000 * 1000); + count++; + } while(count < 15); +} + int cwmp_apply_multiple_firmware() { int e; @@ -192,9 +314,28 @@ int cwmp_apply_multiple_firmware() CWMP_LOG(INFO, "fwbank upgrade ubus method failed: Ubus err code: %d", e); return -1; } + //wait until the apply completes + wait_firmware_to_be_applied(bank_id); return CWMP_OK; } +char *apply_multiple_firmware_task_function(char *task __attribute__((unused))) +{ + int ret = cwmp_apply_multiple_firmware(); + + char *ret_str = (char *)malloc(2 * sizeof(char)); + snprintf(ret_str, 2, "%d", ret); + ret_str[1] = 0; + return ret_str; +} + +int cwmp_apply_multiple_firmware_in_subprocess() +{ + subprocess_start(apply_multiple_firmware_task_function); + char *ret = execute_task_in_subprocess("{}"); //empty json object + return atoi(ret); +} + int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; @@ -211,7 +352,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e goto end_download; } - int http_code = download_file(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password); + int http_code = download_file_in_subprocess(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password); if (http_code == 404) error = FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER; else if (http_code == 401) @@ -290,11 +431,11 @@ char *get_file_name_by_download_url(char *url) return slash+1; } -int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete) +int apply_downloaded_file(struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; if (pdownload->file_type[0] == '1') { - ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion; + ptransfer_complete->old_software_version = cwmp_main->deviceid.softwareversion; } bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_save(); @@ -341,6 +482,7 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d } else if (strcmp(pdownload->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE) == 0) { int err = cwmp_apply_multiple_firmware(); + //int err = cwmp_apply_multiple_firmware_in_subprocess(); if (err == CWMP_OK) error = FAULT_CPE_NO_FAULT; else @@ -353,7 +495,7 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); if (pdownload->file_type[0] == '3') { CWMP_LOG(INFO, "Download and apply new vendor config file is done successfully"); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); + //cwmp_root_cause_transfer_complete(ptransfer_complete); bkp_session_delete_transfer_complete(ptransfer_complete); } return FAULT_CPE_NO_FAULT; @@ -364,11 +506,11 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d } bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); + //cwmp_root_cause_transfer_complete(ptransfer_complete); return error; } -struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp, struct download *pdownload, enum load_type ltype) +struct transfer_complete *set_download_error_transfer_complete(struct download *pdownload, enum load_type ltype) { struct transfer_complete *ptransfer_complete; ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); @@ -379,422 +521,11 @@ struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp ptransfer_complete->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; ptransfer_complete->type = ltype; bkp_session_insert_transfer_complete(ptransfer_complete); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); + cwmp_root_cause_transfer_complete(ptransfer_complete); } return ptransfer_complete; } -void *thread_cwmp_rpc_cpe_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct download *pdownload; - struct timespec download_timeout = { 0, 0 }; - time_t current_time, stime; - int error; - struct transfer_complete *ptransfer_complete; - long int time_of_grace = 3600, timeout; - - sleep(3); - for (;;) { - - if (thread_end) - break; - - if (list_download.next != &(list_download)) { - pdownload = list_entry(list_download.next, struct download, list); - stime = pdownload->scheduled_time; - current_time = time(NULL); - if (pdownload->scheduled_time != 0) - timeout = current_time - pdownload->scheduled_time; - else - timeout = 0; - if ((timeout >= 0) && (timeout > time_of_grace)) { - pthread_mutex_lock(&mutex_download); - bkp_session_delete_download(pdownload); - error = FAULT_CPE_DOWNLOAD_FAILURE; - ptransfer_complete = set_download_error_transfer_complete(cwmp, pdownload, TYPE_DOWNLOAD); - list_del(&(pdownload->list)); - if (pdownload->scheduled_time != 0) - count_download_queue--; - cwmp_free_download_request(pdownload); - pthread_mutex_unlock(&mutex_download); - continue; - } - if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - char *download_file_name = get_file_name_by_download_url(pdownload->url); - CWMP_LOG(INFO, "Launch download file %s", pdownload->url); - error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); - sleep(3); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - error = apply_downloaded_file(cwmp, pdownload, download_file_name, ptransfer_complete); - if (error || pdownload->file_type[0] == '6') - bkp_session_delete_transfer_complete(ptransfer_complete); - } - if (pdownload->file_type[0] == '6') - sleep(30); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_download); - list_del(&(pdownload->list)); - if (pdownload->scheduled_time != 0) - count_download_queue--; - cwmp_free_download_request(pdownload); - pthread_mutex_unlock(&mutex_download); - continue; - } - pthread_mutex_lock(&mutex_download); - download_timeout.tv_sec = stime; - pthread_cond_timedwait(&threshold_download, &mutex_download, &download_timeout); - pthread_mutex_unlock(&mutex_download); - } else { - pthread_mutex_lock(&mutex_download); - pthread_cond_wait(&threshold_download, &mutex_download); - pthread_mutex_unlock(&mutex_download); - } - } - return NULL; -} - -int cwmp_add_apply_schedule_download(struct download *schedule_download, char *start_time) -{ - int i = 0; - int error = FAULT_CPE_NO_FAULT; - struct apply_schedule_download *apply_schedule_download; - - apply_schedule_download = calloc(1, sizeof(struct apply_schedule_download)); - if (apply_schedule_download == NULL) { - error = FAULT_CPE_INTERNAL_ERROR; - goto end; - } - if (error == FAULT_CPE_NO_FAULT) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_schedule_download->command_key = strdup(schedule_download->command_key); - apply_schedule_download->file_type = strdup(schedule_download->file_type); - apply_schedule_download->start_time = strdup(start_time); - for (i = 0; i < 2; i++) { - apply_schedule_download->timeintervals[i].windowstart = schedule_download->timewindowstruct[i].windowstart; - apply_schedule_download->timeintervals[i].windowend = schedule_download->timewindowstruct[i].windowend; - apply_schedule_download->timeintervals[i].maxretries = schedule_download->timewindowstruct[i].maxretries; - } - list_add_tail(&(apply_schedule_download->list), &(list_apply_schedule_download)); - - bkp_session_insert_apply_schedule_download(apply_schedule_download); - bkp_session_save(); - pthread_mutex_unlock(&mutex_apply_schedule_download); - pthread_cond_signal(&threshold_apply_schedule_download); - } -end: - cwmp_free_apply_schedule_download_request(apply_schedule_download); - return 0; -} - -void *thread_cwmp_rpc_cpe_schedule_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct timespec download_timeout = { 0, 0 }; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - int min_time = 0; - struct download *current_download = NULL; - struct download *p, *_p; - - for (;;) { - time_t current_time; - - if (thread_end) - break; - - current_time = time(NULL); - if (list_schedule_download.next != &(list_schedule_download)) { - list_for_each_entry_safe (p, _p, &(list_schedule_download), list) { - if (min_time == 0) { - if (p->timewindowstruct[0].windowend >= current_time) { - min_time = p->timewindowstruct[0].windowstart; - current_download = p; - } else if (p->timewindowstruct[1].windowend >= current_time) { - min_time = p->timewindowstruct[1].windowstart; - current_download = p; - } else { - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(p); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } else { - if (p->timewindowstruct[0].windowend >= current_time) { - if (p->timewindowstruct[0].windowstart < min_time) { - min_time = p->timewindowstruct[0].windowstart; - current_download = p; - } - - } else if (p->timewindowstruct[1].windowend >= current_time) { - if (p->timewindowstruct[1].windowstart < min_time) { - min_time = p->timewindowstruct[1].windowstart; - current_download = p; - } - } else { - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(p); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } - } - } else { - pthread_mutex_lock(&mutex_schedule_download); - pthread_cond_wait(&threshold_schedule_download, &mutex_schedule_download); - pthread_mutex_unlock(&mutex_schedule_download); - } - if (min_time == 0) { - continue; - } else if (min_time <= current_time) { - char *download_file_name = get_file_name_by_download_url(current_download->url); - if ((min_time == current_download->timewindowstruct[0].windowstart && (current_download->timewindowstruct[0].windowmode)[0] == '2') || (min_time == current_download->timewindowstruct[1].windowstart && (current_download->timewindowstruct[1].windowmode)[0] == '2')) { - pthread_mutex_lock(&mutex_schedule_download); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD; - error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - pthread_mutex_unlock(&mutex_schedule_download); - if (pthread_mutex_trylock(&(cwmp->mutex_session_send)) == 0) { - pthread_mutex_lock(&mutex_apply_schedule_download); - pthread_mutex_lock(&mutex_schedule_download); - error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete); - if (error == FAULT_CPE_NO_FAULT) - exit(EXIT_SUCCESS); - - pthread_mutex_unlock(&mutex_schedule_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - } else { - cwmp_add_apply_schedule_download(current_download, ptransfer_complete->start_time); - } - } - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(current_download); - bkp_session_save(); - list_del(&(current_download->list)); - cwmp_free_schedule_download_request(current_download); - pthread_mutex_unlock(&mutex_schedule_download); - min_time = 0; - current_download = NULL; - continue; - } //AT ANY TIME OR WHEN IDLE - else { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - CWMP_LOG(INFO, "Launch download file %s", current_download->url); - error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete); - if (error == FAULT_CPE_NO_FAULT) - exit(EXIT_SUCCESS); - } - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_schedule_download); - list_del(&(current_download->list)); - if (current_download->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(current_download); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } else { - if (min_time == current_download->timewindowstruct[0].windowstart) { - pthread_mutex_lock(&mutex_schedule_download); - download_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } else if (min_time == current_download->timewindowstruct[1].windowstart) { - pthread_mutex_lock(&mutex_schedule_download); - download_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } - } - } - return NULL; -} - -void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct timespec apply_timeout = { 0, 0 }; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - int min_time = 0; - struct apply_schedule_download *apply_download = NULL; - struct apply_schedule_download *p, *_p; - - for (;;) { - time_t current_time; - - if (thread_end) - break; - - current_time = time(NULL); - if (list_apply_schedule_download.next != &(list_apply_schedule_download)) { - list_for_each_entry_safe (p, _p, &(list_apply_schedule_download), list) { - if (min_time == 0) { - if (p->timeintervals[0].windowend >= current_time) { - min_time = p->timeintervals[0].windowstart; - apply_download = p; - } else if (p->timeintervals[1].windowend >= current_time) { - min_time = p->timeintervals[1].windowstart; - apply_download = p; - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - bkp_session_delete_apply_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timeintervals[0].windowstart != 0) - count_download_queue--; - cwmp_free_apply_schedule_download_request(p); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } - } else { - if (p->timeintervals[0].windowend >= current_time) { - if (p->timeintervals[0].windowstart < min_time) { - min_time = p->timeintervals[0].windowstart; - apply_download = p; - } - - } else if (p->timeintervals[1].windowend >= current_time) { - if (p->timeintervals[1].windowstart < min_time) { - min_time = p->timeintervals[1].windowstart; - apply_download = p; - } - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - bkp_session_delete_apply_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - /*if(p->timewindowintervals[0].windowstart != 0) - count_download_queue--;*/ - cwmp_free_apply_schedule_download_request(p); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } - } - } - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - pthread_cond_wait(&threshold_apply_schedule_download, &mutex_apply_schedule_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - } - if (min_time == 0) { - continue; - } else if (min_time <= current_time) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_apply_schedule_download(apply_download); - bkp_session_save(); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - if (apply_download->file_type[0] == '1') { - ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion; - } - ptransfer_complete->command_key = strdup(apply_download->command_key); - ptransfer_complete->start_time = strdup(apply_download->start_time); - ptransfer_complete->complete_time = strdup(get_time(time(NULL))); - ptransfer_complete->fault_code = error; - ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD; - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - - if (strcmp(apply_download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) == 0) { - cwmp_uci_set_value("cwmp", "cpe", "exec_download", "1"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - cwmp_apply_firmware(); - sleep(70); - error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; - } else if (strcmp(apply_download->file_type, WEB_CONTENT_FILE_TYPE) == 0) { - //TODO Not Supported - error = FAULT_CPE_NO_FAULT; - } else if (strcmp(apply_download->file_type, VENDOR_CONFIG_FILE_TYPE) == 0) { - cwmp_uci_init(); - int err = cwmp_uci_import(NULL, VENDOR_CONFIG_FILE, UCI_STANDARD_CONFIG); - cwmp_uci_exit(); - if (err == CWMP_OK) - error = FAULT_CPE_NO_FAULT; - else if (err == CWMP_GEN_ERR) - error = FAULT_CPE_INTERNAL_ERROR; - else if (err == -1) - error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; - } - - if ((error == FAULT_CPE_NO_FAULT) && (apply_download->file_type[0] == '1' || apply_download->file_type[0] == '3')) { - if (apply_download->file_type[0] == '3') { - CWMP_LOG(INFO, "Download and apply new vendor config file is done successfully"); - } - exit(EXIT_SUCCESS); - } - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_delete_transfer_complete(ptransfer_complete); - ptransfer_complete->fault_code = error; - } - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - - pthread_mutex_unlock(&mutex_schedule_download); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_apply_schedule_download); - list_del(&(apply_download->list)); - /*if(pdownload->timeintervals[0].windowstart != 0) - count_download_queue--;*/ - cwmp_free_apply_schedule_download_request(apply_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } else { - if (min_time == apply_download->timeintervals[0].windowstart) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_apply_schedule_download, &mutex_schedule_download, &apply_timeout); - pthread_mutex_unlock(&mutex_apply_schedule_download); - } else if (min_time == apply_download->timeintervals[1].windowstart) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &apply_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } - } - } - return NULL; -} - int cwmp_free_download_request(struct download *download) { if (download != NULL) { @@ -848,26 +579,8 @@ int cwmp_free_schedule_download_request(struct download *schedule_download) return CWMP_OK; } -int cwmp_free_apply_schedule_download_request(struct apply_schedule_download *apply_schedule_download) -{ - if (apply_schedule_download != NULL) { - if (apply_schedule_download->command_key != NULL) - free(apply_schedule_download->command_key); - - if (apply_schedule_download->file_type != NULL) - free(apply_schedule_download->file_type); - - if (apply_schedule_download->start_time != NULL) - free(apply_schedule_download->start_time); - - free(apply_schedule_download); - } - return CWMP_OK; -} - int cwmp_scheduledDownload_remove_all() { - pthread_mutex_lock(&mutex_download); while (list_download.next != &(list_download)) { struct download *download; download = list_entry(list_download.next, struct download, list); @@ -877,14 +590,12 @@ int cwmp_scheduledDownload_remove_all() count_download_queue--; cwmp_free_download_request(download); } - pthread_mutex_unlock(&mutex_download); return CWMP_OK; } int cwmp_scheduled_Download_remove_all() { - pthread_mutex_lock(&mutex_schedule_download); while (list_schedule_download.next != &(list_schedule_download)) { struct download *schedule_download; schedule_download = list_entry(list_schedule_download.next, struct download, list); @@ -894,29 +605,11 @@ int cwmp_scheduled_Download_remove_all() count_download_queue--; cwmp_free_schedule_download_request(schedule_download); } - pthread_mutex_unlock(&mutex_schedule_download); return CWMP_OK; } -int cwmp_apply_scheduled_Download_remove_all() -{ - pthread_mutex_lock(&mutex_apply_schedule_download); - while (list_apply_schedule_download.next != &(list_apply_schedule_download)) { - struct apply_schedule_download *apply_schedule_download; - apply_schedule_download = list_entry(list_apply_schedule_download.next, struct apply_schedule_download, list); - list_del(&(apply_schedule_download->list)); - bkp_session_delete_apply_schedule_download(apply_schedule_download); - /*if(apply_schedule_download->timetimeintervals[0].windowstart != 0) - count_download_queue--;*/ //TOCK - cwmp_free_apply_schedule_download_request(apply_schedule_download); - } - pthread_mutex_unlock(&mutex_apply_schedule_download); - - return CWMP_OK; -} - -int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attribute__((unused)), struct rpc *rpc) +int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc) { if (rpc->extra_data != NULL) { struct transfer_complete *p = (struct transfer_complete *)rpc->extra_data; @@ -930,3 +623,180 @@ int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attrib FREE(rpc->extra_data); return 0; } + +void cwmp_start_download(struct uloop_timeout *timeout) +{ + struct download *pdownload; + int error = FAULT_CPE_NO_FAULT; + struct transfer_complete *ptransfer_complete; + pdownload = container_of(timeout, struct download, handler_timer); + + char *download_file_name = get_file_name_by_download_url(pdownload->url); + CWMP_LOG(INFO, "Launch download file %s", pdownload->url); + error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while downloading the file: %s", pdownload->url); + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } else { + error = apply_downloaded_file(pdownload, download_file_name, ptransfer_complete); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } + } + if (error == FAULT_CPE_NO_FAULT && pdownload->file_type[0] == '3') { + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_download(pdownload); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + list_del(&(pdownload->list)); + if (pdownload->scheduled_time != 0) + count_download_queue--; + cwmp_free_download_request(pdownload); + + struct session_timer_event *download_inform_event = calloc(1, sizeof(struct session_timer_event)); + + download_inform_event->extra_data = ptransfer_complete; + download_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + download_inform_event->event = TransferClt_Evt; + trigger_cwmp_session_timer_with_event(&download_inform_event->session_timer_evt); +} + +void apply_downloads() +{ + struct list_head *ilist; + list_for_each (ilist, &(list_download)) { + struct download *download = list_entry(ilist, struct download, list); + int download_delay = 0; + if (download->scheduled_time > time(NULL)) { + download_delay = download->scheduled_time - time(NULL); + } + uloop_timeout_set(&download->handler_timer, 1000 * download_delay); + } +} + +void cwmp_start_schedule_download(struct uloop_timeout *timeout) +{ + struct download *sched_download; + struct transfer_complete *ptransfer_complete; + sched_download = container_of(timeout, struct download, handler_timer); + bool outdate = false; + int delay; + int window_index; + + time_t now = time(NULL); + if (sched_download->timewindowstruct[0].windowstart > now) { + delay = sched_download->timewindowstruct[0].windowstart - now; + uloop_timeout_set(&sched_download->handler_timer, 1000 * delay); + return; + } else if (sched_download->timewindowstruct[0].windowend >= now) { + outdate = false; + window_index = 0; + } else if (sched_download->timewindowstruct[1].windowstart > now) { + delay = sched_download->timewindowstruct[1].windowstart - now; + uloop_timeout_set(&sched_download->handler_timer, 1000 * delay); + return; + } else if (sched_download->timewindowstruct[1].windowend >= now) { + outdate = false; + window_index = 1; + } else { + outdate = true; + } + + if (!outdate) { + int error; + char *download_file_name = get_file_name_by_download_url(sched_download->url); + CWMP_LOG(INFO, "Launch download file %s", sched_download->url); + error = cwmp_launch_download(sched_download, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while downloading the file: %s", sched_download->url); + goto retry; + } else { + error = apply_downloaded_file(sched_download, download_file_name, ptransfer_complete); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); + goto retry; + } + } + if (error == FAULT_CPE_NO_FAULT && sched_download->file_type[0] == '3') { + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_download(sched_download); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + } else { + CWMP_LOG(ERROR, "Schedule Download out of date"); + ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); + if (ptransfer_complete == NULL) { + // error = FAULT_CPE_INTERNAL_ERROR; + return; + } + + ptransfer_complete->command_key = sched_download->command_key ? strdup(sched_download->command_key) : strdup(""); + ptransfer_complete->start_time = strdup(get_time(now)); + ptransfer_complete->complete_time = strdup(get_time(now)); + ptransfer_complete->type = TYPE_DOWNLOAD; + ptransfer_complete->fault_code = FAULT_CPE_INTERNAL_ERROR; + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } + + return; + +retry: + if (sched_download->timewindowstruct[window_index].maxretries > 0) { + uloop_timeout_set(&sched_download->handler_timer, 10); + sched_download->timewindowstruct[window_index].maxretries--; + return; + } else { + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + //cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + list_del(&(sched_download->list)); + if (sched_download->scheduled_time != 0) + count_download_queue--; + cwmp_free_schedule_download_request(sched_download); + + struct session_timer_event *sched_download_inform_event = calloc(1, sizeof(struct session_timer_event)); + + sched_download_inform_event->extra_data = ptransfer_complete; + sched_download_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + sched_download_inform_event->event = TransferClt_Evt; + trigger_cwmp_session_timer_with_event(&sched_download_inform_event->session_timer_evt); +} + +void apply_schedule_downloads() +{ + struct list_head *ilist; + list_for_each (ilist, &(list_schedule_download)) { + struct download *sched_download = list_entry(ilist, struct download, list); + time_t now = time(NULL); + int download_delay; + if (sched_download->timewindowstruct[0].windowstart > now) + download_delay = sched_download->timewindowstruct[0].windowstart - now; + else if (sched_download->timewindowstruct[0].windowend >= now) + download_delay = 1; + else if (now < sched_download->timewindowstruct[1].windowstart) + download_delay = sched_download->timewindowstruct[1].windowstart - now; + else if (sched_download->timewindowstruct[1].windowend >= now) + download_delay = 1; + else + download_delay = 1; + + uloop_timeout_set(&sched_download->handler_timer, 1000 * download_delay); + } +} diff --git a/src/download.h b/src/download.h index 34a09c1..56abcef 100644 --- a/src/download.h +++ b/src/download.h @@ -10,7 +10,6 @@ */ #ifndef CWMP_DOWNLOAD_H #define CWMP_DOWNLOAD_H - #include "common.h" #define DOWNLOAD_PROTOCOL_HTTP "http://" @@ -32,26 +31,17 @@ extern struct list_head list_download; extern struct list_head list_schedule_download; -extern struct list_head list_apply_schedule_download; - -extern pthread_mutex_t mutex_download; -extern pthread_cond_t threshold_download; -extern pthread_mutex_t mutex_schedule_download; -extern pthread_cond_t threshold_schedule_download; -extern pthread_mutex_t mutex_apply_schedule_download; -extern pthread_cond_t threshold_apply_schedule_download; extern int count_download_queue; int cwmp_free_download_request(struct download *download); int cwmp_free_schedule_download_request(struct download *schedule_download); -int cwmp_free_apply_schedule_download_request(struct apply_schedule_download *apply_schedule_download); int cwmp_scheduledDownload_remove_all(); int cwmp_scheduled_Download_remove_all(); -int cwmp_apply_scheduled_Download_remove_all(); -int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session, struct rpc *rpc); -void *thread_cwmp_rpc_cpe_download(void *v); -void *thread_cwmp_rpc_cpe_schedule_download(void *v); -void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v); +int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc); int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete); +void cwmp_start_download(struct uloop_timeout *timeout); +void apply_downloads(); +void apply_schedule_downloads(); +void cwmp_start_schedule_download(struct uloop_timeout *timeout); #endif diff --git a/src/event.c b/src/event.c index 7891746..7187f6e 100644 --- a/src/event.c +++ b/src/event.c @@ -17,30 +17,33 @@ #include "download.h" #include "upload.h" #include "log.h" +#include "session.h" +#include "cwmp_event.h" +//#include -const struct EVENT_CONST_STRUCT EVENT_CONST[] = {[EVENT_IDX_0BOOTSTRAP] = { "0 BOOTSTRAP", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_1BOOT] = { "1 BOOT", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL }, - [EVENT_IDX_2PERIODIC] = { "2 PERIODIC", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_3SCHEDULED] = { "3 SCHEDULED", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_4VALUE_CHANGE] = { "4 VALUE CHANGE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL }, - [EVENT_IDX_5KICKED] = { "5 KICKED", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_6CONNECTION_REQUEST] = { "6 CONNECTION REQUEST", EVENT_TYPE_SINGLE, 0 }, - [EVENT_IDX_7TRANSFER_COMPLETE] = { "7 TRANSFER COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_8DIAGNOSTICS_COMPLETE] = { "8 DIAGNOSTICS COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL }, - [EVENT_IDX_9REQUEST_DOWNLOAD] = { "9 REQUEST DOWNLOAD", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_10AUTONOMOUS_TRANSFER_COMPLETE] = { "10 AUTONOMOUS TRANSFER COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_11DU_STATE_CHANGE_COMPLETE] = { "11 DU STATE CHANGE COMPLETE", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_Reboot] = { "M Reboot", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_ScheduleInform] = { "M ScheduleInform", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_Download] = { "M Download", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_Schedule_Download] = { "M ScheduleDownload", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_Upload] = { "M Upload", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_M_ChangeDUState] = { "M ChangeDUState", EVENT_TYPE_MULTIPLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, - [EVENT_IDX_14HEARTBEAT] = { "14 HEARTBEAT", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT } }; +const struct EVENT_CONST_STRUCT EVENT_CONST[] = {[EVENT_IDX_0BOOTSTRAP] = { "0 BOOTSTRAP", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_1BOOT] = { "1 BOOT", EVENT_RETRY_AFTER_TRANSMIT_FAIL }, + [EVENT_IDX_2PERIODIC] = { "2 PERIODIC", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_3SCHEDULED] = { "3 SCHEDULED", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_4VALUE_CHANGE] = { "4 VALUE CHANGE", EVENT_RETRY_AFTER_TRANSMIT_FAIL }, + [EVENT_IDX_5KICKED] = { "5 KICKED", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_6CONNECTION_REQUEST] = { "6 CONNECTION REQUEST", 0 }, + [EVENT_IDX_7TRANSFER_COMPLETE] = { "7 TRANSFER COMPLETE", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_8DIAGNOSTICS_COMPLETE] = { "8 DIAGNOSTICS COMPLETE", EVENT_RETRY_AFTER_TRANSMIT_FAIL }, + [EVENT_IDX_9REQUEST_DOWNLOAD] = { "9 REQUEST DOWNLOAD", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_10AUTONOMOUS_TRANSFER_COMPLETE] = { "10 AUTONOMOUS TRANSFER COMPLETE", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_11DU_STATE_CHANGE_COMPLETE] = { "11 DU STATE CHANGE COMPLETE", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_Reboot] = { "M Reboot", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_ScheduleInform] = { "M ScheduleInform", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_Download] = { "M Download", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_Schedule_Download] = { "M ScheduleDownload", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_Upload] = { "M Upload", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_M_ChangeDUState] = { "M ChangeDUState", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, + [EVENT_IDX_14HEARTBEAT] = { "14 HEARTBEAT", EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT } }; void cwmp_save_event_container(struct event_container *event_container) //to be moved to backupsession { - if (EVENT_CONST[event_container->code].RETRY & EVENT_RETRY_AFTER_REBOOT) { + if (event_container && EVENT_CONST[event_container->code].RETRY & EVENT_RETRY_AFTER_REBOOT) { struct list_head *ilist; mxml_node_t *b; @@ -55,84 +58,27 @@ void cwmp_save_event_container(struct event_container *event_container) //to be } } -struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_code, char *command_key) +int cwmp_root_cause_event_boot() { - struct event_container *event_container; - struct list_head *ilist; - - if (cwmp->head_event_container == NULL) { - struct session *session; - session = cwmp_add_queue_session(cwmp); - if (session == NULL) { - return NULL; - } - cwmp->head_event_container = &(session->head_event_container); - } - //session = list_entry(cwmp->head_event_container, struct session, head_event_container); - list_for_each (ilist, cwmp->head_event_container) { - event_container = list_entry(ilist, struct event_container, list); - if (event_container->code == event_code && EVENT_CONST[event_code].TYPE == EVENT_TYPE_SINGLE) { - return event_container; - } - if (event_container->code > event_code) { - break; - } - } - event_container = calloc(1, sizeof(struct event_container)); - if (event_container == NULL) { - return NULL; - } - INIT_LIST_HEAD(&(event_container->head_dm_parameter)); - list_add(&(event_container->list), ilist->prev); - event_container->code = event_code; - event_container->command_key = command_key ? strdup(command_key) : strdup(""); - if ((cwmp->event_id < 0) || (cwmp->event_id >= MAX_INT_ID)) { - cwmp->event_id = 0; - } - cwmp->event_id++; - event_container->id = cwmp->event_id; - return event_container; -} - -void cwmp_root_cause_event_ipdiagnostic(void) -{ - struct cwmp *cwmp = &cwmp_main; - struct event_container *event_container; - - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_8DIAGNOSTICS_COMPLETE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return; - } - cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - return; -} - -int cwmp_root_cause_event_boot(struct cwmp *cwmp) -{ - if (cwmp->env.boot == CWMP_START_BOOT) { + if (cwmp_main->env.boot == CWMP_START_BOOT) { struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->env.boot = 0; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_1BOOT, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + cwmp_main->env.boot = 0; + event_container = cwmp_add_event_container(EVENT_IDX_1BOOT, ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } + cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } return CWMP_OK; } -int event_remove_all_event_container(struct session *session, int rem_from) +int event_remove_all_event_container(int rem_from) { - while (session->head_event_container.next != &(session->head_event_container)) { + while (cwmp_main->session->events.next != &cwmp_main->session->events) { struct event_container *event_container; - event_container = list_entry(session->head_event_container.next, struct event_container, list); + event_container = list_entry(cwmp_main->session->events.next, struct event_container, list); + if (event_container->code == EVENT_IDX_14HEARTBEAT) + continue; bkp_session_delete_event(event_container->id, rem_from ? "send" : "queue"); free(event_container->command_key); cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); @@ -143,16 +89,40 @@ int event_remove_all_event_container(struct session *session, int rem_from) return CWMP_OK; } -int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp) +int remove_single_event(int event_code) +{ + while (cwmp_main->session->events.next != &cwmp_main->session->events) { + struct event_container *event_container; + event_container = list_entry(cwmp_main->session->events.next, struct event_container, list); + if (event_container->code == event_code) { + bkp_session_delete_event(event_container->id, "send"); + free(event_container->command_key); + cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); + list_del(&(event_container->list)); + free(event_container); + bkp_session_save(); + break; + } + if (event_container) { + free(event_container->command_key); + cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); + list_del(&(event_container->list)); + free(event_container); + } + } + return CWMP_OK; +} + +int event_remove_noretry_event_container() { struct list_head *ilist, *q; - list_for_each_safe (ilist, q, &(session->head_event_container)) { + list_for_each_safe (ilist, q, &(cwmp_main->session->events)) { struct event_container *event_container; event_container = list_entry(ilist, struct event_container, list); if (EVENT_CONST[event_container->code].CODE[0] == '6') - cwmp->cwmp_cr_event = 1; + cwmp_main->cwmp_cr_event = 1; if (EVENT_CONST[event_container->code].RETRY == 0) { free(event_container->command_key); @@ -164,254 +134,162 @@ int event_remove_noretry_event_container(struct session *session, struct cwmp *c return CWMP_OK; } -int cwmp_root_cause_event_bootstrap(struct cwmp *cwmp) +int cwmp_root_cause_event_bootstrap() { struct event_container *event_container; char *acsurl = NULL; int cmp = 0; - cwmp_load_saved_session(cwmp, &acsurl, ACS); + cwmp_load_saved_session(&acsurl, ACS); if (acsurl == NULL) - save_acs_bkp_config(cwmp); + save_acs_bkp_config(); - if (acsurl == NULL || ((cmp = CWMP_STRCMP(cwmp->conf.acsurl, acsurl)) != 0)) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - if (cwmp->head_event_container != NULL && cwmp->head_session_queue.next != &(cwmp->head_session_queue)) { - struct session *session; - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - event_remove_all_event_container(session, RPC_QUEUE); - } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_0BOOTSTRAP, ""); + if (acsurl == NULL || ((cmp = strcmp(cwmp_main->conf.acsurl, acsurl)) != 0)) { + event_container = cwmp_add_event_container(EVENT_IDX_0BOOTSTRAP, ""); FREE(acsurl); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + if (event_container == NULL) return CWMP_MEM_ERR; - } + cwmp_save_event_container(event_container); cwmp_scheduleInform_remove_all(); cwmp_scheduledDownload_remove_all(); cwmp_scheduled_Download_remove_all(); - cwmp_apply_scheduled_Download_remove_all(); cwmp_scheduledUpload_remove_all(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - } else { + } else FREE(acsurl); - } if (cmp) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } char buf[64] = "Device.ManagementServer.URL"; add_dm_parameter_to_list(&(event_container->head_dm_parameter), buf, NULL, NULL, 0, false); cwmp_save_event_container(event_container); - save_acs_bkp_config(cwmp); + save_acs_bkp_config(); cwmp_scheduleInform_remove_all(); cwmp_scheduledDownload_remove_all(); - cwmp_apply_scheduled_Download_remove_all(); cwmp_scheduled_Download_remove_all(); cwmp_scheduledUpload_remove_all(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } return CWMP_OK; } -int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p) +int cwmp_root_cause_transfer_complete(struct transfer_complete *p) { struct event_container *event_container; - struct session *session; struct rpc *rpc_acs; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_7TRANSFER_COMPLETE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_7TRANSFER_COMPLETE, ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } + + if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_TRANSFER_COMPLETE)) == NULL) + return CWMP_MEM_ERR; + switch (p->type) { case TYPE_DOWNLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Download, p->command_key ? p->command_key : ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_M_Download, p->command_key ? p->command_key : ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } break; case TYPE_UPLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Upload, p->command_key ? p->command_key : ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_M_Upload, p->command_key ? p->command_key : ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } break; case TYPE_SCHEDULE_DOWNLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } break; } - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_TRANSFER_COMPLETE)) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } rpc_acs->extra_data = (void *)p; - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_OK; } -int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p) +int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p) { struct event_container *event_container; - struct session *session; struct rpc *rpc_acs; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : ""); + if (event_container == NULL) return CWMP_MEM_ERR; - } - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + + if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) return CWMP_MEM_ERR; - } + rpc_acs->extra_data = (void *)p; - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_OK; } -int cwmp_root_cause_get_rpc_method(struct cwmp *cwmp) +int cwmp_root_cause_schedule_inform(struct schedule_inform *schedule_inform) { - if (cwmp->env.periodic == CWMP_START_PERIODIC) { - struct event_container *event_container; - struct session *session; - - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->env.periodic = 0; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - cwmp_save_event_container(event_container); - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - } - - return CWMP_OK; -} - -void *thread_event_periodic(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; struct event_container *event_container; - int periodic_interval; - bool periodic_enable; - time_t periodic_time; - struct timespec periodic_timeout = { 0, 0 }; - time_t current_time; - long int delta_time; - time_t unknown_time; - - periodic_interval = cwmp->conf.period; - periodic_enable = cwmp->conf.periodic_enable; - periodic_time = cwmp->conf.time; - unknown_time = convert_datetime_to_timestamp("0001-01-01T00:00:00Z"); - - for (;;) { - pthread_mutex_lock(&(cwmp->mutex_periodic)); - if (cwmp->conf.periodic_enable) { - current_time = time(NULL); - if (periodic_time != 0) { - if (periodic_time == unknown_time) { - delta_time = (current_time + cwmp->conf.periodic_entropy) % periodic_interval; - } else { - delta_time = (current_time - periodic_time) % periodic_interval; - } - - if (delta_time >= 0) - periodic_timeout.tv_sec = current_time + periodic_interval - delta_time; - else - periodic_timeout.tv_sec = current_time - delta_time; - } else { - periodic_timeout.tv_sec = current_time + periodic_interval; - } - cwmp->session_status.next_periodic = periodic_timeout.tv_sec; - pthread_cond_timedwait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic), &periodic_timeout); - } else { - cwmp->session_status.next_periodic = 0; - pthread_cond_wait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic)); - } - pthread_mutex_unlock(&(cwmp->mutex_periodic)); - - if (thread_end) - break; - - if (periodic_interval != cwmp->conf.period || periodic_enable != cwmp->conf.periodic_enable || periodic_time != cwmp->conf.time) { - periodic_enable = cwmp->conf.periodic_enable; - periodic_interval = cwmp->conf.period; - periodic_time = cwmp->conf.time; - continue; - } - CWMP_LOG(INFO, "Periodic thread: add periodic event in the queue"); - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - continue; - } + event_container = cwmp_add_event_container(EVENT_IDX_3SCHEDULED, ""); + if (event_container != NULL) { cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); } - return NULL; + event_container = cwmp_add_event_container(EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey); + if (event_container != NULL) { + cwmp_save_event_container(event_container); + } + remove_schedule_inform(schedule_inform); + count_schedule_inform_queue--; + bkp_session_save(); + return CWMP_OK; } -bool event_exist_in_list(struct cwmp *cwmp, int event) +int cwmp_root_cause_get_rpc_method() +{ + if (cwmp_main->env.periodic == CWMP_START_PERIODIC) { + struct event_container *event_container; + + cwmp_main->env.periodic = 0; + event_container = cwmp_add_event_container(EVENT_IDX_2PERIODIC, ""); + if (event_container == NULL) + return CWMP_MEM_ERR; + + cwmp_save_event_container(event_container); + if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL) + return CWMP_MEM_ERR; + } + + return CWMP_OK; +} + +bool event_exist_in_list(int event) { struct event_container *event_container = NULL; - list_for_each_entry (event_container, cwmp->head_event_container, list) { + list_for_each_entry (event_container, &cwmp_main->session->events, list) { if (event_container->code == event) return true; } return false; } -int cwmp_root_cause_event_periodic(struct cwmp *cwmp) +int cwmp_root_cause_event_periodic() { char local_time[27] = { 0 }; struct tm *t_tm; - if (cwmp->cwmp_period == cwmp->conf.period && cwmp->cwmp_periodic_enable == cwmp->conf.periodic_enable && cwmp->cwmp_periodic_time == cwmp->conf.time) + if (cwmp_main->cwmp_period == cwmp_main->conf.period && cwmp_main->cwmp_periodic_enable == cwmp_main->conf.periodic_enable && cwmp_main->cwmp_periodic_time == cwmp_main->conf.time) return CWMP_OK; - pthread_mutex_lock(&(cwmp->mutex_periodic)); - cwmp->cwmp_period = cwmp->conf.period; - cwmp->cwmp_periodic_enable = cwmp->conf.periodic_enable; - cwmp->cwmp_periodic_time = cwmp->conf.time; - CWMP_LOG(INFO, cwmp->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp->cwmp_period); + cwmp_main->cwmp_period = cwmp_main->conf.period; + cwmp_main->cwmp_periodic_enable = cwmp_main->conf.periodic_enable; + cwmp_main->cwmp_periodic_time = cwmp_main->conf.time; + CWMP_LOG(INFO, cwmp_main->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp_main->cwmp_period); - t_tm = localtime(&cwmp->cwmp_periodic_time); + t_tm = localtime(&cwmp_main->cwmp_periodic_time); if (t_tm == NULL) return CWMP_GEN_ERR; @@ -423,22 +301,20 @@ int cwmp_root_cause_event_periodic(struct cwmp *cwmp) local_time[22] = ':'; local_time[26] = '\0'; - CWMP_LOG(INFO, cwmp->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time); - pthread_mutex_unlock(&(cwmp->mutex_periodic)); - pthread_cond_signal(&(cwmp->threshold_periodic)); + CWMP_LOG(INFO, cwmp_main->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time); return CWMP_OK; } -void connection_request_ip_value_change(struct cwmp *cwmp, int version) +void connection_request_ip_value_change(int version) { char *bip = NULL; char *ip_version = (version == IPv6) ? "ipv6" : "ip"; - char *ip_value = (version == IPv6) ? cwmp->conf.ipv6 : cwmp->conf.ip; + char *ip_value = (version == IPv6) ? cwmp_main->conf.ipv6 : cwmp_main->conf.ip; if (version == IPv6) - cwmp_load_saved_session(cwmp, &bip, CR_IPv6); + cwmp_load_saved_session(&bip, CR_IPv6); else - cwmp_load_saved_session(cwmp, &bip, CR_IP); + cwmp_load_saved_session(&bip, CR_IP); if (bip == NULL) { bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value); @@ -447,30 +323,26 @@ void connection_request_ip_value_change(struct cwmp *cwmp, int version) } if (strcmp(bip, ip_value) != 0) { struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { FREE(bip); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return; } cwmp_save_event_container(event_container); bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value); bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); } FREE(bip); } -void connection_request_port_value_change(struct cwmp *cwmp, int port) +void connection_request_port_value_change(int port) { char *bport = NULL; char bufport[16]; snprintf(bufport, sizeof(bufport), "%d", port); - cwmp_load_saved_session(cwmp, &bport, CR_PORT); + cwmp_load_saved_session(&bport, CR_PORT); if (bport == NULL) { bkp_session_simple_insert_in_parent("connection_request", "port", bufport); @@ -479,7 +351,7 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port) } if (strcmp(bport, bufport) != 0) { struct event_container *event_container; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { FREE(bport); return; @@ -491,20 +363,20 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port) FREE(bport); } -int cwmp_root_cause_events(struct cwmp *cwmp) +int cwmp_root_cause_events() { int error; - if ((error = cwmp_root_cause_event_bootstrap(cwmp))) + if ((error = cwmp_root_cause_event_bootstrap())) return error; - if ((error = cwmp_root_cause_event_boot(cwmp))) + if ((error = cwmp_root_cause_event_boot())) return error; - if ((error = cwmp_root_cause_get_rpc_method(cwmp))) + if ((error = cwmp_root_cause_get_rpc_method())) return error; - if ((error = cwmp_root_cause_event_periodic(cwmp))) + if ((error = cwmp_root_cause_event_periodic())) return error; return CWMP_OK; diff --git a/src/event.h b/src/event.h index 7c57085..490b641 100644 --- a/src/event.h +++ b/src/event.h @@ -13,7 +13,7 @@ #define EVENT_H_ #include "common.h" -#include "session.h" +#include "event.h" typedef struct event_container { struct list_head list; @@ -25,7 +25,6 @@ typedef struct event_container { typedef struct EVENT_CONST_STRUCT { char *CODE; - unsigned int TYPE; unsigned short RETRY; } EVENT_CONST_STRUCT; @@ -37,12 +36,6 @@ enum event_retry_after_enum EVENT_RETRY_AFTER_BOOTSTRAP = 0x4 }; -enum event_type_enum -{ - EVENT_TYPE_SINGLE = 0x0, - EVENT_TYPE_MULTIPLE = 0x1 -}; - enum event_idx_enum { EVENT_IDX_0BOOTSTRAP, @@ -64,22 +57,24 @@ enum event_idx_enum EVENT_IDX_M_Upload, EVENT_IDX_M_ChangeDUState, EVENT_IDX_14HEARTBEAT, + TransferClt_Evt, + Schedule_Inform_Evt, + CDU_Evt, __EVENT_IDX_MAX }; extern const struct EVENT_CONST_STRUCT EVENT_CONST[__EVENT_IDX_MAX]; -struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_idx, char *command_key); -int event_remove_all_event_container(struct session *session, int rem_from); -int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp); +int event_remove_all_event_container(int rem_from); +int remove_single_event(int event_code); +int event_remove_noretry_event_container(); void cwmp_save_event_container(struct event_container *event_container); -void *thread_event_periodic(void *v); -void connection_request_ip_value_change(struct cwmp *cwmp, int version); -void connection_request_port_value_change(struct cwmp *cwmp, int port); +void connection_request_ip_value_change( int version); +void connection_request_port_value_change(int port); int cwmp_get_int_event_code(const char *code); -bool event_exist_in_list(struct cwmp *cwmp, int event); -int cwmp_root_cause_events(struct cwmp *cwmp); -int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p); -int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p); -void cwmp_root_cause_event_ipdiagnostic(void); +bool event_exist_in_list(int event); +int cwmp_root_cause_events(); +int cwmp_root_cause_transfer_complete(struct transfer_complete *p); +int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p); +int cwmp_root_cause_schedule_inform(struct schedule_inform *schedule_inform); #endif /* SRC_INC_EVENT_H_ */ diff --git a/src/heartbeat.c b/src/heartbeat.c index 401c131..24b69b6 100644 --- a/src/heartbeat.c +++ b/src/heartbeat.c @@ -10,6 +10,7 @@ */ #include #include +#include #include "heartbeat.h" #include "common.h" @@ -20,156 +21,89 @@ #include "log.h" #include "event.h" #include "http.h" +#include "cwmp_event.h" -pthread_cond_t threshold_heartbeat_session; -pthread_cond_t threasheld_retry_session; -pthread_mutex_t mutex_heartbeat; -pthread_mutex_t mutex_heartbeat_session; bool old_heartbeat_enable = false; int heart_beat_retry_count_session = 0; -static struct session_status heart_beat_session_status = {0}; +struct uloop_timeout heartbeat_session_timer = { .cb = cwmp_heartbeat_session_timer }; -void check_trigger_heartbeat_session() +long int cwmp_heartbeat_session_time(void) { - if (cwmp_main.conf.heart_beat_enable && !old_heartbeat_enable) - pthread_cond_signal(&threshold_heartbeat_session); -} - -int add_heart_beat_event(struct session *heartbeat_session) -{ - struct event_container *event_container; - event_container = calloc(1, sizeof(struct event_container)); - if (event_container == NULL) { - return -1; + long int heartbeat_report; + time_t now = time(NULL); + struct tm *now_tm = gmtime((const time_t *)&now); + struct tm *heart_time = gmtime((const time_t *)&cwmp_main->conf.heart_time); + struct tm heart_init_tm = {.tm_year = now_tm->tm_year, .tm_mon = now_tm->tm_mon, .tm_mday = now_tm->tm_mday, .tm_hour = heart_time->tm_hour, .tm_min = heart_time->tm_min, .tm_sec = heart_time->tm_sec}; + time_t heart_init_time = mktime(&heart_init_tm); + if (heart_init_time - mktime(now_tm) < 0) { + add_day_to_time(&heart_init_tm); + heart_init_time = mktime(&heart_init_tm); } - INIT_LIST_HEAD(&(event_container->head_dm_parameter)); - list_add(&(event_container->list), heartbeat_session->head_event_container.prev); - event_container->code = EVENT_IDX_14HEARTBEAT; - event_container->command_key = strdup(""); - event_container->id = 1; - /* - * event_container will be freed in the destruction of the session heartbeat_session - */ - // cppcheck-suppress memleak - return 0; + + heartbeat_report = heart_init_time - mktime(now_tm); + + return heartbeat_report; } -void *thread_heartbeat_session(void *v __attribute__((unused))) +void cwmp_heartbeat_session_timer(struct uloop_timeout *timeout __attribute__((unused))) { - static struct timespec heartbeat_interval = { 0, 0 }; - - sleep(2); - for (;;) { - if (thread_end) - break; - - if (cwmp_main.conf.heart_beat_enable) { - heartbeat_interval.tv_sec = time(NULL) + cwmp_main.conf.heartbeat_interval; - pthread_mutex_lock(&mutex_heartbeat); - pthread_cond_timedwait(&threshold_heartbeat_session, &mutex_heartbeat, &heartbeat_interval); - if (thread_end) - break; - - if (cwmp_main.session_status.last_status == SESSION_FAILURE) { - CWMP_LOG(WARNING, "Not able to start HEARTBEAT Session for this period: CWMP Session is retrying"); - pthread_cond_wait(&threasheld_retry_session, &mutex_heartbeat); - //continue; - } - - if (thread_end) - break; - - pthread_mutex_lock(&mutex_heartbeat_session); - struct session *heartbeat_session = NULL; - heartbeat_session = calloc(1, sizeof(struct session)); - if (heartbeat_session == NULL) { - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - continue; - } - INIT_LIST_HEAD(&(heartbeat_session->head_event_container)); - INIT_LIST_HEAD(&(heartbeat_session->head_rpc_acs)); - INIT_LIST_HEAD(&(heartbeat_session->head_rpc_cpe)); - struct rpc *rpc_acs; - rpc_acs = cwmp_add_session_rpc_acs_head(heartbeat_session, RPC_ACS_INFORM); - if (rpc_acs == NULL) { - cwmp_session_destructor(heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - continue; - } - if (add_heart_beat_event(heartbeat_session) != 0) { - cwmp_session_destructor(heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - continue; - } - - if (heart_beat_session_status.last_status == SESSION_FAILURE) { - cwmp_config_load(&cwmp_main); - if (thread_end) { - cwmp_session_destructor(heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - continue; - } - } - - heart_beat_session_status.last_end_time = 0; - heart_beat_session_status.last_start_time = time(NULL); - heart_beat_session_status.last_status = SESSION_RUNNING; - heart_beat_session_status.next_retry = 0; - - if (file_exists(fc_cookies)) - remove(fc_cookies); - - cwmp_uci_init(); - CWMP_LOG(INFO, "Start HEARTBEAT session"); - int error = cwmp_schedule_rpc(&cwmp_main, heartbeat_session); - CWMP_LOG(INFO, "End HEARTBEAT session"); - cwmp_uci_exit(); - - if (thread_end) { - event_remove_all_event_container(heartbeat_session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(heartbeat_session); - pthread_mutex_unlock(&(cwmp_main.mutex_session_send)); - pthread_mutex_unlock(&mutex_heartbeat); - // Exiting to avoid race conditions - exit(0); - } - - if (error || heartbeat_session->error == CWMP_RETRY_SESSION) { - cwmp_config_load(&cwmp_main); - heart_beat_retry_count_session++; - run_session_end_func(); - CWMP_LOG(INFO, "Retry HEARTBEAT session, retry count = %d, retry in %ds", cwmp_main.retry_count_session, cwmp_get_retry_interval(&cwmp_main, 1)); - heart_beat_session_status.last_end_time = time(NULL); - heart_beat_session_status.last_status = SESSION_FAILURE; - heart_beat_session_status.next_retry = time(NULL) + cwmp_get_retry_interval(&cwmp_main, 1); - heartbeat_interval.tv_sec = time(NULL) + cwmp_get_retry_interval(&cwmp_main, 1); - heart_beat_session_status.failure_session++; - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - continue; - } - event_remove_all_event_container(heartbeat_session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(heartbeat_session); - heart_beat_retry_count_session = 0; - heart_beat_session_status.last_end_time = time(NULL); - heart_beat_session_status.last_status = SESSION_SUCCESS; - heart_beat_session_status.next_retry = 0; - heart_beat_session_status.success_session++; - heartbeat_interval.tv_sec = time(NULL) + cwmp_main.conf.heartbeat_interval; - pthread_mutex_unlock(&mutex_heartbeat_session); - pthread_mutex_unlock(&mutex_heartbeat); - } else { - pthread_mutex_lock(&mutex_heartbeat); - pthread_cond_wait(&threshold_heartbeat_session, &mutex_heartbeat); - pthread_mutex_unlock(&mutex_heartbeat); + if (cwmp_main->conf.heart_beat_enable) { + //HEARTBEAT event must wait a Non-HEARTBEAT Inform is being retried to be completed + if (cwmp_main->session->session_status.last_status == SESSION_FAILURE) { + cwmp_main->session->session_status.next_heartbeat = true; + cwmp_main->session->session_status.is_heartbeat = false; + return; } + + //struct session_timer_event *heartbeat_inform_event = calloc(1, sizeof(struct session_timer_event)); + + + uloop_timeout_set(&heartbeat_session_timer, cwmp_main->conf.heartbeat_interval * 1000); + + cwmp_main->session->session_status.next_heartbeat = false; + cwmp_main->session->session_status.is_heartbeat = true; + cwmp_add_event_container(EVENT_IDX_14HEARTBEAT, ""); + start_cwmp_session(); } - return NULL; +} + +void intiate_heartbeat_procedures() +{ + uloop_timeout_cancel(&heartbeat_session_timer); + if (cwmp_main->conf.heart_beat_enable) { + if (cwmp_main->conf.heart_time == 0) { + uloop_timeout_set(&heartbeat_session_timer, cwmp_main->conf.heartbeat_interval * 1000); + } else { + time_t hearttime_interval = cwmp_main->conf.heart_time - time(NULL); + if (hearttime_interval >= 0) { + uloop_timeout_set(&heartbeat_session_timer, hearttime_interval * 1000); + } else { + uloop_timeout_set(&heartbeat_session_timer, cwmp_heartbeat_session_time() * 1000); + } + } + + } +} + +void reinit_heartbeat_procedures() +{ + if (cwmp_main->conf.heart_beat_enable) { + if (!cwmp_main->prev_heartbeat_enable || (cwmp_main->prev_heartbeat_interval != cwmp_main->conf.heartbeat_interval) || (cwmp_main->prev_heartbeat_time != cwmp_main->conf.heart_time)) { + cwmp_main->heart_session = true; + if ((cwmp_main->prev_heartbeat_time != cwmp_main->conf.heart_time) && cwmp_main->conf.heart_time != 0) { + time_t hearttime_interval = cwmp_main->conf.heart_time - time(NULL); + if (hearttime_interval >= 0) + cwmp_main->heart_session_interval = hearttime_interval; + else + cwmp_main->heart_session_interval = cwmp_heartbeat_session_time(); + } else + cwmp_main->heart_session_interval = cwmp_main->conf.heartbeat_interval; + } + } else + uloop_timeout_cancel(&heartbeat_session_timer); + + cwmp_main->prev_heartbeat_enable = cwmp_main->conf.heart_beat_enable; + cwmp_main->prev_heartbeat_interval = cwmp_main->conf.heartbeat_interval; + cwmp_main->prev_heartbeat_time = cwmp_main->conf.heart_time; } diff --git a/src/heartbeat.h b/src/heartbeat.h index 9102dce..18a99c4 100644 --- a/src/heartbeat.h +++ b/src/heartbeat.h @@ -12,13 +12,11 @@ #define HEARTBEAT_H #include -extern pthread_mutex_t mutex_heartbeat; -extern pthread_mutex_t mutex_heartbeat_session; -extern pthread_cond_t threshold_heartbeat_session; -extern pthread_cond_t threasheld_retry_session; +extern struct uloop_timeout heartbeat_session_timer; extern int heart_beat_retry_count_session; extern bool old_heartbeat_enable; -void *thread_heartbeat_session(void *v); -void check_trigger_heartbeat_session(); +void cwmp_heartbeat_session_timer(struct uloop_timeout *timeout); +void intiate_heartbeat_procedures(); +void reinit_heartbeat_procedures(); #endif diff --git a/src/http.c b/src/http.c index 43556dd..525712b 100644 --- a/src/http.c +++ b/src/http.c @@ -39,14 +39,14 @@ void http_set_timeout(void) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1); } -int icwmp_http_client_init(struct cwmp *cwmp) +int icwmp_http_client_init() { char *dhcp_dis = NULL; char *acs_var_stat = NULL; uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis); - if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { + if (dhcp_dis && cwmp_main->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat); if (acs_var_stat) { if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) { @@ -55,13 +55,13 @@ int icwmp_http_client_init(struct cwmp *cwmp) return -1; } } else { - if (cwmp->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { + if (cwmp_main->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { FREE(dhcp_dis); return -1; } } } else { - if (cwmp->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { + if (cwmp_main->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { FREE(dhcp_dis); return -1; } @@ -79,7 +79,7 @@ int icwmp_http_client_init(struct cwmp *cwmp) if (!curl) return -1; - if (cwmp->conf.ipv6_enable) { + if (cwmp_main->conf.ipv6_enable) { unsigned char buf[sizeof(struct in6_addr)]; char *ip = NULL; @@ -131,21 +131,21 @@ static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **m return size * rxed; } -static void http_set_security_options(struct cwmp *cwmp) +static void http_set_security_options() { - curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp->conf.acs_userid); - curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp->conf.acs_passwd); + curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp_main->conf.acs_userid); + curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp_main->conf.acs_passwd); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST); - if (cwmp->conf.acs_ssl_capath) - curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath); - if (cwmp->conf.insecure_enable) { + if (cwmp_main->conf.acs_ssl_capath) + curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp_main->conf.acs_ssl_capath); + if (cwmp_main->conf.insecure_enable) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); } } -static void http_set_connection_options(struct cwmp *cwmp) +static void http_set_connection_options() { curl_easy_setopt(curl, CURLOPT_URL, http_c.url); @@ -161,12 +161,12 @@ static void http_set_connection_options(struct cwmp *cwmp) curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); - curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp->conf.interface); + curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp_main->conf.interface); } -static void http_set_header_list_options(struct cwmp *cwmp) +static void http_set_header_list_options() { - switch (cwmp->conf.compression) { + switch (cwmp_main->conf.compression) { case COMP_NONE: break; case COMP_GZIP: @@ -193,7 +193,7 @@ static void http_set_inout_options(char *msg_out, int msg_out_len, char **msg_in curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in); } -int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in) +int icwmp_http_send_message(char *msg_out, int msg_out_len, char **msg_in) { unsigned char buf[sizeof(struct in6_addr)]; int tmp = 0; @@ -212,15 +212,15 @@ int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, c if (!http_c.header_list) return -1; - if (cwmp->conf.http_disable_100continue) { + if (cwmp_main->conf.http_disable_100continue) { http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); if (!http_c.header_list) return -1; } - http_set_connection_options(cwmp); - http_set_security_options(cwmp); - http_set_header_list_options(cwmp); + http_set_connection_options(); + http_set_security_options(); + http_set_header_list_options(); http_set_inout_options(msg_out, msg_out_len, msg_in); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); @@ -272,7 +272,7 @@ int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, c } if (http_code == 415) { - cwmp->conf.compression = COMP_NONE; + cwmp_main->conf.compression = COMP_NONE; goto error; } if (http_code != 200 && http_code != 204) @@ -301,11 +301,12 @@ error: static void http_success_cr(void) { - CWMP_LOG(INFO, "Connection Request thread: add connection request event in the queue"); - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, ""); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); + CWMP_LOG(INFO, "Connection Request triggering ..."); + struct blob_buf b = { 0 }; + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + icwmp_ubus_invoke("tr069", "inform", b.head, NULL, NULL); + blob_buf_free(&b); } static void http_cr_new_client(int client, bool service_available) @@ -323,8 +324,8 @@ static void http_cr_new_client(int client, bool service_available) pthread_mutex_lock(&mutex_config_load); fp = fdopen(client, "r+"); - char *username = cwmp_main.conf.cpe_userid; - char *password = cwmp_main.conf.cpe_passwd; + char *username = cwmp_main->conf.cpe_userid; + char *password = cwmp_main->conf.cpe_passwd; memset(auth_digest_buffer, 0, BUFSIZ); if (!username || !password) { @@ -332,7 +333,8 @@ static void http_cr_new_client(int client, bool service_available) service_available = false; goto http_end; } - snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path); + snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main->conf.connection_request_path); + pthread_mutex_unlock(&mutex_config_load); while (fgets(buffer, sizeof(buffer), fp)) { if (buffer[0] == '\r' || buffer[0] == '\n') { /* end of http request (empty line) */ @@ -363,6 +365,7 @@ static void http_cr_new_client(int client, bool service_available) strip_lead_trail_char(buffer, '\n'); strip_lead_trail_char(buffer, '\r'); + if (!strncasecmp(buffer, "Authorization: Digest ", strlen("Authorization: Digest "))) { auth_digest_checked = true; CWMP_STRNCPY(auth_digest_buffer, buffer, BUFSIZ); @@ -377,7 +380,8 @@ static void http_cr_new_client(int client, bool service_available) } CWMP_LOG(INFO, "Received host: (%s)", request_host); - int auth_check = validate_http_digest_auth("GET", cwmp_main.conf.connection_request_path, auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, cwmp_main.conf.session_timeout, request_host); + int auth_check = validate_http_digest_auth("GET", cwmp_main->conf.connection_request_path, auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, cwmp_main->conf.session_timeout, request_host); + if (auth_check == -1) { /* invalid nonce */ internal_error = true; goto http_end; @@ -392,11 +396,17 @@ http_end: fputs("HTTP/1.1 503 Service Unavailable\r\n", fp); fputs("Connection: close\r\n", fp); fputs("Content-Length: 0\r\n", fp); + fputs("\r\n", fp); + fclose(fp); + close(client); } else if (auth_status) { CWMP_LOG(INFO, "Receive Connection Request: success authentication"); fputs("HTTP/1.1 200 OK\r\n", fp); fputs("Connection: close\r\n", fp); fputs("Content-Length: 0\r\n", fp); + fputs("\r\n", fp); + fclose(fp); + close(client); http_success_cr(); } else if (internal_error) { CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error"); @@ -408,13 +418,12 @@ http_end: CWMP_LOG(INFO, "Receive Connection Request: Return 401 Unauthorized"); fputs("HTTP/1.1 401 Unauthorized\r\n", fp); fputs("Connection: close\r\n", fp); - http_authentication_failure_resp(fp, "GET", cwmp_main.conf.connection_request_path, REALM, OPAQUE); + http_authentication_failure_resp(fp, "GET", cwmp_main->conf.connection_request_path, REALM, OPAQUE); fputs("\r\n", fp); + fputs("\r\n", fp); + fclose(fp); + close(client); } - fputs("\r\n", fp); - - fclose(fp); - pthread_mutex_unlock(&mutex_config_load); } void icwmp_http_server_init(void) @@ -423,20 +432,20 @@ void icwmp_http_server_init(void) unsigned short cr_port; for (;;) { - cr_port = (unsigned short)(cwmp_main.conf.connection_request_port); + cr_port = (unsigned short)(cwmp_main->conf.connection_request_port); unsigned short i = (DEFAULT_CONNECTION_REQUEST_PORT == cr_port) ? 1 : 0; //Create socket - cwmp_main.cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0); - if (cwmp_main.cr_socket_desc == -1) { + cwmp_main->cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0); + if (cwmp_main->cr_socket_desc == -1) { CWMP_LOG(ERROR, "Could not open server socket for Connection Requests, Error no is : %d, Error description is : %s", errno, strerror(errno)); sleep(1); continue; } - fcntl(cwmp_main.cr_socket_desc, F_SETFD, fcntl(cwmp_main.cr_socket_desc, F_GETFD) | FD_CLOEXEC); + fcntl(cwmp_main->cr_socket_desc, F_SETFD, fcntl(cwmp_main->cr_socket_desc, F_GETFD) | FD_CLOEXEC); int reusaddr = 1; - if (setsockopt(cwmp_main.cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) { + if (setsockopt(cwmp_main->cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) { CWMP_LOG(WARNING, "setsockopt(SO_REUSEADDR) failed"); } @@ -447,7 +456,7 @@ void icwmp_http_server_init(void) for (;; i++) { server.sin6_port = htons(cr_port); //Bind - if (bind(cwmp_main.cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { + if (bind(cwmp_main->cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { //print the error message CWMP_LOG(ERROR, "Could not bind server socket on the port %d, Error no is : %d, Error description is : %s", cr_port, errno, strerror(errno)); cr_port = DEFAULT_CONNECTION_REQUEST_PORT + i; @@ -461,9 +470,11 @@ void icwmp_http_server_init(void) char cr_port_str[6]; snprintf(cr_port_str, 6, "%hu", cr_port); cr_port_str[5] = '\0'; + cwmp_uci_init(); cwmp_uci_set_value("cwmp", "cpe", "port", cr_port_str); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - connection_request_port_value_change(&cwmp_main, cr_port); + connection_request_port_value_change(cr_port); + cwmp_uci_exit(); CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port); } @@ -475,15 +486,15 @@ void icwmp_http_server_listen(void) struct sockaddr_in6 client; //Listen - listen(cwmp_main.cr_socket_desc, 3); + listen(cwmp_main->cr_socket_desc, 3); //Accept and incoming connection c = sizeof(struct sockaddr_in); - while ((client_sock = accept(cwmp_main.cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { + while ((client_sock = accept(cwmp_main->cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { bool service_available; time_t current_time; - if (thread_end) + if (cwmp_stop) return; current_time = time(NULL); @@ -499,7 +510,6 @@ void icwmp_http_server_listen(void) } } http_cr_new_client(client_sock, service_available); - close(client_sock); } if (client_sock < 0) { diff --git a/src/http.h b/src/http.h index a6fb776..09fc7f9 100644 --- a/src/http.h +++ b/src/http.h @@ -26,11 +26,11 @@ struct http_client { void http_set_timeout(void); -int icwmp_http_client_init(struct cwmp *cwmp); +int icwmp_http_client_init(); void icwmp_http_client_exit(void); -int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in); +int icwmp_http_send_message(char *msg_out, int msg_out_len, char **msg_in); -void icwmp_http_server_init(void); +int http_cr_server_init(void); void icwmp_http_server_listen(void); - +void icwmp_http_server_init(void); #endif diff --git a/src/notifications.c b/src/notifications.c index 186fffc..5da6fb7 100644 --- a/src/notifications.c +++ b/src/notifications.c @@ -19,11 +19,13 @@ #include "log.h" #include "event.h" #include "xml.h" +#include "cwmp_event.h" LIST_HEAD(list_value_change); LIST_HEAD(list_lw_value_change); LIST_HEAD(list_param_obj_notify); -pthread_mutex_t mutex_value_change = PTHREAD_MUTEX_INITIALIZER; + +struct uloop_timeout check_notify_timer = { .cb = periodic_check_notifiy }; char *notifications[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"}; @@ -392,15 +394,15 @@ void cwmp_update_enabled_notify_file(void) /* * Load custom notify json file */ -void load_custom_notify_json(struct cwmp *cwmp) +void load_custom_notify_json() { struct blob_buf bbuf; struct blob_attr *cur; struct blob_attr *custom_notify_list = NULL; int rem; - cwmp->custom_notify_active = false; - if (cwmp->conf.custom_notify_json == NULL || !file_exists(cwmp->conf.custom_notify_json)) + cwmp_main->custom_notify_active = false; + if (cwmp_main->conf.custom_notify_json == NULL || !file_exists(cwmp_main->conf.custom_notify_json)) return; // Check for custom notification success import marker @@ -411,8 +413,8 @@ void load_custom_notify_json(struct cwmp *cwmp) blob_buf_init(&bbuf, 0); // Create success marker in temp area, so that it can be in sync with backup script - if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.custom_notify_json) == false) { - CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.custom_notify_json); + if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.custom_notify_json) == false) { + CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); creat(RUN_NOTIFY_MARKER, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return; @@ -422,7 +424,7 @@ void load_custom_notify_json(struct cwmp *cwmp) struct blob_attr *tb_notif[1] = { NULL}; blobmsg_parse(p_notif, 1, tb_notif, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); if (tb_notif[0] == NULL) { - CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp->conf.custom_notify_json); + CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); creat(RUN_NOTIFY_MARKER, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return; @@ -454,7 +456,7 @@ void load_custom_notify_json(struct cwmp *cwmp) } blob_buf_free(&bbuf); creat(RUN_NOTIFY_MARKER, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - cwmp->custom_notify_active = true; + cwmp_main->custom_notify_active = true; } /* @@ -545,92 +547,70 @@ int check_value_change(void) return int_ret; } -void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p) +void cwmp_prepare_value_change() +{ + struct event_container *event_container; + if (list_value_change.next == &(list_value_change)) + return; + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); + if (!event_container) + return; + list_splice_init(&(list_value_change), &(event_container->head_dm_parameter)); + cwmp_save_event_container(event_container); +} + +void sotfware_version_value_change(struct transfer_complete *p) { char *current_software_version = NULL; if (!p->old_software_version || p->old_software_version[0] == 0) return; - current_software_version = cwmp->deviceid.softwareversion; - if (p->old_software_version && current_software_version && strcmp(p->old_software_version, current_software_version) != 0) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - } + current_software_version = cwmp_main->deviceid.softwareversion; + if (p->old_software_version && current_software_version && strcmp(p->old_software_version, current_software_version) != 0) + cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); } -void *thread_periodic_check_notify(void *v) +void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)v; - int periodic_interval; - bool periodic_enable; - struct timespec periodic_timeout = { 0, 0 }; - time_t current_time; - int is_notify; + int is_notify = 0; + if (cwmp_stop) + return; + is_notify = check_value_change(); + if (is_notify > 0) + cwmp_update_enabled_notify_file(); + if (is_notify & NOTIF_ACTIVE) + send_active_value_change(); + if (is_notify & NOTIF_LW_ACTIVE) + cwmp_lwnotification(); - periodic_interval = cwmp->conf.periodic_notify_interval; - periodic_enable = cwmp->conf.periodic_notify_enable; + uloop_timeout_set(&check_notify_timer, cwmp_main->conf.periodic_notify_interval * 1000); +} - for (;;) { - if (periodic_enable) { - pthread_mutex_lock(&(cwmp->mutex_notify_periodic)); - current_time = time(NULL); - periodic_timeout.tv_sec = current_time + periodic_interval; - - if (thread_end) - break; - - pthread_cond_timedwait(&(cwmp->threshold_notify_periodic), &(cwmp->mutex_notify_periodic), &periodic_timeout); - - if (thread_end) - break; - - pthread_mutex_lock(&(cwmp->mutex_session_send)); - is_notify = check_value_change(); - if (is_notify > 0) - cwmp_update_enabled_notify_file(); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - if (is_notify & NOTIF_ACTIVE) - send_active_value_change(); - if (is_notify & NOTIF_LW_ACTIVE) - cwmp_lwnotification(); - pthread_mutex_unlock(&(cwmp->mutex_notify_periodic)); - } else - break; - } - return NULL; +void trigger_periodic_notify_check() +{ + uloop_timeout_set(&check_notify_timer, 10); } void add_list_value_change(char *param_name, char *param_data, char *param_type) { - pthread_mutex_lock(&(mutex_value_change)); add_dm_parameter_to_list(&list_value_change, param_name, param_data, param_type, 0, false); - pthread_mutex_unlock(&(mutex_value_change)); } void clean_list_value_change() { - pthread_mutex_lock(&(mutex_value_change)); cwmp_free_all_dm_parameter_list(&list_value_change); - pthread_mutex_unlock(&(mutex_value_change)); } void send_active_value_change(void) { - struct cwmp *cwmp = &cwmp_main; struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); + if (event_container == NULL) return; - } cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); return; } @@ -641,10 +621,9 @@ void add_lw_list_value_change(char *param_name, char *param_data, char *param_ty static void udplw_server_param(struct addrinfo **res) { struct addrinfo hints = { 0 }; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; + struct config *conf = &(cwmp_main->conf); char port[32]; - conf = &(cwmp->conf); + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; snprintf(port, sizeof(port), "%d", conf->lw_notification_port); @@ -703,9 +682,8 @@ void cwmp_lwnotification() char msg[1024], *msg_out; char signature[41]; struct addrinfo *servaddr; - struct cwmp *cwmp = &cwmp_main; struct config *conf; - conf = &(cwmp->conf); + conf = &(cwmp_main->conf); udplw_server_param(&servaddr); xml_prepare_lwnotification_message(&msg_out); diff --git a/src/notifications.h b/src/notifications.h index ccbaa38..fcb9bc0 100644 --- a/src/notifications.h +++ b/src/notifications.h @@ -30,8 +30,8 @@ enum NOTIFICATION_STATUS extern struct cwmp_dm_parameter forced_notifications_parameters[]; extern struct list_head list_lw_value_change; extern struct list_head list_value_change; -extern pthread_mutex_t mutex_value_change; extern struct list_head list_param_obj_notify; +extern struct uloop_timeout check_notify_timer; /*#define foreach_parameter_notification(function, parameter, notification) \ #ifndef NOTIF_VARIABLES_##function \ @@ -53,18 +53,21 @@ void cwmp_update_enabled_notify_file(void); int check_value_change(void); void create_list_param_obj_notify(); void create_list_param_leaf_notify(); -void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p); +void sotfware_version_value_change(struct transfer_complete *p); void *thread_periodic_check_notify(void *v); void send_active_value_change(void); void add_list_value_change(char *param_name, char *param_data, char *param_type); void clean_list_value_change(); char *cwmp_set_parameter_attributes(char *parameter_name, int notification); char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *parameters_list); -void load_custom_notify_json(struct cwmp *cwmp); +void load_custom_notify_json(); void add_lw_list_value_change(char *param_name, char *param_data, char *param_type); char *calculate_lwnotification_cnonce(); void cwmp_lwnotification(); void clean_list_param_notify(); void init_list_param_notify(); void reinit_list_param_notify(); +void cwmp_prepare_value_change(); +void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused))); +void trigger_periodic_notify_check(); #endif /* SRC_INC_NOTIFICATIONS_H_ */ diff --git a/src/reboot.c b/src/reboot.c index c0d600f..b397175 100644 --- a/src/reboot.c +++ b/src/reboot.c @@ -1,121 +1,64 @@ /* - * reboot.c - Reboot method fuctions + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. * - * Copyright (C) 2022, IOPSYS Software Solutions AB. - * - * Author Amin Ben Ramdhane - * - * See LICENSE file for license related information. + * Copyright (C) 2021 iopsys Software Solutions AB + * Author Omar Kallel * */ #include -#include "reboot.h" +#include "session.h" #include "cwmp_uci.h" #include "log.h" -#include "session.h" +#include "reboot.h" -static pthread_t delay_reboot_thread; -static pthread_t delay_schedule_thread; -static int g_curr_delay_reboot = -1; -static time_t g_curr_schedule_redoot = 0; +void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused))); +void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused))); -static void *thread_delay_reboot(void *arg) +struct uloop_timeout schedule_reboot_timer = { .cb = cwmp_schedule_reboot }; +struct uloop_timeout delay_reboot_timer = { .cb = cwmp_delay_reboot }; + +void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)arg; + cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z"); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); + if (time(NULL) > cwmp_main->conf.schedule_reboot) + return; + cwmp_reboot("schedule_reboot"); +} - CWMP_LOG(INFO, "The device will reboot after %d seconds", cwmp->conf.delay_reboot); - sleep(cwmp->conf.delay_reboot); +void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused))) +{ cwmp_uci_set_value("cwmp", "cpe", "delay_reboot", "-1"); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - /* check if the session is running before calling reboot method */ - /* if the session is in progress, wait until the end of the session */ - /* else calling reboot method */ - if (cwmp->session_status.last_status == SESSION_RUNNING) { + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { cwmp_set_end_session(END_SESSION_REBOOT); } else { cwmp_reboot("delay_reboot"); exit(EXIT_SUCCESS); } - - return NULL; } -static void create_delay_reboot_thread(struct cwmp *cwmp, bool thread_exist) +void launch_reboot_methods() { - if (thread_exist) { - CWMP_LOG(INFO, "There is already a delay reboot thread!, Cancel the current thread"); + static int curr_delay_reboot = -1; + static time_t curr_schedule_redoot = 0; - pthread_cancel(delay_reboot_thread); - create_delay_reboot_thread(cwmp, false); - } else { - CWMP_LOG(INFO, "Create a delay reboot thread"); + if (cwmp_main->conf.delay_reboot != curr_delay_reboot && cwmp_main->conf.delay_reboot > 0) { + CWMP_LOG(INFO, "The device will reboot after %ld seconds", cwmp_main->conf.delay_reboot); + curr_delay_reboot = cwmp_main->conf.delay_reboot; + uloop_timeout_cancel(&delay_reboot_timer); + uloop_timeout_set(&delay_reboot_timer, cwmp_main->conf.delay_reboot * 1000); + } - if (pthread_create(&delay_reboot_thread, NULL, &thread_delay_reboot, (void *)cwmp)) { - CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); - } - - if (pthread_detach(delay_reboot_thread)) { - CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); - } - } -} - -static void *thread_schedule_reboot(void *arg) -{ - struct cwmp *cwmp = (struct cwmp *)arg; - time_t remaining_time = cwmp->conf.schedule_reboot - time(NULL); - - CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time); - sleep(remaining_time); - cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - - /* check if the session is running before calling reboot method */ - /* if the session is in progress, wait until the end of the session */ - /* else calling reboot method */ - if (cwmp->session_status.last_status == SESSION_RUNNING) { - cwmp_set_end_session(END_SESSION_REBOOT); - } else { - cwmp_reboot("schedule_reboot"); - exit(EXIT_SUCCESS); - } - - return NULL; -} - -static void create_schedule_reboot_thread(struct cwmp *cwmp, bool thread_exist) -{ - if (thread_exist) { - CWMP_LOG(INFO, "There is already a schedule reboot thread!, Cancel the current thread"); - - pthread_cancel(delay_schedule_thread); - create_schedule_reboot_thread(cwmp, false); - } else { - CWMP_LOG(INFO, "Create a schedule reboot thread"); - - if (pthread_create(&delay_schedule_thread, NULL, &thread_schedule_reboot, (void *)cwmp)) { - CWMP_LOG(ERROR, "Error when creating the schedule reboot thread!"); - } - - if (pthread_detach(delay_schedule_thread)) { - CWMP_LOG(ERROR, "Error when detaching the schedule reboot thread!"); - } - } -} - -void launch_reboot_methods(struct cwmp *cwmp) -{ - - if (cwmp->conf.delay_reboot != g_curr_delay_reboot && cwmp->conf.delay_reboot > 0) { - - create_delay_reboot_thread(cwmp, (g_curr_delay_reboot != -1)); - g_curr_delay_reboot = cwmp->conf.delay_reboot; - } - - if (cwmp->conf.schedule_reboot != g_curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) { - - create_schedule_reboot_thread(cwmp, (g_curr_schedule_redoot != 0)); - g_curr_schedule_redoot = cwmp->conf.schedule_reboot; + if (cwmp_main->conf.schedule_reboot != curr_schedule_redoot && (cwmp_main->conf.schedule_reboot - time(NULL)) > 0) { + curr_schedule_redoot = cwmp_main->conf.schedule_reboot; + time_t remaining_time = cwmp_main->conf.schedule_reboot - time(NULL); + CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time); + uloop_timeout_cancel(&schedule_reboot_timer); + uloop_timeout_set(&schedule_reboot_timer, remaining_time * 1000); } } diff --git a/src/reboot.h b/src/reboot.h index 98b2992..169e44b 100644 --- a/src/reboot.h +++ b/src/reboot.h @@ -14,7 +14,7 @@ #include "common.h" -void launch_reboot_methods(struct cwmp *cwmp); +void launch_reboot_methods(); #endif //_REBOOT_H__ diff --git a/src/rpc.c b/src/rpc.c index b702882..00fc706 100755 --- a/src/rpc.c +++ b/src/rpc.c @@ -26,6 +26,7 @@ #include "sched_inform.h" #include "diagnostic.h" #include "cwmp_uci.h" +#include "cwmp_event.h" #define PROCESSING_DELAY (1) // In download/upload the message enqueued before sending the response, which cause the download/upload // to start just before the time. This delay is to compensate the time lapsed during the message enqueue and response @@ -67,33 +68,31 @@ char *forced_inform_parameters[] = { "Device.ManagementServer.AliasBasedAddressing" }; -int xml_handle_message(struct session *session) +int xml_handle_message() { struct rpc *rpc_cpe; char *c; int i; mxml_node_t *b; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); /* get method */ if (icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body") == -1) { CWMP_LOG(INFO, "Internal error"); - session->fault_code = FAULT_CPE_INTERNAL_ERROR; + cwmp_main->session->fault_code = FAULT_CPE_INTERNAL_ERROR; goto fault; } - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!b) { CWMP_LOG(INFO, "Invalid received message"); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } - session->body_in = b; + cwmp_main->session->body_in = b; while (1) { - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND_FIRST); if (!b) goto error; if (mxmlGetType(b) == MXML_ELEMENT) @@ -101,11 +100,13 @@ int xml_handle_message(struct session *session) } c = (char *)mxmlGetElement(b); + if (c == NULL) { CWMP_LOG(INFO, "Could not get element from received message"); goto error; } + /* convert QName to localPart, check that ns is the expected one */ if (strchr(c, ':')) { char *tmp = strchr(c, ':'); @@ -113,20 +114,20 @@ int xml_handle_message(struct session *session) if (strlen(ns.cwmp) != ns_len) { CWMP_LOG(INFO, "Namespace length is not matched in string (%s) and expected (%s)", c, ns.cwmp); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } if (strncmp(ns.cwmp, c, ns_len)) { CWMP_LOG(INFO, "Namespace in string (%s) is not the expected (%s) one", c, ns.cwmp); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } c = tmp + 1; } else { CWMP_LOG(INFO, "Can not convert QName to local part with received string (%s)", c); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } CWMP_LOG(INFO, "SOAP RPC message: %s", c); @@ -134,7 +135,7 @@ int xml_handle_message(struct session *session) for (i = 1; i < __RPC_CPE_MAX; i++) { if (i != RPC_CPE_FAULT && strcmp(c, rpc_cpe_methods[i].name) == 0 && rpc_cpe_methods[i].amd <= conf->supported_amd_version) { CWMP_LOG(INFO, "%s RPC is supported", c); - rpc_cpe = cwmp_add_session_rpc_cpe(session, i); + rpc_cpe = cwmp_add_session_rpc_cpe(i); if (rpc_cpe == NULL) goto error; break; @@ -142,12 +143,12 @@ int xml_handle_message(struct session *session) } if (!rpc_cpe) { CWMP_LOG(INFO, "%s RPC is not supported", c); - session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED; + cwmp_main->session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED; goto fault; } return 0; fault: - rpc_cpe = cwmp_add_session_rpc_cpe(session, RPC_CPE_FAULT); + rpc_cpe = cwmp_add_session_rpc_cpe(RPC_CPE_FAULT); if (rpc_cpe == NULL) goto error; return 0; @@ -227,9 +228,10 @@ bool check_inform_parameter_events_list_corresponding(char *events_str_list, str return false; } -static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct session *session) +static void load_inform_xml_schema(mxml_node_t **tree) { char declaration[1024] = {0}; + char c[256] = {0}; mxml_node_t *xml = NULL, *envelope = NULL; if (tree == NULL) @@ -246,8 +248,8 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct struct xml_data_struct env_xml_attrs = {0}; env_xml_attrs.xml_env = &envelope; - env_xml_attrs.amd_version = &cwmp->conf.supported_amd_version; - env_xml_attrs.session_timeout = &cwmp->conf.session_timeout; + env_xml_attrs.amd_version = &cwmp_main->conf.supported_amd_version; + env_xml_attrs.session_timeout = &cwmp_main->conf.session_timeout; int fault = build_xml_node_data(SOAP_ENV, xml, &env_xml_attrs); @@ -264,10 +266,10 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct struct xml_data_struct inform_xml_attrs = {0}; - char *manufacturer = cwmp->deviceid.manufacturer ? cwmp->deviceid.manufacturer : ""; - char *oui = cwmp->deviceid.oui ? cwmp->deviceid.oui : ""; - char *product_class = cwmp->deviceid.productclass ? cwmp->deviceid.productclass : ""; - char *serial_number = cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : ""; + char *manufacturer = cwmp_main->deviceid.manufacturer ? cwmp_main->deviceid.manufacturer : ""; + char *oui = cwmp_main->deviceid.oui ? cwmp_main->deviceid.oui : ""; + char *product_class = cwmp_main->deviceid.productclass ? cwmp_main->deviceid.productclass : ""; + char *serial_number = cwmp_main->deviceid.serialnumber ? cwmp_main->deviceid.serialnumber : ""; int max_env = 1; char *current_time = get_time(time(NULL)); @@ -277,10 +279,10 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct inform_xml_attrs.serial_number = &serial_number; inform_xml_attrs.max_envelopes = &max_env; inform_xml_attrs.current_time = ¤t_time; - inform_xml_attrs.retry_count = &cwmp->retry_count_session; + inform_xml_attrs.retry_count = &cwmp_main->retry_count_session; LIST_HEAD(xml_events_list); - event_container_list_to_xml_data_list(&(session->head_event_container), &xml_events_list); + event_container_list_to_xml_data_list(&(cwmp_main->session->events), &xml_events_list); inform_xml_attrs.data_list = &xml_events_list; fault = build_xml_node_data(SOAP_INFORM_CWMP, inform, &inform_xml_attrs); @@ -300,7 +302,7 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct struct cwmp_dm_parameter *dm_parameter; int size = 0; - list_for_each (ilist, &(session->head_event_container)) { + list_for_each (ilist, &(cwmp_main->session->events)) { struct event_container *event_container = list_entry(ilist, struct event_container, list); list_for_each (jlist, &(event_container->head_dm_parameter)) { dm_parameter = list_entry(jlist, struct cwmp_dm_parameter, list); @@ -332,6 +334,10 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct } } + //only forced inform parameters are included in heartbeat inform session + if (cwmp_main->session->session_status.is_heartbeat) + goto end; + struct uci_section *s = NULL; cwmp_uci_foreach_sections("cwmp", "inform_parameter", UCI_VARSTATE_CONFIG, s) { @@ -348,7 +354,7 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct char *events_str_list = NULL; cwmp_uci_get_value_by_section_string(s, "events_list", &events_str_list); - if (!check_inform_parameter_events_list_corresponding(events_str_list, &(session->head_event_container))) + if (!check_inform_parameter_events_list_corresponding(events_str_list, &(cwmp_main->session->events))) continue; LIST_HEAD(parameters_list); @@ -372,7 +378,7 @@ static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct cwmp_free_all_dm_parameter_list(¶meters_list); } - char c[256] = {0}; +end: if (snprintf(c, sizeof(c), "cwmp:ParameterValueStruct[%d]", size) == -1) { MXML_DELETE(xml); return; @@ -408,19 +414,19 @@ static int validate_inform_parameter_name(struct list_head *parameters_values_li return FAULT_CPE_NO_FAULT; } -int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused))) +int cwmp_rpc_acs_prepare_message_inform(struct rpc *this __attribute__((unused))) { mxml_node_t *tree; - if (session == NULL) + if (cwmp_main->session == NULL) return -1; - load_inform_xml_schema(&tree, cwmp, session); + load_inform_xml_schema(&tree); if (!tree) goto error; - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; @@ -429,14 +435,14 @@ error: return -1; } -int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused))) +int cwmp_rpc_acs_parse_response_inform(struct rpc *this __attribute__((unused))) { mxml_node_t *tree, *b; int i = -1; char *c; const char *cwmp_urn; - tree = session->tree_in; + tree = cwmp_main->session->tree_in; if (!tree) goto error; b = mxmlFindElement(tree, tree, "MaxEnvelopes", NULL, NULL, MXML_DESCEND); @@ -445,19 +451,19 @@ int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *sessio b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST); if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b)) goto error; - if (cwmp->conf.supported_amd_version == 1) { - cwmp->conf.amd_version = 1; + if (cwmp_main->conf.supported_amd_version == 1) { + cwmp_main->conf.amd_version = 1; return 0; } b = mxmlFindElement(tree, tree, "UseCWMPVersion", NULL, NULL, MXML_DESCEND); - if (b && cwmp->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion + if (b && cwmp_main->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST); if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b)) goto error; c = (char *) mxmlGetOpaque(b); if (c && *(c + 1) == '.') { c += 2; - cwmp->conf.amd_version = atoi(c) + 1; + cwmp_main->conf.amd_version = atoi(c) + 1; return 0; } goto error; @@ -470,28 +476,28 @@ int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *sessio } } if (i == 0) { - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; } else if (i >= 1 && i <= 3) { - switch (cwmp->conf.supported_amd_version) { + switch (cwmp_main->conf.supported_amd_version) { case 1: - cwmp->conf.amd_version = 1; //Already done + cwmp_main->conf.amd_version = 1; //Already done break; case 2: case 3: case 4: //MIN ACS CPE - if (cwmp->conf.supported_amd_version <= i + 1) - cwmp->conf.amd_version = cwmp->conf.supported_amd_version; + if (cwmp_main->conf.supported_amd_version <= i + 1) + cwmp_main->conf.amd_version = cwmp_main->conf.supported_amd_version; else - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; break; - //(cwmp->supported_conf.amd_version < i+1) ?"cwmp->conf.amd_version":"i+1"; + //(cwmp_main->supported_conf.amd_version < i+1) ?"cwmp_main->conf.amd_version":"i+1"; case 5: - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; break; } } else if (i >= 4) { - cwmp->conf.amd_version = cwmp->conf.supported_amd_version; + cwmp_main->conf.amd_version = cwmp_main->conf.supported_amd_version; } return 0; @@ -521,10 +527,10 @@ void set_not_known_acs_support() } } -int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp __attribute__((unused)), struct session *session, struct rpc *this __attribute__((unused))) +int cwmp_rpc_acs_parse_response_get_rpc_methods(struct rpc *this __attribute__((unused))) { mxml_node_t *tree, *b; - tree = session->tree_in; + tree = cwmp_main->session->tree_in; b = mxmlFindElement(tree, tree, "cwmp:GetRPCMethodsResponse", NULL, NULL, MXML_DESCEND); if (!b) goto error; @@ -537,7 +543,7 @@ int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp __attribute__( if (node_type == MXML_OPAQUE && mxmlGetType(parent_node) == MXML_ELEMENT && node_opaque && strcmp((char *) mxmlGetElement(parent_node), "string") == 0) set_rpc_acs_to_supported((char*)node_opaque); - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } set_not_known_acs_support(); return 0; @@ -548,7 +554,7 @@ error: /* * [RPC ACS]: GetRPCMethods */ -int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc __attribute__((unused))) +int cwmp_rpc_acs_prepare_get_rpc_methods(struct rpc *rpc __attribute__((unused))) { mxml_node_t *tree, *n; @@ -559,13 +565,13 @@ int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *sess n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) return -1; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = build_top_body_soap_request(tree, "GetRPCMethods"); if (!n) return -1; - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; } @@ -573,7 +579,7 @@ int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *sess /* * [RPC ACS]: TransferComplete */ -int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int cwmp_rpc_acs_prepare_transfer_complete(struct rpc *rpc) { mxml_node_t *tree, *n; struct transfer_complete *p; @@ -586,7 +592,7 @@ int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *se n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) goto error; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = build_top_body_soap_request(tree, "TransferComplete"); if (!n) @@ -607,7 +613,7 @@ int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *se goto error; FREE(faultstring); - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; @@ -618,7 +624,7 @@ error: /* * [RPC ACS]: DUStateChangeComplete */ -int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int cwmp_rpc_acs_prepare_du_state_change_complete(struct rpc *rpc) { mxml_node_t *tree, *n; struct du_state_change_complete *p; @@ -632,7 +638,7 @@ int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct sess if (!n) goto error; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = build_top_body_soap_request(tree, "DUStateChangeComplete"); if (!n) @@ -653,7 +659,7 @@ int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct sess } cwmp_free_all_xml_data_list(&opt_result_list); - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; error: @@ -663,17 +669,17 @@ error: /* * [RPC CPE]: GetParameterValues */ -int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_values(struct rpc *rpc) { mxml_node_t *b, *parameter_list = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR; int counter = 0; char c[256]; - if (session->tree_out == NULL) + if (cwmp_main->session->tree_out == NULL) goto fault; - b = build_top_body_soap_response(session->tree_out, "GetParameterValues"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "GetParameterValues"); struct xml_data_struct gpv_resp_xml_attrs = {0}; @@ -693,7 +699,7 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc gpv_xml_attrs.validations = gpv_validation; gpv_xml_attrs.nbre_validations = 1; - fault = load_xml_node_data(SOAP_REQ_GPV, session->body_in, &gpv_xml_attrs); + fault = load_xml_node_data(SOAP_REQ_GPV, cwmp_main->session->body_in, &gpv_xml_attrs); if (fault) { fault_code = fault; goto fault; @@ -725,7 +731,7 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc l = l->next; } cwmp_free_all_xml_data_list(&gpv_xml_data_list); - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -737,7 +743,7 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) return -1; return 0; } @@ -745,7 +751,7 @@ fault: /* * [RPC CPE]: GetParameterNames */ -int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_names(struct rpc *rpc) { mxml_node_t *n, *b, *parameter_list; char *parameter_name = NULL; @@ -762,7 +768,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc gpn_xml_attrs.validations = gpn_validation; gpn_xml_attrs.nbre_validations = 2; - int fault = load_xml_node_data(SOAP_REQ_GPN, session->body_in, &gpn_xml_attrs); + int fault = load_xml_node_data(SOAP_REQ_GPN, cwmp_main->session->body_in, &gpn_xml_attrs); if (fault != CWMP_OK) { fault_code = fault; goto fault; @@ -774,10 +780,10 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc } FREE(parameter_name); - if (session->tree_out == NULL) + if (cwmp_main->session->tree_out == NULL) goto fault; - n = build_top_body_soap_response(session->tree_out, "GetParameterNames"); + n = build_top_body_soap_response(cwmp_main->session->tree_out, "GetParameterNames"); if (!n){ fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -806,7 +812,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc cwmp_free_all_dm_parameter_list(¶meters_list); cwmp_free_all_xml_data_list(&prameters_xml_list); - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -818,7 +824,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc fault: cwmp_free_all_dm_parameter_list(¶meters_list); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) return -1; return 0; } @@ -826,14 +832,14 @@ fault: /* * [RPC CPE]: GetParameterAttributes */ -int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_attributes(struct rpc *rpc) { mxml_node_t *n, *parameter_list, *b; int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR; char c[256]; - b = session->body_in; + b = cwmp_main->session->body_in; - n = build_top_body_soap_response(session->tree_out, "GetParameterAttributes"); + n = build_top_body_soap_response(cwmp_main->session->tree_out, "GetParameterAttributes"); if (!n) goto fault; @@ -885,7 +891,7 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct } cwmp_free_all_xml_data_list(&gpa_xml_data_list); - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -896,7 +902,7 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) return -1; return 0; } @@ -904,10 +910,10 @@ fault: /* * [RPC CPE]: SetParameterValues */ -int is_duplicated_parameter(mxml_node_t *param_node, struct session *session) +int is_duplicated_parameter(mxml_node_t *param_node) { mxml_node_t *b = param_node; - while ((b = mxmlWalkNext(b, session->body_in, MXML_DESCEND))) { + while ((b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND))) { const char *node_opaque = mxmlGetOpaque(b); mxml_node_t *parent = mxmlGetParent(b); mxml_type_t node_type = mxmlGetType(b); @@ -920,7 +926,7 @@ int is_duplicated_parameter(mxml_node_t *param_node, struct session *session) return 0; } -int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc) { mxml_node_t *b = NULL; char *parameter_key = NULL; @@ -938,7 +944,7 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc spv_xml_attrs.validations = spv_validation; spv_xml_attrs.nbre_validations = 2; - int fault = load_xml_node_data(SOAP_REQ_SPV, session->body_in, &spv_xml_attrs); + int fault = load_xml_node_data(SOAP_REQ_SPV, cwmp_main->session->body_in, &spv_xml_attrs); if (fault) { fault_code = fault; goto fault; @@ -973,7 +979,7 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc cwmp_free_all_xml_data_list(&xml_list_set_param_value); cwmp_free_all_dm_parameter_list(&list_set_param_value); - b = build_top_body_soap_response(session->tree_out, "SetParameterValues"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "SetParameterValues"); if (!b) { fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -997,7 +1003,7 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc fault: cwmp_free_all_dm_parameter_list(&list_set_param_value); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; cwmp_free_all_list_param_fault(rpc->list_set_value_fault); @@ -1011,7 +1017,7 @@ fault: /* * [RPC CPE]: SetParameterAttributes */ -int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_set_parameter_attributes(struct rpc *rpc) { mxml_node_t *n; int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0; @@ -1020,7 +1026,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "SetParameterAttributes") == -1) goto fault; - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -1050,7 +1056,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct } cwmp_free_all_xml_data_list(&prameters_xml_list); - mxml_node_t *resp = build_top_body_soap_response(session->tree_out, "SetParameterAttributes"); + mxml_node_t *resp = build_top_body_soap_response(cwmp_main->session->tree_out, "SetParameterAttributes"); if (!resp) goto fault; @@ -1058,7 +1064,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; return ret; @@ -1067,7 +1073,7 @@ fault: /* * [RPC CPE]: AddObject */ -int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_add_object(struct rpc *rpc) { mxml_node_t *b; char *object_name = NULL; @@ -1082,7 +1088,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) add_obj_xml_attrs.validations = gpn_validation; add_obj_xml_attrs.nbre_validations = 2; - int fault = load_xml_node_data(SOAP_REQ_ADDOBJ, session->body_in, &add_obj_xml_attrs); + int fault = load_xml_node_data(SOAP_REQ_ADDOBJ, cwmp_main->session->body_in, &add_obj_xml_attrs); if (fault) { fault_code = fault; @@ -1110,7 +1116,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) fault_code = FAULT_CPE_INTERNAL_ERROR; goto fault; } - b = build_top_body_soap_response(session->tree_out, "AddObject"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "AddObject"); if (!b) { fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -1145,7 +1151,7 @@ fault: FREE(object_name); FREE(parameter_key); FREE(instance); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; if (transaction_id) { cwmp_transaction_abort(); @@ -1157,7 +1163,7 @@ fault: /* * [RPC CPE]: DeleteObject */ -int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_delete_object(struct rpc *rpc) { mxml_node_t *b; char *object_name = NULL; @@ -1171,7 +1177,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) del_obj_xml_attrs.validations = gpn_validation; del_obj_xml_attrs.nbre_validations = 2; - int fault = load_xml_node_data(SOAP_REQ_DELOBJ, session->body_in, &del_obj_xml_attrs); + int fault = load_xml_node_data(SOAP_REQ_DELOBJ, cwmp_main->session->body_in, &del_obj_xml_attrs); if (fault) { fault_code = fault; @@ -1193,7 +1199,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) goto fault; } - b = build_top_body_soap_response(session->tree_out, "DeleteObject"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "DeleteObject"); if (!b) { fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -1220,7 +1226,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) fault: FREE(object_name); FREE(parameter_key); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; if (transaction_id) { cwmp_transaction_abort(); @@ -1232,14 +1238,14 @@ fault: /* * [RPC CPE]: GetRPCMethods */ -int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_rpc_methods(struct rpc *rpc) { mxml_node_t *n, *method_list; int i, counter = 0; - mxml_node_t *b = session->body_in; + mxml_node_t *b = cwmp_main->session->body_in; char c[128]; - n = build_top_body_soap_response(session->tree_out, "GetRPCMethods"); + n = build_top_body_soap_response(cwmp_main->session->tree_out, "GetRPCMethods"); if (!n) goto fault; @@ -1268,7 +1274,7 @@ int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc goto fault; cwmp_free_all_xml_data_list(&rpcs_list); - b = mxmlFindElement(session->tree_out, session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1281,7 +1287,7 @@ int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1292,11 +1298,11 @@ error: /* * [RPC CPE]: FactoryReset */ -int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_factory_reset(struct rpc *rpc) { mxml_node_t *b; - b = build_top_body_soap_response(session->tree_out, "FactoryReset"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "FactoryReset"); if (!b) goto fault; @@ -1306,7 +1312,7 @@ int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc) return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1317,11 +1323,11 @@ error: /* * [RPC CPE]: X_FactoryResetSoft */ -int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct rpc *rpc) { mxml_node_t *b; - b = build_top_body_soap_response(session->tree_out, "X_FactoryResetSoft"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "X_FactoryResetSoft"); if (!b) goto fault; @@ -1331,7 +1337,7 @@ int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1342,12 +1348,12 @@ error: /* * [RPC CPE]: CancelTransfer */ -int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_cancel_transfer(struct rpc *rpc) { mxml_node_t *b; char *command_key = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR; - b = session->body_in; + b = cwmp_main->session->body_in; struct xml_data_struct canceltrancer_obj_xml_attrs = {0}; canceltrancer_obj_xml_attrs.command_key = &command_key; @@ -1355,7 +1361,7 @@ int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc canceltrancer_obj_xml_attrs.validations = canceltransfer_validation; canceltrancer_obj_xml_attrs.nbre_validations = 1; - fault_code = load_xml_node_data(SOAP_REQ_CANCELTRANSFER, session->body_in, &canceltrancer_obj_xml_attrs); + fault_code = load_xml_node_data(SOAP_REQ_CANCELTRANSFER, cwmp_main->session->body_in, &canceltrancer_obj_xml_attrs); if (command_key) cancel_transfer(command_key); @@ -1363,7 +1369,7 @@ int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc if (fault_code) goto fault; - b = build_top_body_soap_response(session->tree_out, "CancelTransfer"); + b = build_top_body_soap_response(cwmp_main->session->tree_out, "CancelTransfer"); if (!b) { fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -1374,7 +1380,7 @@ int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc fault: FREE(command_key); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -1390,14 +1396,12 @@ int cancel_transfer(char *key) list_for_each_safe (ilist, q, &(list_download)) { struct download *pdownload = list_entry(ilist, struct download, list); if (strcmp(pdownload->command_key, key) == 0) { - pthread_mutex_lock(&mutex_download); bkp_session_delete_download(pdownload); bkp_session_save(); list_del(&(pdownload->list)); if (pdownload->scheduled_time != 0) count_download_queue--; cwmp_free_download_request(pdownload); - pthread_mutex_unlock(&mutex_download); } } } @@ -1405,14 +1409,12 @@ int cancel_transfer(char *key) list_for_each_safe (ilist, q, &(list_upload)) { struct upload *pupload = list_entry(ilist, struct upload, list); if (strcmp(pupload->command_key, key) == 0) { - pthread_mutex_lock(&mutex_upload); bkp_session_delete_upload(pupload); bkp_session_save(); list_del(&(pupload->list)); if (pupload->scheduled_time != 0) count_download_queue--; cwmp_free_upload_request(pupload); - pthread_mutex_unlock(&mutex_upload); } } } @@ -1423,13 +1425,13 @@ int cancel_transfer(char *key) /* * [RPC CPE]: Reboot */ -int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_reboot(struct rpc *rpc) { mxml_node_t *b; struct event_container *event_container; char *command_key = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR; - b = session->body_in; + b = cwmp_main->session->body_in; struct xml_data_struct reboot_obj_xml_attrs = {0}; reboot_obj_xml_attrs.command_key = &command_key; @@ -1437,23 +1439,20 @@ int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc) reboot_obj_xml_attrs.validations = reboot_validation; reboot_obj_xml_attrs.nbre_validations = 1; - fault_code = load_xml_node_data(SOAP_REQ_REBOOT, session->body_in, &reboot_obj_xml_attrs); + fault_code = load_xml_node_data(SOAP_REQ_REBOOT, cwmp_main->session->body_in, &reboot_obj_xml_attrs); if (fault_code) goto fault; commandKey = icwmp_strdup(command_key); - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_M_Reboot, command_key); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_M_Reboot, command_key); + if (event_container == NULL) goto fault; - } - cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - b = build_top_body_soap_response(session->tree_out, "Reboot"); + cwmp_save_event_container(event_container); + + b = build_top_body_soap_response(cwmp_main->session->tree_out, "Reboot"); if (!b) goto fault; @@ -1465,7 +1464,7 @@ int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc) fault: FREE(command_key); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -1476,7 +1475,7 @@ error: /* * [RPC CPE]: ScheduleInform */ -int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_schedule_inform(struct rpc *rpc) { mxml_node_t *n; char *command_key = NULL; @@ -1487,7 +1486,6 @@ int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc int delay_seconds = 0; - pthread_mutex_lock(&mutex_schedule_inform); struct xml_data_struct schedinform_obj_xml_attrs = {0}; schedinform_obj_xml_attrs.command_key = &command_key; @@ -1496,14 +1494,13 @@ int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc schedinform_obj_xml_attrs.validations = schedinform_validation; schedinform_obj_xml_attrs.nbre_validations = 2; - fault = load_xml_node_data(SOAP_REQ_SCHEDINF, session->body_in, &schedinform_obj_xml_attrs); + fault = load_xml_node_data(SOAP_REQ_SCHEDINF, cwmp_main->session->body_in, &schedinform_obj_xml_attrs); if (fault) goto fault; if (count_schedule_inform_queue >= MAX_SCHEDULE_INFORM_QUEUE) { fault = FAULT_CPE_RESOURCES_EXCEEDED; - pthread_mutex_unlock(&mutex_schedule_inform); goto fault; } count_schedule_inform_queue++; @@ -1516,31 +1513,29 @@ int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc } } - n = build_top_body_soap_response(session->tree_out, "ScheduleInform"); + n = build_top_body_soap_response(cwmp_main->session->tree_out, "ScheduleInform"); if (!n) goto fault; CWMP_LOG(INFO, "Schedule inform event will start in %us", delay_seconds); schedule_inform = calloc(1, sizeof(struct schedule_inform)); - if (schedule_inform == NULL) { - pthread_mutex_unlock(&mutex_schedule_inform); + if (schedule_inform == NULL) goto fault; - } + schedule_inform->handler_timer.cb = cwmp_start_schedule_inform; schedule_inform->commandKey = CWMP_STRDUP(command_key); schedule_inform->scheduled_time = scheduled_time; list_add(&(schedule_inform->list), ilist->prev); bkp_session_insert_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey); bkp_session_save(); - pthread_mutex_unlock(&mutex_schedule_inform); - pthread_cond_signal(&threshold_schedule_inform); FREE(command_key); + cwmp_set_end_session(END_SESSION_SCHEDULE_INFORM); return 0; fault: FREE(command_key); - if (cwmp_create_fault_message(session, rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR)) return -1; return 0; @@ -1549,7 +1544,7 @@ fault: /* * [RPC CPE]: ChangeDuState */ -int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_change_du_state(struct rpc *rpc) { mxml_node_t *n, *t; struct change_du_state *change_du_state = NULL; @@ -1561,8 +1556,7 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); - + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -1590,24 +1584,21 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc xml_data_list_to_cdu_operations_list(&xml_list_operations, &change_du_state->list_operation); - t = build_top_body_soap_response(session->tree_out, "ChangeDUState"); + t = build_top_body_soap_response(cwmp_main->session->tree_out, "ChangeDUState"); if (!t) goto fault; - if (error == FAULT_CPE_NO_FAULT) { - pthread_mutex_lock(&mutex_change_du_state); - list_add_tail(&(change_du_state->list), &(list_change_du_state)); - bkp_session_insert_change_du_state(change_du_state); - bkp_session_save(); - pthread_mutex_unlock(&mutex_change_du_state); - pthread_cond_signal(&threshold_change_du_state); - } + change_du_state->handler_timer.cb = change_du_state_execute; + list_add_tail(&(change_du_state->list), &(list_change_du_state)); + bkp_session_insert_change_du_state(change_du_state); + bkp_session_save(); + cwmp_set_end_session(END_SESSION_CDU); return 0; fault: cwmp_free_change_du_state_request(change_du_state); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) goto error; return 0; @@ -1618,7 +1609,7 @@ error: /* * [RPC CPE]: Download */ -int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_download(struct rpc *rpc) { mxml_node_t *n; char c[256]; @@ -1633,7 +1624,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -1678,7 +1669,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) if (error != FAULT_CPE_NO_FAULT) goto fault; - mxml_node_t *t = build_top_body_soap_response(session->tree_out, "Download"); + mxml_node_t *t = build_top_body_soap_response(cwmp_main->session->tree_out, "Download"); char *start_time = "0001-01-01T00:00:00+00:00"; char *complete_time = "0001-01-01T00:00:00+00:00"; int status = 1; @@ -1694,7 +1685,6 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) } if (error == FAULT_CPE_NO_FAULT) { - pthread_mutex_lock(&mutex_download); if (download_delay != 0) scheduled_time = time(NULL) + download_delay + PROCESSING_DELAY; @@ -1709,6 +1699,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) count_download_queue++; download->scheduled_time = scheduled_time; } + download->handler_timer.cb = cwmp_start_download; bkp_session_insert_download(download); bkp_session_save(); if (download_delay != 0) { @@ -1716,16 +1707,14 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) } else { CWMP_LOG(INFO, "Download will start at the end of session"); } - - pthread_mutex_unlock(&mutex_download); - pthread_cond_signal(&threshold_download); + cwmp_set_end_session(END_SESSION_DOWNLOAD); } return 0; fault: cwmp_free_download_request(download); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) return -1; return 0; } @@ -1733,7 +1722,7 @@ fault: /* * [RPC CPE]: ScheduleDownload */ -int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc) { mxml_node_t *n, *t; char c[256]; @@ -1747,7 +1736,7 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -1820,12 +1809,11 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r if (error != FAULT_CPE_NO_FAULT) goto fault; - t = build_top_body_soap_response(session->tree_out, "ScheduleDownload"); + t = build_top_body_soap_response(cwmp_main->session->tree_out, "ScheduleDownload"); if (!t) goto fault; - pthread_mutex_lock(&mutex_schedule_download); list_add_tail(&(schedule_download->list), &(list_schedule_download)); if (schedule_download_delay[0] != 0) { count_download_queue++; @@ -1835,6 +1823,7 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2]; schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1]; } + schedule_download->handler_timer.cb = cwmp_start_schedule_download; bkp_session_insert_schedule_download(schedule_download); bkp_session_save(); if (schedule_download_delay[0] != 0) { @@ -1842,14 +1831,17 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r } else { CWMP_LOG(INFO, "Schedule Download will start at the end of session"); } - pthread_mutex_unlock(&mutex_schedule_download); - pthread_cond_signal(&threshold_schedule_download); - + time_t now = time(NULL); + if ((schedule_download->timewindowstruct[0].windowstart < now) ||(schedule_download->timewindowstruct[0].windowend < now && (now < schedule_download->timewindowstruct[1].windowstart || schedule_download->timewindowstruct[1].windowend < now) )) { + error = FAULT_CPE_INTERNAL_ERROR; + goto fault; + } + cwmp_set_end_session(END_SESSION_SCHEDULE_DOWNLOAD); return 0; fault: cwmp_free_schedule_download_request(schedule_download); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) goto error; return 0; @@ -1860,7 +1852,7 @@ error: /* * [RPC CPE]: Upload */ -int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_upload(struct rpc *rpc) { mxml_node_t *n; int error = FAULT_CPE_NO_FAULT; @@ -1875,7 +1867,7 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -1920,7 +1912,7 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) goto fault; } - mxml_node_t *t = build_top_body_soap_response(session->tree_out, "Upload"); + mxml_node_t *t = build_top_body_soap_response(cwmp_main->session->tree_out, "Upload"); char *start_time = "0001-01-01T00:00:00+00:00"; char *complete_time = "0001-01-01T00:00:00+00:00"; int status = 1; @@ -1936,7 +1928,6 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) } if (error == FAULT_CPE_NO_FAULT) { - pthread_mutex_lock(&mutex_upload); if (upload_delay != 0) scheduled_time = time(NULL) + upload_delay + PROCESSING_DELAY; @@ -1953,19 +1944,19 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) } bkp_session_insert_upload(upload); bkp_session_save(); + upload->handler_timer.cb = cwmp_start_upload; if (upload_delay != 0) { CWMP_LOG(INFO, "Upload will start in %us", upload_delay); } else { CWMP_LOG(INFO, "Upload will start at the end of session"); } - pthread_mutex_unlock(&mutex_upload); - pthread_cond_signal(&threshold_upload); + cwmp_set_end_session(END_SESSION_UPLOAD); } return 0; fault: cwmp_free_upload_request(upload); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) return -1; return 0; } @@ -1974,16 +1965,16 @@ fault: * [FAULT]: Fault */ -int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_fault(struct rpc *rpc) { mxml_node_t *body; - body = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + body = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); struct xml_data_struct fault_xml_attrs = {0}; - char *faultcode = (FAULT_CPE_ARRAY[session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server"; + char *faultcode = (FAULT_CPE_ARRAY[cwmp_main->session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server"; char *faultstring = "CWMP fault"; - int fault_code = atoi(session->fault_code ? FAULT_CPE_ARRAY[session->fault_code].CODE : "0"); - char *fault_string = strdup(FAULT_CPE_ARRAY[session->fault_code].DESCRIPTION); + int fault_code = atoi(cwmp_main->session->fault_code ? FAULT_CPE_ARRAY[cwmp_main->session->fault_code].CODE : "0"); + char *fault_string = strdup(FAULT_CPE_ARRAY[cwmp_main->session->fault_code].DESCRIPTION); fault_xml_attrs.fault_code = &fault_code; fault_xml_attrs.fault_string = &fault_string; fault_xml_attrs.faultcode = &faultcode; @@ -1999,7 +1990,7 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) cwmp_param_fault_list_to_xml_data_list(rpc->list_set_value_fault, &spv_fault_xml_data_list); struct xml_data_struct spv_fault_xml_attrs = {0}; spv_fault_xml_attrs.data_list = &spv_fault_xml_data_list; - body = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + body = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:Fault", NULL, NULL, MXML_DESCEND); fault = build_xml_node_data(SOAP_SPV_FAULT, body, &spv_fault_xml_attrs); if (fault) return -1; @@ -2009,18 +2000,18 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) return 0; } -int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code) +int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code) { CWMP_LOG(INFO, "Fault detected"); - session->fault_code = fault_code; + cwmp_main->session->fault_code = fault_code; - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_out); - if (xml_prepare_msg_out(session)) + if (xml_prepare_msg_out(cwmp_main->session)) return -1; CWMP_LOG(INFO, "Preparing the Fault message"); - if (rpc_cpe_methods[RPC_CPE_FAULT].handler(session, rpc_cpe)) + if (rpc_cpe_methods[RPC_CPE_FAULT].handler(rpc_cpe)) return -1; rpc_cpe->type = RPC_CPE_FAULT; diff --git a/src/rpc.h b/src/rpc.h index 8add0b4..def1e36 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -20,34 +20,34 @@ extern const struct rpc_cpe_method rpc_cpe_methods[__RPC_CPE_MAX]; extern struct rpc_acs_method rpc_acs_methods[__RPC_ACS_MAX]; -int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_rpc_methods(struct rpc *rpc); +int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_values(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_names(struct rpc *rpc); +int cwmp_handle_rpc_cpe_set_parameter_attributes(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_attributes(struct rpc *rpc); +int cwmp_handle_rpc_cpe_add_object(struct rpc *rpc); +int cwmp_handle_rpc_cpe_delete_object(struct rpc *rpc); +int cwmp_handle_rpc_cpe_reboot(struct rpc *rpc); +int cwmp_handle_rpc_cpe_download(struct rpc *rpc); +int cwmp_handle_rpc_cpe_upload(struct rpc *rpc); +int cwmp_handle_rpc_cpe_factory_reset(struct rpc *rpc); +int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct rpc *rpc); int cancel_transfer(char *key); -int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc); +int cwmp_handle_rpc_cpe_cancel_transfer(struct rpc *rpc); +int cwmp_handle_rpc_cpe_schedule_inform(struct rpc *rpc); +int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc); +int cwmp_handle_rpc_cpe_change_du_state(struct rpc *rpc); +int cwmp_handle_rpc_cpe_fault(struct rpc *rpc); -int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *this); -int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc); +int cwmp_rpc_acs_prepare_message_inform(struct rpc *rpc); +int cwmp_rpc_acs_parse_response_inform(struct rpc *rpc); +int cwmp_rpc_acs_parse_response_get_rpc_methods(struct rpc *this); +int cwmp_rpc_acs_prepare_get_rpc_methods(struct rpc *rpc); +int cwmp_rpc_acs_prepare_transfer_complete(struct rpc *rpc); +int cwmp_rpc_acs_prepare_du_state_change_complete(struct rpc *rpc); -int xml_handle_message(struct session *session); -int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code); +int xml_handle_message(); +int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code); #endif diff --git a/src/sched_inform.c b/src/sched_inform.c index 16ea76a..6712c6a 100644 --- a/src/sched_inform.c +++ b/src/sched_inform.c @@ -13,101 +13,59 @@ #include "backupSession.h" #include "event.h" #include "log.h" +#include "cwmp_event.h" +#include "session.h" LIST_HEAD(list_schedule_inform); -pthread_mutex_t mutex_schedule_inform = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_schedule_inform; int count_schedule_inform_queue = 0; -void *thread_cwmp_rpc_cpe_scheduleInform(void *v) +int remove_schedule_inform(struct schedule_inform *schedule_inform) { - struct cwmp *cwmp = (struct cwmp *)v; - struct event_container *event_container; - struct schedule_inform *schedule_inform; - struct timespec si_timeout = { 0, 0 }; - time_t current_time, stime; - bool add_event_same_time = false; - - for (;;) { - - if (thread_end) - break; - - if (list_schedule_inform.next != &(list_schedule_inform)) { - schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list); - stime = schedule_inform->scheduled_time; - current_time = time(NULL); - if (current_time >= schedule_inform->scheduled_time) { - if (add_event_same_time) { - pthread_mutex_lock(&mutex_schedule_inform); - list_del(&(schedule_inform->list)); - if (schedule_inform->commandKey != NULL) { - bkp_session_delete_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey); - free(schedule_inform->commandKey); - } - free(schedule_inform); - pthread_mutex_unlock(&mutex_schedule_inform); - continue; - } - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - CWMP_LOG(INFO, "Schedule Inform thread: add ScheduleInform event in the queue"); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_3SCHEDULED, ""); - if (event_container != NULL) { - cwmp_save_event_container(event_container); - } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey); - if (event_container != NULL) { - cwmp_save_event_container(event_container); - } - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_schedule_inform); - list_del(&(schedule_inform->list)); - if (schedule_inform->commandKey != NULL) { - bkp_session_delete_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey); - free(schedule_inform->commandKey); - } - free(schedule_inform); - count_schedule_inform_queue--; - pthread_mutex_unlock(&mutex_schedule_inform); - add_event_same_time = true; - continue; - } - bkp_session_save(); - add_event_same_time = false; - pthread_mutex_lock(&mutex_schedule_inform); - si_timeout.tv_sec = stime; - pthread_cond_timedwait(&threshold_schedule_inform, &mutex_schedule_inform, &si_timeout); - pthread_mutex_unlock(&mutex_schedule_inform); - } else { - bkp_session_save(); - add_event_same_time = false; - pthread_mutex_lock(&mutex_schedule_inform); - pthread_cond_wait(&threshold_schedule_inform, &mutex_schedule_inform); - pthread_mutex_unlock(&mutex_schedule_inform); - } + if (schedule_inform != NULL) { + list_del(&(schedule_inform->list)); + bkp_session_delete_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey ? schedule_inform->commandKey : ""); + FREE(schedule_inform->commandKey); + free(schedule_inform); } - - return NULL; + return CWMP_OK; } int cwmp_scheduleInform_remove_all() { - pthread_mutex_lock(&mutex_schedule_inform); while (list_schedule_inform.next != &(list_schedule_inform)) { struct schedule_inform *schedule_inform; schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list); - list_del(&(schedule_inform->list)); - if (schedule_inform->commandKey != NULL) { - bkp_session_delete_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey); - free(schedule_inform->commandKey); - } - free(schedule_inform); + remove_schedule_inform(schedule_inform); } bkp_session_save(); - pthread_mutex_unlock(&mutex_schedule_inform); return CWMP_OK; } + +void cwmp_start_schedule_inform(struct uloop_timeout *timeout) +{ + struct schedule_inform *schedule_inform = container_of(timeout, struct schedule_inform, handler_timer);; + + struct session_timer_event *schedinform_inform_event = calloc(1, sizeof(struct session_timer_event)); + + schedinform_inform_event->extra_data = schedule_inform; + schedinform_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + schedinform_inform_event->event = Schedule_Inform_Evt; + trigger_cwmp_session_timer_with_event(&schedinform_inform_event->session_timer_evt); + +} + +void apply_schedule_inform() +{ + struct list_head *ilist; + list_for_each (ilist, &(list_schedule_inform)) { + struct schedule_inform *sched_inform = list_entry(ilist, struct schedule_inform, list); + int sched_inform_delay = 0; + if (sched_inform->scheduled_time > time(NULL)) { + sched_inform_delay = sched_inform->scheduled_time - time(NULL); + } + uloop_timeout_set(&sched_inform->handler_timer, 1000 * sched_inform_delay); + } +} diff --git a/src/sched_inform.h b/src/sched_inform.h index 7d587e3..babd037 100644 --- a/src/sched_inform.h +++ b/src/sched_inform.h @@ -11,15 +11,12 @@ #ifndef CWMP_SCHED_INFORM_H #define CWMP_SCHED_INFORM_H - #include "common.h" - extern struct list_head list_schedule_inform; -extern pthread_mutex_t mutex_schedule_inform; -extern pthread_cond_t threshold_schedule_inform; extern int count_schedule_inform_queue; -void *thread_cwmp_rpc_cpe_scheduleInform(void *v); +void cwmp_start_schedule_inform(struct uloop_timeout *timeout); int cwmp_scheduleInform_remove_all(); - +void apply_schedule_inform(); +int remove_schedule_inform(struct schedule_inform *schedule_inform); #endif diff --git a/src/session.c b/src/session.c index baf5fee..cb1bee5 100644 --- a/src/session.c +++ b/src/session.c @@ -10,22 +10,493 @@ */ #include +#include +#include "common.h" #include "session.h" #include "config.h" #include "event.h" #include "rpc.h" #include "backupSession.h" #include "heartbeat.h" +#include "http.h" +#include "download.h" +#include "upload.h" +#include "xml.h" +#include "log.h" +#include "notifications.h" +#include "config.h" +#include "ssl_utils.h" +#include "cwmp_event.h" +#include "diagnostic.h" +#include "heartbeat.h" +#include "sched_inform.h" +#include "cwmp_du_state.h" + +static void cwmp_periodic_session_timer(struct uloop_timeout *timeout); +struct uloop_timeout session_timer = { .cb = cwmp_schedule_session }; +struct uloop_timeout periodic_session_timer = { .cb = cwmp_periodic_session_timer }; +struct uloop_timeout retry_session_timer = { .cb = cwmp_schedule_session }; +//struct session_timer_event session_timer_evt = {.session_timer_evt = {.cb = cwmp_schedule_session_with_event}, .event = -1}; unsigned int end_session_flag = 0; -void cwmp_set_end_session(unsigned int flag) +int create_cwmp_session_structure() { - end_session_flag |= flag; + cwmp_main->session = calloc(1, sizeof(struct session)); + if (cwmp_main->session == NULL) + return CWMP_GEN_ERR; + INIT_LIST_HEAD(&(cwmp_main->session->events)); + INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_acs)); + INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_cpe)); + cwmp_main->session->session_status.is_heartbeat = false; + cwmp_main->session->session_status.next_heartbeat = false; + return CWMP_OK; } -struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type) +int cwmp_session_init() +{ + struct rpc *rpc_acs; + + cwmp_main->cwmp_cr_event = 0; + + cwmp_uci_init(); + /* + * Set Required methods as initial value of + */ + rpc_acs = cwmp_add_session_rpc_acs_head(RPC_ACS_GET_RPC_METHODS); + if (rpc_acs == NULL) + return CWMP_GEN_ERR; + + rpc_acs = cwmp_add_session_rpc_acs_head(RPC_ACS_INFORM); + if (rpc_acs == NULL) + return CWMP_GEN_ERR; + + set_cwmp_session_status(SESSION_RUNNING, 0); + if (file_exists(fc_cookies)) + remove(fc_cookies); + return CWMP_OK; +} + +int clean_cwmp_session_structure() +{ + FREE(cwmp_main->session); + return 0; +} + +int cwmp_session_rpc_destructor(struct rpc *rpc) +{ + list_del(&(rpc->list)); + free(rpc); + return CWMP_OK; +} + +int cwmp_session_exit() +{ + cwmp_uci_exit(); + icwmp_cleanmem(); + return CWMP_OK; +} + +static int cwmp_rpc_cpe_handle_message(struct rpc *rpc_cpe) +{ + if (xml_prepare_msg_out()) + return -1; + if (rpc_cpe_methods[rpc_cpe->type].handler(rpc_cpe)) + return -1; + if (xml_set_cwmp_id_rpc_cpe()) + return -1; + + return 0; +} + +int cwmp_schedule_rpc() +{ + struct list_head *ilist; + struct rpc *rpc_acs, *rpc_cpe; + + if (icwmp_http_client_init() || cwmp_stop) { + CWMP_LOG(INFO, "Initializing http client failed"); + goto retry; + } + + while (1) { + list_for_each (ilist, &(cwmp_main->session->head_rpc_acs)) { + rpc_acs = list_entry(ilist, struct rpc, list); + if (rpc_acs_methods[rpc_acs->type].acs_support == RPC_ACS_NOT_SUPPORT) { + CWMP_LOG(WARNING, "The RPC method %s is not included in the RPCs list supported by the ACS", rpc_acs_methods[rpc_acs->type].name); + continue; + } + if (!rpc_acs->type || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name); + if (rpc_acs_methods[rpc_acs->type].prepare_message(rpc_acs) || cwmp_stop) + goto retry; + + if (xml_set_cwmp_id() || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name); + if (xml_send_message(rpc_acs) || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); + if (rpc_acs_methods[rpc_acs->type].parse_response || cwmp_stop) + if (rpc_acs_methods[rpc_acs->type].parse_response(rpc_acs)) + goto retry; + + ilist = ilist->prev; + if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL) + rpc_acs_methods[rpc_acs->type].extra_clean(rpc_acs); + cwmp_session_rpc_destructor(rpc_acs); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + if (cwmp_main->session->hold_request || cwmp_stop) + break; + } + + // If restart service caused firewall restart, wait for firewall restart to complete + if (g_firewall_restart == true) + check_firewall_restart_state(); + + CWMP_LOG(INFO, "Send empty message to the ACS"); + if (xml_send_message(NULL) || cwmp_stop) + goto retry; + if (!cwmp_main->session->tree_in || cwmp_stop) + goto next; + + CWMP_LOG(INFO, "Receive request from the ACS"); + if (xml_handle_message() || cwmp_stop) + goto retry; + + while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) { + + rpc_cpe = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list); + if (!rpc_cpe->type || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); + if (cwmp_rpc_cpe_handle_message(rpc_cpe) || cwmp_stop) + goto retry; + MXML_DELETE(cwmp_main->session->tree_in); + + CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); + if (xml_send_message(rpc_cpe) || cwmp_stop) + goto retry; + MXML_DELETE(cwmp_main->session->tree_out); + + cwmp_session_rpc_destructor(rpc_cpe); + if (!cwmp_main->session->tree_in || cwmp_stop) + break; + + CWMP_LOG(INFO, "Receive request from the ACS"); + if (xml_handle_message() || cwmp_stop) + goto retry; + } + + next: + if (cwmp_main->session->head_rpc_acs.next == &(cwmp_main->session->head_rpc_acs)) + break; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + } + + cwmp_main->session->error = CWMP_OK; + goto end; + +retry: + CWMP_LOG(INFO, "Failed"); + cwmp_main->session->error = CWMP_RETRY_SESSION; + event_remove_noretry_event_container(); + +end: + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + icwmp_http_client_exit(); + xml_exit(); + return cwmp_main->session->error; +} + +int cwmp_get_retry_interval(bool heart_beat) +{ + unsigned int retry_count = 0; + double min = 0; + double max = 0; + int m = cwmp_main->conf.retry_min_wait_interval; + int k = cwmp_main->conf.retry_interval_multiplier; + int exp; + if (heart_beat) + exp = heart_beat_retry_count_session; + else + exp = cwmp_main->retry_count_session; + if (exp == 0) + return MAX_INT32; + if (exp > 10) + exp = 10; + min = pow(((double)k / 1000), (double)(exp - 1)) * m; + max = pow(((double)k / 1000), (double)exp) * m; + char *rand = generate_random_string(4); + if (rand) { + unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16); + retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min; + free(rand); + } + return (retry_count); +} + +void set_cwmp_session_status(int status, int retry_time) +{ + cwmp_main->session->session_status.last_status = status; + if (status == SESSION_SUCCESS) { + cwmp_main->session->session_status.last_end_time = time(NULL); + cwmp_main->session->session_status.next_retry = 0; + cwmp_main->session->session_status.success_session++; + } else if (status == SESSION_RUNNING) { + cwmp_main->session->session_status.last_end_time = 0; + cwmp_main->session->session_status.next_retry = 0; + cwmp_main->session->session_status.last_start_time = time(NULL); + } else { + cwmp_main->session->session_status.last_end_time = time(NULL); + cwmp_main->session->session_status.next_retry = time(NULL) + retry_time; + cwmp_main->session->session_status.failure_session++; + } +} + +void rpc_exit() +{ + struct rpc *rpc; + while (cwmp_main->session->head_rpc_acs.next != &(cwmp_main->session->head_rpc_acs)) { + rpc = list_entry(cwmp_main->session->head_rpc_acs.next, struct rpc, list); + if (!rpc) + break; + if (rpc_acs_methods[rpc->type].extra_clean != NULL) + rpc_acs_methods[rpc->type].extra_clean(rpc); + cwmp_session_rpc_destructor(rpc); + } + + while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) { + rpc = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list); + if (!rpc) + break; + cwmp_session_rpc_destructor(rpc); + } +} + +void start_cwmp_session() +{ + int t, error; + char *exec_download = NULL; + + uloop_timeout_cancel(&check_notify_timer); + if (cwmp_session_init() != CWMP_OK) { + CWMP_LOG(ERROR, "Not able to init a CWMP session"); + t = cwmp_get_retry_interval(0); + CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t); + set_cwmp_session_status(SESSION_FAILURE, t); + cwmp_config_load(); + trigger_periodic_notify_check(); + return; + } + + if (cwmp_main->session->session_status.last_status == SESSION_FAILURE) + cwmp_config_load(); + /* + * Value changes + */ + if (!cwmp_main->session->session_status.is_heartbeat) { + int is_notify = 0; + if (file_exists(DM_ENABLED_NOTIFY)) { + if (!event_exist_in_list(EVENT_IDX_4VALUE_CHANGE)) + is_notify = check_value_change(); + } + if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp_main->custom_notify_active) { + cwmp_main->custom_notify_active = false; + cwmp_update_enabled_notify_file(); + } + cwmp_prepare_value_change(cwmp_main); + clean_list_value_change(); + } + /* + * Start session + */ + + CWMP_LOG(INFO, "Start session"); + + uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download); + if (exec_download && strcmp(exec_download, "1") == 0) { + CWMP_LOG(INFO, "Firmware downloaded and applied successfully"); + cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0"); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); + } + FREE(exec_download); + error = cwmp_schedule_rpc(); + if (error != CWMP_OK) { + CWMP_LOG(ERROR, "CWMP session error: %d", error); + } + /* + * End session + */ + CWMP_LOG(INFO, "End session"); + + if (cwmp_stop) { + event_remove_all_event_container(RPC_SEND); + event_remove_all_event_container(RPC_QUEUE); + run_session_end_func(); + cwmp_session_exit(); + rpc_exit(); + return; + } + + if (cwmp_main->session->error == CWMP_RETRY_SESSION && (!list_empty(&(cwmp_main->session->events)) || (list_empty(&(cwmp_main->session->events)) && cwmp_main->cwmp_cr_event == 0))) { //CWMP Retry session + cwmp_config_load(); + cwmp_main->retry_count_session++; + t = cwmp_get_retry_interval(0); + CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t); + if (!cwmp_main->session->session_status.is_heartbeat) { + set_cwmp_session_status(SESSION_FAILURE, t); + uloop_timeout_set(&retry_session_timer, 1000 * t); + } else { + uloop_timeout_cancel(&heartbeat_session_timer); + uloop_timeout_set(&heartbeat_session_timer, 1000 * t); + } + } else { + if (!cwmp_main->session->session_status.is_heartbeat) + event_remove_all_event_container(RPC_SEND); + else + remove_single_event(EVENT_IDX_14HEARTBEAT); + //event_remove_all_event_container(RPC_QUEUE); + cwmp_main->retry_count_session = 0; + set_cwmp_session_status(SESSION_SUCCESS, 0); + rpc_exit(); + } + run_session_end_func(); + cwmp_session_exit(); + CWMP_LOG(INFO, "Waiting the next session"); + if (cwmp_main->session->session_status.next_heartbeat && (cwmp_main->session->session_status.last_status == SESSION_SUCCESS)) { + cwmp_main->session->session_status.next_heartbeat = false; + uloop_timeout_cancel(&heartbeat_session_timer); + uloop_timeout_set(&heartbeat_session_timer, 1000); + + } else { + cwmp_main->session->session_status.is_heartbeat = false; + trigger_periodic_notify_check(); + } +} + +void trigger_cwmp_session_timer() +{ + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_set(&session_timer, 10); +} + +void cwmp_schedule_session(struct uloop_timeout *timeout __attribute__((unused))) +{ + start_cwmp_session(); +} + +void trigger_cwmp_session_timer_with_event(struct uloop_timeout *timeout) +{ + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_cancel(timeout); + uloop_timeout_set(timeout, 10); +} + +void cwmp_schedule_session_with_event(struct uloop_timeout *timeout) +{ + struct session_timer_event *session_event = container_of(timeout, struct session_timer_event, session_timer_evt); + FREE(global_session_event); + global_session_event = session_event; + if (session_event->event == TransferClt_Evt) { + struct transfer_complete *ptransfer_complete = (struct transfer_complete *)session_event->extra_data; + cwmp_root_cause_transfer_complete(ptransfer_complete); + } else if (session_event->event == CDU_Evt) { + struct du_state_change_complete *pdu_state_change_complete = (struct du_state_change_complete *)session_event->extra_data; + cwmp_root_cause_changedustate_complete(pdu_state_change_complete); + } else if (session_event->event == Schedule_Inform_Evt) { + struct schedule_inform *schedule_inform = (struct schedule_inform *)session_event->extra_data; + cwmp_root_cause_schedule_inform(schedule_inform); + } else if (session_event->event == EVENT_IDX_14HEARTBEAT) { + cwmp_main->session->session_status.next_heartbeat = false; + cwmp_main->session->session_status.is_heartbeat = true; + cwmp_add_event_container(EVENT_IDX_14HEARTBEAT, ""); + } else if (session_event->event >= 0) { + struct event_container *event_container = NULL; + event_container = cwmp_add_event_container(session_event->event, ""); + if (event_container == NULL) { + CWMP_LOG(ERROR, "Not able to add the event %s for the new session", EVENT_CONST[session_event->event].CODE); + } + session_event->event = -1; + cwmp_save_event_container(event_container); + } + + start_cwmp_session(); +} + +static void cwmp_periodic_session_timer(struct uloop_timeout *timeout __attribute__((unused))) +{ + if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) { + cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period; + uloop_timeout_set(&periodic_session_timer, cwmp_main->conf.period * 1000); + } + if (cwmp_main->conf.periodic_enable) { + struct session_timer_event *periodic_inform_event = calloc(1, sizeof(struct session_timer_event)); + + periodic_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + periodic_inform_event->event = EVENT_IDX_2PERIODIC; + trigger_cwmp_session_timer_with_event(&periodic_inform_event->session_timer_evt); + } +} + +long int cwmp_periodic_session_time(void) +{ + long int delta_time; + long int periodic_time; + + delta_time = time(NULL) - cwmp_main->conf.time; + if(delta_time > 0) + periodic_time = cwmp_main->conf.period - (delta_time % cwmp_main->conf.period); + else + periodic_time = (-delta_time) % cwmp_main->conf.period; + + cwmp_main->session->session_status.next_periodic = time(NULL) + periodic_time; + return periodic_time; +} + +void initiate_cwmp_periodic_session_feature() +{ + uloop_timeout_cancel(&periodic_session_timer); + if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) { + if (cwmp_main->conf.time > 0){ + CWMP_LOG(INFO, "Init periodic inform: periodic_inform time = %ld, interval = %d\n", cwmp_main->conf.time, cwmp_main->conf.period); + uloop_timeout_set(&periodic_session_timer, cwmp_periodic_session_time() * 1000); + } else { + CWMP_LOG(INFO, "Init periodic inform: interval = %d\n", cwmp_main->conf.period); + cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period; + uloop_timeout_set(&periodic_session_timer, cwmp_main->conf.period * 1000); + } + } +} + +void reinit_cwmp_periodic_session_feature() +{ + if (cwmp_main->conf.periodic_enable) { + if (!cwmp_main->prev_periodic_enable || (cwmp_main->prev_periodic_interval != cwmp_main->conf.period) || (cwmp_main->prev_periodic_time != cwmp_main->conf.time)) { + uloop_timeout_cancel(&periodic_session_timer); + if ((cwmp_main->prev_periodic_time != cwmp_main->conf.time) && cwmp_main->conf.time > 0) + uloop_timeout_set(&periodic_session_timer, cwmp_periodic_session_time() * 1000); + else + uloop_timeout_set(&periodic_session_timer, cwmp_main->conf.period * 1000); + } + } else + uloop_timeout_cancel(&periodic_session_timer); + + cwmp_main->prev_periodic_enable = cwmp_main->conf.periodic_enable; + cwmp_main->prev_periodic_interval = cwmp_main->conf.period; + cwmp_main->prev_periodic_time = cwmp_main->conf.time; +} + +struct rpc *cwmp_add_session_rpc_cpe(int type) { struct rpc *rpc_cpe; @@ -34,11 +505,11 @@ struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type) return NULL; } rpc_cpe->type = type; - list_add_tail(&(rpc_cpe->list), &(session->head_rpc_cpe)); + list_add_tail(&(rpc_cpe->list), &(cwmp_main->session->head_rpc_cpe)); return rpc_cpe; } -struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type) +struct rpc *cwmp_add_session_rpc_acs(int type) { struct rpc *rpc_acs; @@ -47,7 +518,7 @@ struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type) return NULL; } rpc_acs->type = type; - list_add_tail(&(rpc_acs->list), &(session->head_rpc_acs)); + list_add_tail(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs)); return rpc_acs; } @@ -55,7 +526,7 @@ int cwmp_apply_acs_changes(void) { int error; - old_heartbeat_enable = cwmp_main.conf.heart_beat_enable; + old_heartbeat_enable = cwmp_main->conf.heart_beat_enable; if ((error = cwmp_config_reload(&cwmp_main))) return error; @@ -66,23 +537,7 @@ int cwmp_apply_acs_changes(void) return CWMP_OK; } -int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session) -{ - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - if (cwmp->session_send != NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MUTEX_ERR; - } - list_del(&(session->list)); - cwmp->session_send = session; - cwmp->head_event_container = NULL; - bkp_session_move_inform_to_inform_send(); - bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_OK; -} - -struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type) +struct rpc *cwmp_add_session_rpc_acs_head(int type) { struct rpc *rpc_acs; @@ -91,151 +546,145 @@ struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type) return NULL; } rpc_acs->type = type; - list_add(&(rpc_acs->list), &(session->head_rpc_acs)); + list_add(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs)); return rpc_acs; } -struct session *cwmp_add_queue_session(struct cwmp *cwmp) +void cwmp_set_end_session(unsigned int flag) { - struct session *session = NULL; - struct rpc *rpc_acs; - - session = calloc(1, sizeof(struct session)); - if (session == NULL) - return NULL; - - list_add_tail(&(session->list), &(cwmp->head_session_queue)); - INIT_LIST_HEAD(&(session->head_event_container)); - INIT_LIST_HEAD(&(session->head_rpc_acs)); - INIT_LIST_HEAD(&(session->head_rpc_cpe)); - - /* - * Set Required methods as initial value of - */ - rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_GET_RPC_METHODS); - if (rpc_acs == NULL) { - FREE(session); - return NULL; - } - rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM); - if (rpc_acs == NULL) { - FREE(session); - return NULL; - } - - return session; + end_session_flag |= flag; } -int cwmp_session_rpc_destructor(struct rpc *rpc) +int run_session_end_func(void) { - list_del(&(rpc->list)); - free(rpc); - return CWMP_OK; -} - -int cwmp_session_destructor(struct session *session) -{ - struct rpc *rpc; - while (session->head_rpc_acs.next != &(session->head_rpc_acs)) { - rpc = list_entry(session->head_rpc_acs.next, struct rpc, list); - if (!rpc) - break; - if (rpc_acs_methods[rpc->type].extra_clean != NULL) - rpc_acs_methods[rpc->type].extra_clean(session, rpc); - cwmp_session_rpc_destructor(rpc); - } - - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - rpc = list_entry(session->head_rpc_cpe.next, struct rpc, list); - if (!rpc) - break; - cwmp_session_rpc_destructor(rpc); - } - - if (session->list.next != NULL && session->list.prev != NULL) - list_del(&(session->list)); - free(session); - - return CWMP_OK; -} - -int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session) -{ - struct list_head *ilist, *jlist; - struct rpc *rpc_acs, *queue_rpc_acs; - struct session *session_queue; - - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->retry_count_session++; - cwmp->session_send = NULL; - if (cwmp->head_session_queue.next == &(cwmp->head_session_queue)) { - list_add_tail(&(session->list), &(cwmp->head_session_queue)); - session->hold_request = 0; - session->digest_auth = 0; - cwmp->head_event_container = &(session->head_event_container); - if (session->head_rpc_acs.next != &(session->head_rpc_acs)) { - rpc_acs = list_entry(session->head_rpc_acs.next, struct rpc, list); - if (rpc_acs->type != RPC_ACS_INFORM) { - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - } - } else { - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - } - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - struct rpc *rpc_cpe; - rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list); - cwmp_session_rpc_destructor(rpc_cpe); - } - bkp_session_move_inform_to_inform_queue(); - bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_OK; - } - list_for_each (ilist, &(session->head_event_container)) { - struct event_container *event_container_new, *event_container_old; - event_container_old = list_entry(ilist, struct event_container, list); - event_container_new = cwmp_add_event_container(cwmp, event_container_old->code, event_container_old->command_key); - if (event_container_new == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - list_splice_init(&(event_container_old->head_dm_parameter), &(event_container_new->head_dm_parameter)); - cwmp_save_event_container(event_container_new); - } - session_queue = list_entry(cwmp->head_event_container, struct session, head_event_container); - list_for_each (ilist, &(session->head_rpc_acs)) { - rpc_acs = list_entry(ilist, struct rpc, list); - bool dup; - dup = false; - list_for_each (jlist, &(session_queue->head_rpc_acs)) { - queue_rpc_acs = list_entry(jlist, struct rpc, list); - if (queue_rpc_acs->type == rpc_acs->type && (rpc_acs->type == RPC_ACS_INFORM || rpc_acs->type == RPC_ACS_GET_RPC_METHODS)) { - dup = true; - break; - } - } - if (dup) { - continue; - } - ilist = ilist->prev; - list_del(&(rpc_acs->list)); - list_add_tail(&(rpc_acs->list), &(session_queue->head_rpc_acs)); - } - cwmp_session_destructor(session); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + if (end_session_flag & END_SESSION_RESTART_SERVICES) { + CWMP_LOG(INFO, "Restart modified services"); + icwmp_restart_services(); + } + + if (end_session_flag & END_SESSION_RELOAD) { + CWMP_LOG(INFO, "Config reload: end session request"); + cwmp_uci_reinit(); + if (cwmp_apply_acs_changes() != CWMP_OK) { + CWMP_LOG(ERROR, "config reload failed at session end"); + } + reinit_cwmp_periodic_session_feature(); + reinit_heartbeat_procedures(); + } + + if (end_session_flag & END_SESSION_INIT_NOTIFY) { + CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify"); + reinit_list_param_notify(); + } + + if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) { + CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file"); + cwmp_update_enabled_notify_file(); + } + + if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request"); + cwmp_nslookup_diagnostics(); + } + + if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request"); + cwmp_traceroute_diagnostics(); + } + + if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request"); + cwmp_udp_echo_diagnostics(); + } + + if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request"); + cwmp_serverselection_diagnostics(); + } + + if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request"); + cwmp_ip_ping_diagnostics(); + } + + if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing download diagnostic: end session request"); + cwmp_download_diagnostics(); + } + + if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing upload diagnostic: end session request"); + cwmp_upload_diagnostics(); + } + + if (cwmp_main->diag_session) { + struct session_timer_event *periodic_inform_event = calloc(1, sizeof(struct session_timer_event)); + periodic_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + periodic_inform_event->event = EVENT_IDX_8DIAGNOSTICS_COMPLETE; + trigger_cwmp_session_timer_with_event(&periodic_inform_event->session_timer_evt); + cwmp_main->diag_session = false; + } + + if (end_session_flag & END_SESSION_DOWNLOAD) { + CWMP_LOG(INFO, "Apply Downaload Calls"); + apply_downloads(); + } + + if (end_session_flag & END_SESSION_SCHEDULE_DOWNLOAD) { + CWMP_LOG(INFO, "Apply ScheduleDownaload Calls"); + apply_schedule_downloads(); + } + + if (end_session_flag & END_SESSION_UPLOAD) { + CWMP_LOG(INFO, "Apply Upload Calls"); + apply_upload(); + } + + if (end_session_flag & END_SESSION_SCHEDULE_INFORM) { + CWMP_LOG(INFO, "Apply ScheduleInform Calls"); + apply_schedule_inform(); + } + + if (end_session_flag & END_SESSION_CDU) { + CWMP_LOG(INFO, "Apply CDU Calls"); + apply_change_du_state(); + } + + if (cwmp_main->heart_session) { + uloop_timeout_cancel(&heartbeat_session_timer); + uloop_timeout_set(&heartbeat_session_timer, cwmp_main->heart_session_interval * 1000); + cwmp_main->heart_session = false; + } + + if (end_session_flag & END_SESSION_REBOOT) { + CWMP_LOG(INFO, "Executing Reboot: end session request"); + cwmp_reboot(commandKey); + exit(EXIT_SUCCESS); + } + + if (end_session_flag & END_SESSION_FACTORY_RESET) { + CWMP_LOG(INFO, "Executing factory reset: end session request"); + cwmp_factory_reset(); + exit(EXIT_SUCCESS); + } + + if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) { + CWMP_LOG(INFO, "Executing factory reset soft: end session request"); + cwmp_factory_reset(); + exit(EXIT_SUCCESS); + } + + // check if any interface reset request exists then take action + intf_reset_node *iter = NULL, *node = NULL; + list_for_each_entry_safe(iter, node, &intf_reset_list, list) { + CWMP_LOG(INFO, "Executing interface reset: end session request"); + cwmp_invoke_intf_reset(iter->path); + list_del(&iter->list); + free(iter); + } + + INIT_LIST_HEAD(&intf_reset_list); + + end_session_flag = 0; return CWMP_OK; } diff --git a/src/session.h b/src/session.h index d2090c0..52cd237 100644 --- a/src/session.h +++ b/src/session.h @@ -12,14 +12,29 @@ #ifndef SESSION_H_ #define SESSION_H_ -#include "xml_utils.h" +#include #include "common.h" + +extern struct uloop_timeout retry_session_timer; + +typedef struct session_status { + time_t last_start_time; + time_t last_end_time; + int last_status; + bool is_heartbeat; + time_t next_periodic; + time_t next_retry; + bool next_heartbeat; + unsigned int success_session; + unsigned int failure_session; +} session_status; + typedef struct session { - struct list_head list; - struct list_head head_event_container; struct list_head head_rpc_cpe; struct list_head head_rpc_acs; + struct list_head events; + struct session_status session_status; mxml_node_t *tree_in; mxml_node_t *tree_out; mxml_node_t *body_in; @@ -29,6 +44,15 @@ typedef struct session { int error; } session; +struct session_timer_event { + struct uloop_timeout session_timer_evt; + int event; + void *extra_data; +}; + + +//extern struct session_timer_event session_timer_evt; + enum end_session_enum { END_SESSION_REBOOT = 1, @@ -45,7 +69,12 @@ enum end_session_enum END_SESSION_SERVERSELECTION_DIAGNOSTIC = 1 << 11, END_SESSION_SET_NOTIFICATION_UPDATE = 1 << 12, END_SESSION_RESTART_SERVICES = 1 << 13, - END_SESSION_INIT_NOTIFY = 1 << 14 + END_SESSION_INIT_NOTIFY = 1 << 14, + END_SESSION_DOWNLOAD = 1 << 15, + END_SESSION_SCHEDULE_DOWNLOAD = 1 << 16, + END_SESSION_UPLOAD = 1 << 17, + END_SESSION_SCHEDULE_INFORM = 1 << 18, + END_SESSION_CDU = 1 << 19 }; enum enum_session_status @@ -59,13 +88,25 @@ enum enum_session_status extern unsigned int end_session_flag; void cwmp_set_end_session(unsigned int flag); -struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type); -struct session *cwmp_add_queue_session(struct cwmp *cwmp); -struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type); -int cwmp_apply_acs_changes(); -int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session); -struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type); +struct rpc *cwmp_add_session_rpc_cpe(int type); +struct rpc *cwmp_add_session_rpc_acs(int type); +struct rpc *cwmp_add_session_rpc_acs_head(int type); int cwmp_session_rpc_destructor(struct rpc *rpc); -int cwmp_session_destructor(struct session *session); -int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session); +void trigger_cwmp_session_timer(); +void trigger_session_by_ubus(char *event); +void initiate_cwmp_periodic_session_feature(); +int run_session_end_func(void); +void cwmp_schedule_session(struct uloop_timeout *timeout); +void cwmp_schedule_session_with_event(struct uloop_timeout *timeout); +void trigger_cwmp_session_timer_with_event(struct uloop_timeout *timeout); +void start_cwmp_session(); +int create_cwmp_session_structure(); +int clean_cwmp_session_structure(); +void set_cwmp_session_status(int status, int retry_time); +int cwmp_session_init(); +int cwmp_session_exit(); +int cwmp_schedule_rpc(); +int cwmp_get_retry_interval(bool heart_beat); +int cwmp_apply_acs_changes(void); +void rpc_exit(); #endif /* SRC_INC_SESSION_H_ */ diff --git a/src/ssl_utils.c b/src/ssl_utils.c index 175fabf..d512dcc 100644 --- a/src/ssl_utils.c +++ b/src/ssl_utils.c @@ -118,9 +118,8 @@ end: void message_compute_signature(char *msg_out, char *signature, size_t len) { int result_len = 20; - struct cwmp *cwmp = &cwmp_main; struct config *conf; - conf = &(cwmp->conf); + conf = &(cwmp_main->conf); #ifdef LMBEDTLS unsigned char result[MBEDTLS_MD_MAX_SIZE] = {0}; diff --git a/src/subprocess.c b/src/subprocess.c new file mode 100644 index 0000000..48c16df --- /dev/null +++ b/src/subprocess.c @@ -0,0 +1,146 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + * + */ + +#include + +#include "common.h" +#include "subprocess.h" +#include "log.h" + +#define END_TASK "{\"task\":\"end\"}" +#define EXIT_TASK "{\"task\":\"exit\"}" + +static int pipefd1[2], pipefd2[2]; + +bool check_task_name(char *task, char *name) +{ + struct blob_buf bbuf; + + if (strcmp(task, "{}") == 0) + return false; + + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return false; + } + + const struct blobmsg_policy p[1] = { { "task", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + if (tb[0] == NULL) + return false; + + char *task_name = blobmsg_get_string(tb[0]); + + if (strcmp(task_name, name) == 0) { + blob_buf_free(&bbuf); + return true; + } + blob_buf_free(&bbuf); + return false; +} + +bool check_task_is_end(char *task) +{ + return check_task_name(task, "end"); +} + +bool check_task_is_exit(char *task) +{ + return check_task_name(task, "exit"); +} + +int subprocess_start(task_function task_fun) +{ + if(task_fun == NULL) + return CWMP_GEN_ERR; + + pid_t p; + if (pipe(pipefd1) == -1) { + CWMP_LOG(ERROR, "pipefd1 failed\n"); + return CWMP_GEN_ERR; + } + if (pipe(pipefd2) == -1) { + CWMP_LOG(ERROR, "pipefd2 failed\n"); + return CWMP_GEN_ERR; + } + p = fork(); + if (p == 0) { + while(1) { + char from_parent[512]; + read(pipefd1[0], from_parent, 512); //The received string should has the form {"task":"TaskName", "arg1_name":"xxx", "arg2_name":"xxxx"} + if (strlen(from_parent) == 0) + continue; + //get the task name + //if the task name is end + if (check_task_is_end(from_parent)){ + write(pipefd2[1], EXIT_TASK, strlen(EXIT_TASK)+1); + exit(EXIT_SUCCESS); + } + char *to_child = task_fun(from_parent); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "ret", to_child); + char *to_child_json = blobmsg_format_json(bbuf.head, true); + write(pipefd2[1], to_child_json, strlen(to_child_json)+1); + FREE(to_child); + FREE(to_child_json); + blob_buf_free(&bbuf); + } + } + return CWMP_OK; +} + +char *execute_task_in_subprocess(char *task) +{ + char *ret = NULL; + + write(pipefd1[1], task, strlen(task) + 1); + + while(1) { + char from_child[512]; + read(pipefd2[0], from_child, 512); + if(strlen(from_child) == 0) + continue; + //The received string from the child should has the format {"task":"exit"} or {"ret":"exit"} + if (check_task_is_exit(from_child)){ + close(pipefd2[1]); + close(pipefd2[0]); + break; + } + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + if (blobmsg_add_json_from_string(&bbuf, from_child) == false) { + blob_buf_free(&bbuf); + continue; + } + const struct blobmsg_policy p[1] = { { "ret", BLOBMSG_TYPE_STRING } }; + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + if (tb[0] == NULL) { + blob_buf_free(&bbuf); + continue; + } + ret = blobmsg_get_string(tb[0]); + write(pipefd1[1], END_TASK, strlen(END_TASK) +1); + } + close(pipefd1[0]); + close(pipefd1[1]); + return ret; +} diff --git a/src/subprocess.h b/src/subprocess.h new file mode 100644 index 0000000..a1c2316 --- /dev/null +++ b/src/subprocess.h @@ -0,0 +1,7 @@ +#ifndef SUB_PROC_H +#define SUB_PROC_H +#include +typedef char* (*task_function)(char *task_arg); +int subprocess_start(task_function task_fun); +char *execute_task_in_subprocess(char *task); +#endif diff --git a/src/ubus_utils.c b/src/ubus_utils.c index 6b4cea0..8dfea8f 100644 --- a/src/ubus_utils.c +++ b/src/ubus_utils.c @@ -14,9 +14,13 @@ #include "sched_inform.h" #include "event.h" #include "cwmp_uci.h" +#include "session.h" +#include "cwmp_event.h" typedef int (*callback)(struct blob_buf *b); +static struct ubus_context *ubus_ctx = NULL; + struct command_cb { char *str; callback cb; @@ -33,16 +37,14 @@ static const char *arr_session_status[] = { static int reload_cmd(struct blob_buf *b) { CWMP_LOG(INFO, "triggered ubus reload"); - if (cwmp_main.session_status.last_status == SESSION_RUNNING) { + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { cwmp_set_end_session(END_SESSION_RELOAD); blobmsg_add_u32(b, "status", 0); blobmsg_add_string(b, "info", "Session running, reload at the end of the session"); } else { int error = CWMP_OK; - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); cwmp_uci_reinit(); error = cwmp_apply_acs_changes(); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); if (error != CWMP_OK) { // Failed to load cwmp config CWMP_LOG(ERROR, "cwmp failed to reload the configuration"); @@ -102,7 +104,7 @@ static const struct blobmsg_policy icwmp_cmd_policy[] = { static int icwmp_command_handler(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)), struct ubus_request_data *req, const char *method __attribute__((unused)), struct blob_attr *msg) { - if (cwmp_main.init_complete == false) { + if (cwmp_main->init_complete == false) { CWMP_LOG(INFO, "Request can't be handled since icwmpd is still in init state"); return 0; } @@ -168,7 +170,7 @@ static time_t get_next_session_time() sched_time = schedule_inform->scheduled_time; } - time_t next_time = get_nonzero_min_time(sched_time, cwmp_main.session_status.next_retry, cwmp_main.session_status.next_periodic); + time_t next_time = get_nonzero_min_time(sched_time, cwmp_main->session->session_status.next_retry, cwmp_main->session->session_status.next_periodic); return next_time; } @@ -176,20 +178,20 @@ static time_t get_next_session_time() static void bb_add_icwmp_status(struct blob_buf *bb) { void *tbl = blobmsg_open_table(bb, "cwmp"); - bb_add_string(bb, "status", cwmp_main.init_complete ? "up" : "init"); - bb_add_string(bb, "start_time", get_time(cwmp_main.start_time)); - bb_add_string(bb, "acs_url", cwmp_main.conf.acsurl); + bb_add_string(bb, "status", cwmp_main->init_complete ? "up" : "init"); + bb_add_string(bb, "start_time", get_time(cwmp_main->start_time)); + bb_add_string(bb, "acs_url", cwmp_main->conf.acsurl); blobmsg_close_table(bb, tbl); } static void bb_add_icwmp_last_session(struct blob_buf *bb) { void *tbl = blobmsg_open_table(bb, "last_session"); - const char *status = cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A"; + const char *status = cwmp_main->session->session_status.last_start_time ? arr_session_status[cwmp_main->session->session_status.last_status] : "N/A"; bb_add_string(bb, "status", status); - char *start_time = cwmp_main.session_status.last_start_time ? get_time(cwmp_main.session_status.last_start_time) : "N/A"; + char *start_time = cwmp_main->session->session_status.last_start_time ? get_time(cwmp_main->session->session_status.last_start_time) : "N/A"; bb_add_string(bb, "start_time", start_time); - char *end_time = cwmp_main.session_status.last_end_time ? get_time(cwmp_main.session_status.last_end_time) : "N/A"; + char *end_time = cwmp_main->session->session_status.last_end_time ? get_time(cwmp_main->session->session_status.last_end_time) : "N/A"; bb_add_string(bb, "end_time", end_time); blobmsg_close_table(bb, tbl); } @@ -208,9 +210,9 @@ static void bb_add_icwmp_next_session(struct blob_buf *bb) static void bb_add_icwmp_statistics(struct blob_buf *bb) { void *tbl = blobmsg_open_table(bb, "statistics"); - blobmsg_add_u32(bb, "success_sessions", cwmp_main.session_status.success_session); - blobmsg_add_u32(bb, "failure_sessions", cwmp_main.session_status.failure_session); - blobmsg_add_u32(bb, "total_sessions", cwmp_main.session_status.success_session + cwmp_main.session_status.failure_session); + blobmsg_add_u32(bb, "success_sessions", cwmp_main->session->session_status.success_session); + blobmsg_add_u32(bb, "failure_sessions", cwmp_main->session->session_status.failure_session); + blobmsg_add_u32(bb, "total_sessions", cwmp_main->session->session_status.success_session + cwmp_main->session->session_status.failure_session); blobmsg_close_table(bb, tbl); } @@ -245,81 +247,51 @@ static const struct blobmsg_policy icwmp_inform_policy[] = { [INFORM_EVENT] = {.name = "event", .type = BLOBMSG_TYPE_STRING }, }; -static void icwmp_inform_get_rpc_method(struct ubus_context *ctx, struct ubus_request_data *req) +static int icwmp_inform_get_rpc_method(struct blob_buf *bb) { - struct event_container *event_container; - struct session *session; - struct blob_buf bb; + if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL) + return -1; - if (ctx == NULL) - return; + blobmsg_add_u32(bb, "status", 1); + blobmsg_add_string(bb, "info", "Session with GetRPCMethods will start"); - memset(&bb, 0, sizeof(struct blob_buf)); - blob_buf_init(&bb, 0); - - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_2PERIODIC, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - return; - } - - cwmp_save_event_container(event_container); - session = list_entry(cwmp_main.head_event_container, struct session, head_event_container); - if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - return; - } - - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); - blobmsg_add_u32(&bb, "status", 1); - blobmsg_add_string(&bb, "info", "Session with GetRPCMethods will start"); - - ubus_send_reply(ctx, req, bb.head); - blob_buf_free(&bb); + return EVENT_IDX_2PERIODIC; } -static void icwmp_inform_event(struct ubus_context *ctx, struct ubus_request_data *req, char *event) +static int icwmp_inform_event(struct blob_buf *bb, char *event) { - struct blob_buf bb; - - if (ctx == NULL || event == NULL) - return; - - memset(&bb, 0, sizeof(struct blob_buf)); - blob_buf_init(&bb, 0); - int event_code = cwmp_get_int_event_code(event); - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - cwmp_add_event_container(&cwmp_main, event_code, ""); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); if (event_code != EVENT_IDX_14HEARTBEAT) { - pthread_cond_signal(&(cwmp_main.threshold_session_send)); - if (cwmp_main.session_status.last_status == SESSION_RUNNING) { - blobmsg_add_u32(&bb, "status", -1); - blobmsg_add_string(&bb, "info", "Session already running, event will be sent at the end of the session"); + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { + blobmsg_add_u32(bb, "status", -1); + blobmsg_add_string(bb, "info", "Session already running, event will be sent at the end of the session"); } else { - blobmsg_add_u32(&bb, "status", 1); - blobmsg_add_string(&bb, "info", "Session started"); + blobmsg_add_u32(bb, "status", 1); + blobmsg_add_string(bb, "info", "Session started"); } } - - ubus_send_reply(ctx, req, bb.head); - blob_buf_free(&bb); + return event_code; } static int icwmp_inform_handler(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)), struct ubus_request_data *req, const char *method __attribute__((unused)), struct blob_attr *msg) { - if (cwmp_main.init_complete == false) { - CWMP_LOG(INFO, "Inform can't be sent since icwmpd is still in init state"); - return 0; + struct blob_buf bb; + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + if (cwmp_main->init_complete == false) { + CWMP_LOG(WARNING, "Inform can't be sent since icwmpd is still in init state"); + blobmsg_add_u32(&bb, "status", -1); + blobmsg_add_string(&bb, "info", "icwmpd is still in init state"); + goto end; } + struct blob_attr *tb[__INFORM_MAX] = {0}; bool is_get_rpc = false; char *event = ""; int ret = -1; + int event_code = -1; ret = blobmsg_parse(icwmp_inform_policy, ARRAY_SIZE(icwmp_inform_policy), tb, blob_data(msg), blob_len(msg)); @@ -332,11 +304,26 @@ static int icwmp_inform_handler(struct ubus_context *ctx, struct ubus_object *ob } if (is_get_rpc) { - icwmp_inform_get_rpc_method(ctx, req); + event_code = icwmp_inform_get_rpc_method(&bb); } else { - icwmp_inform_event(ctx, req, event); + event_code = icwmp_inform_event(&bb, event); + } + if (event_code == -1) { + CWMP_LOG(WARNING, "tr069 ubus: ubus inform method not able to get the event code"); + blobmsg_add_u32(&bb, "status", -1); + blobmsg_add_string(&bb, "info", "not able to get the event code"); + goto end; } + struct session_timer_event *ubus_inform_event = calloc(1, sizeof(struct session_timer_event)); + + ubus_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + ubus_inform_event->event = event_code; + trigger_cwmp_session_timer_with_event(&ubus_inform_event->session_timer_evt); + +end: + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); return 0; } @@ -376,25 +363,48 @@ void bb_add_string(struct blob_buf *bb, const char *name, const char *value) blobmsg_add_string(bb, name, ""); } +int icwmp_uloop_ubus_init() +{ + ubus_ctx = ubus_connect(cwmp_main->conf.ubus_socket); + if (!ubus_ctx) + return -1; + + ubus_add_uloop(ubus_ctx); + + if (icwmp_register_object(ubus_ctx)) + return -1; + + return 0; +} + +void icwmp_uloop_ubus_exit() +{ + if (ubus_ctx) { + ubus_remove_object(ubus_ctx, &tr069_object); + ubus_free(ubus_ctx); + ubus_ctx = NULL; + } +} + int icwmp_ubus_invoke(const char *obj, const char *method, struct blob_attr *msg, icwmp_ubus_cb icwmp_callback, void *callback_arg) { uint32_t id; int rc = 0; - struct ubus_context *ubus_ctx = NULL; + struct ubus_context *ctx = NULL; - ubus_ctx = ubus_connect(NULL); - if (ubus_ctx == NULL) + ctx = ubus_connect(NULL); + if (ctx == NULL) return -1; - if (!ubus_lookup_id(ubus_ctx, obj, &id)) - rc = ubus_invoke(ubus_ctx, id, method, msg, icwmp_callback, callback_arg, 20000); + if (!ubus_lookup_id(ctx, obj, &id)) + rc = ubus_invoke(ctx, id, method, msg, icwmp_callback, callback_arg, 20000); else rc = -1; - if (ubus_ctx) { - ubus_free(ubus_ctx); - ubus_ctx = NULL; + if (ctx) { + ubus_free(ctx); + ctx = NULL; } return rc; diff --git a/src/ubus_utils.h b/src/ubus_utils.h index 632b191..384f8f2 100644 --- a/src/ubus_utils.h +++ b/src/ubus_utils.h @@ -21,5 +21,6 @@ int icwmp_register_object(struct ubus_context *ctx); int icwmp_delete_object(struct ubus_context *ctx); int icwmp_ubus_invoke(const char *obj, const char *method, struct blob_attr *msg, icwmp_ubus_cb icwmp_callback, void *callback_arg); - +int icwmp_uloop_ubus_init(); +void icwmp_uloop_ubus_exit(); #endif /* __ICWMP_UBUS_UTILS_H__ */ diff --git a/src/upload.c b/src/upload.c index 9b40a05..0ee4ec5 100644 --- a/src/upload.c +++ b/src/upload.c @@ -20,14 +20,13 @@ #include "backupSession.h" #include "event.h" #include "cwmp_uci.h" +#include "subprocess.h" +#include "session.h" #define CURL_TIMEOUT 20 LIST_HEAD(list_upload); -pthread_cond_t threshold_upload; -pthread_mutex_t mutex_upload = PTHREAD_MUTEX_INITIALIZER; - int lookup_vcf_name(int instance, char **value) { char vcf_name_parameter[256]; @@ -64,6 +63,9 @@ int lookup_vlf_name(int instance, char **value) return 0; } +/* + * Upload file + */ int upload_file(const char *file_path, const char *url, const char *username, const char *password) { int res_code = 0; @@ -109,6 +111,58 @@ int upload_file(const char *file_path, const char *url, const char *username, co return res_code; } +char *upload_file_task_function(char *task) +{ + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return NULL; + } + const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL}; + blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + char *task_name = blobmsg_get_string(tb[0]); + if (!task_name || strcmp(task_name, "upload") != 0) + return NULL; + char *file_path = blobmsg_get_string(tb[1]); + char *url = blobmsg_get_string(tb[2]); + char *username = blobmsg_get_string(tb[3]); + char *password = blobmsg_get_string(tb[4]); + + int http_code = upload_file(file_path, url, username, password); + char *http_ret = (char *)malloc(4 * sizeof(char)); + snprintf(http_ret, 4, "%d", http_code); + http_ret[3] = 0; + return http_ret; +} + +int upload_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password) +{ + subprocess_start(upload_file_task_function); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "task", "upload"); + blobmsg_add_string(&bbuf, "file_path", file_path); + blobmsg_add_string(&bbuf, "url", url); + blobmsg_add_string(&bbuf, "username", username); + blobmsg_add_string(&bbuf, "password", password); + char *upload_task = blobmsg_format_json(bbuf.head, true); + blob_buf_free(&bbuf); + + if (upload_task != NULL) { + char *ret = execute_task_in_subprocess(upload_task); + return atoi(ret); + } + return 500; +} + int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; @@ -156,7 +210,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans goto end_upload; } - int ret = upload_file(file_path, pupload->url, pupload->username, pupload->password); + int ret = upload_file_in_subprocess(file_path, pupload->url, pupload->username, pupload->password); if (ret == 200 || ret == 204) error = FAULT_CPE_NO_FAULT; else @@ -182,90 +236,6 @@ end_upload: return error; } -void *thread_cwmp_rpc_cpe_upload(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct upload *pupload; - struct timespec upload_timeout = { 0, 0 }; - time_t current_time, stime; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - long int time_of_grace = 3600, timeout; - - for (;;) { - - if (thread_end) - break; - - if (list_upload.next != &(list_upload)) { - pupload = list_entry(list_upload.next, struct upload, list); - stime = pupload->scheduled_time; - current_time = time(NULL); - if (pupload->scheduled_time != 0) - timeout = current_time - pupload->scheduled_time; - else - timeout = 0; - if ((timeout >= 0) && (timeout > time_of_grace)) { - pthread_mutex_lock(&mutex_upload); - bkp_session_delete_upload(pupload); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - if (ptransfer_complete != NULL) { - error = FAULT_CPE_DOWNLOAD_FAILURE; - - ptransfer_complete->command_key = strdup(pupload->command_key); - ptransfer_complete->start_time = strdup(get_time(time(NULL))); - ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time); - ptransfer_complete->fault_code = error; - ptransfer_complete->type = TYPE_UPLOAD; - bkp_session_insert_transfer_complete(ptransfer_complete); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - } - list_del(&(pupload->list)); - if (pupload->scheduled_time != 0) - count_download_queue--; - cwmp_free_upload_request(pupload); - pthread_mutex_unlock(&mutex_download); - continue; - } - if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - CWMP_LOG(INFO, "Launch upload file %s", pupload->url); - error = cwmp_launch_upload(pupload, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - bkp_session_delete_transfer_complete(ptransfer_complete); - ptransfer_complete->fault_code = error; - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - } - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_upload); - list_del(&(pupload->list)); - if (pupload->scheduled_time != 0) - count_download_queue--; - cwmp_free_upload_request(pupload); - pthread_mutex_unlock(&mutex_upload); - continue; - } - pthread_mutex_lock(&mutex_upload); - upload_timeout.tv_sec = stime; - pthread_cond_timedwait(&threshold_upload, &mutex_upload, &upload_timeout); - pthread_mutex_unlock(&mutex_upload); - } else { - pthread_mutex_lock(&mutex_upload); - pthread_cond_wait(&threshold_upload, &mutex_upload); - pthread_mutex_unlock(&mutex_upload); - } - } - return NULL; -} - int cwmp_free_upload_request(struct upload *upload) { if (upload != NULL) { @@ -291,7 +261,6 @@ int cwmp_free_upload_request(struct upload *upload) int cwmp_scheduledUpload_remove_all() { - pthread_mutex_lock(&mutex_upload); while (list_upload.next != &(list_upload)) { struct upload *upload; upload = list_entry(list_upload.next, struct upload, list); @@ -301,7 +270,49 @@ int cwmp_scheduledUpload_remove_all() count_download_queue--; cwmp_free_upload_request(upload); } - pthread_mutex_unlock(&mutex_upload); - return CWMP_OK; } + +void cwmp_start_upload(struct uloop_timeout *timeout) +{ + struct upload *pupload; + int error = FAULT_CPE_NO_FAULT; + struct transfer_complete *ptransfer_complete; + + pupload = container_of(timeout, struct upload, handler_timer); + + CWMP_LOG(INFO, "Launch download file %s", pupload->url); + error = cwmp_launch_upload(pupload, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while uploading the file: %s", pupload->url); + } + + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + list_del(&(pupload->list)); + if (pupload->scheduled_time != 0) + count_download_queue--; + cwmp_free_upload_request(pupload); + + struct session_timer_event *upload_inform_event = calloc(1, sizeof(struct session_timer_event)); + + upload_inform_event->extra_data = ptransfer_complete; + upload_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event; + upload_inform_event->event = TransferClt_Evt; + trigger_cwmp_session_timer_with_event(&upload_inform_event->session_timer_evt); +} + +void apply_upload() +{ + struct list_head *ilist; + list_for_each (ilist, &(list_upload)) { + struct download *upload = list_entry(ilist, struct download, list); + int upload_delay = 0; + if (upload->scheduled_time > time(NULL)) { + upload_delay = upload->scheduled_time - time(NULL); + } + uloop_timeout_set(&upload->handler_timer, 1000 * upload_delay); + } +} diff --git a/src/upload.h b/src/upload.h index 3f05215..37964ed 100644 --- a/src/upload.h +++ b/src/upload.h @@ -15,11 +15,11 @@ #include "common.h" extern struct list_head list_upload; -extern pthread_mutex_t mutex_upload; -extern pthread_cond_t threshold_upload; int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete); void *thread_cwmp_rpc_cpe_upload(void *v); int cwmp_scheduledUpload_remove_all(); int cwmp_free_upload_request(struct upload *upload); +void cwmp_start_upload(struct uloop_timeout *timeout); +void apply_upload(); #endif diff --git a/src/xml.c b/src/xml.c index 0e5f2c0..542aeb0 100644 --- a/src/xml.c +++ b/src/xml.c @@ -52,7 +52,7 @@ struct xml_node_data xml_nodes_data[] = { [SOAP_TIMEWINDOW_REF] = {XML_LIST, SOAP_TIME_REF, NULL, {}}, [SOAP_TIME_REF] = {XML_SINGLE, 0, NULL, {{"WindowStart", XML_LINTEGER, 0, NULL}, {"WindowEnd", XML_LINTEGER, 0, NULL}, {"WindowMode", XML_STRING, 0, NULL}, {"WindowMode", XML_FUNC, 0, load_sched_download_window_mode}, {"MaxRetries", XML_INTEGER, 0, NULL}}}, [SOAP_REQ_CDU_OPERATIONS] = {XML_LIST, SOAP_REQ_CDU_OPS_REF, "Operations", {}}, - [SOAP_REQ_CDU_OPS_REF] = {XML_SINGLE, 0, NULL, {{"Operations", XML_FUNC, 0, NULL}}}, + [SOAP_REQ_CDU_OPS_REF] = {XML_SINGLE, 0, NULL, {{"Operations", XML_FUNC, 0, load_change_du_state_operation}}}, [SOAP_REQ_DU_INSTALL] = {XML_SINGLE, 0, NULL, {{"URL", XML_STRING, 0, NULL}, {"UUID", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"ExecutionEnvRef", XML_STRING, 0, NULL}}}, [SOAP_REQ_DU_UPDATE] = {XML_SINGLE, 0, NULL, {{"URL", XML_STRING, 0, NULL}, {"UUID", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"Version", XML_STRING, 0, NULL}}}, [SOAP_REQ_DU_UNINSTALL] = {XML_SINGLE, 0, NULL, {{"Version", XML_STRING, 0, NULL}, {"ExecutionEnvRef", XML_STRING, 0, NULL}, {"URL", XML_STRING, 0, NULL}}}, @@ -88,7 +88,7 @@ struct xml_node_data xml_nodes_data[] = { [SOAP_INFORM_CWMP] = {XML_SINGLE, 0, NULL, {{"DeviceId", XML_REC, SOAP_DEVID, NULL}, {"Event", XML_FUNC, 0, build_inform_events}, {"MaxEnvelopes", XML_INTEGER, 0, NULL}, {"CurrentTime", XML_STRING, 0, NULL}, {"RetryCount", XML_INTEGER, 0, NULL}}}, [SOAP_DEVID] = {XML_SINGLE, 0, NULL, {{"Manufacturer", XML_STRING, 0, NULL}, {"OUI", XML_STRING, 0, NULL}, {"ProductClass", XML_STRING, 0, NULL}, {"SerialNumber", XML_STRING, 0, NULL}}}, [SOAP_DU_CHANGE_COMPLETE] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"Results", XML_REC, SOAP_CDU_RESULTS_REF, NULL}}}, - [SOAP_CDU_RESULTS_REF] = {XML_LIST, 0, NULL, {{"OpResultStruct", XML_REC, SOAP_CDU_OPTS_REF, NULL}}}, + [SOAP_CDU_RESULTS_REF] = {XML_LIST, SOAP_CDU_OPTS_REF, "OpResultStruct", {}}, [SOAP_CDU_OPTS_REF] = {XML_SINGLE, 0, NULL, {{"UUID", XML_STRING, 0, NULL}, {"DeploymentUnitRef", XML_STRING, 0, NULL}, {"Version", XML_STRING, 0, NULL}, {"CurrentState", XML_STRING, 0, NULL}, {"StartTime", XML_STRING, 0, NULL}, {"CompleteTime", XML_STRING, 0, NULL}, {"FaultStruct", XML_REC, SOAP_CWMP_FAULT, NULL}}}, [ATTR_PARAM_STRUCT] = {XML_SINGLE, 0, NULL, {{"xsi:type", XML_STRING, 0, NULL}}}, [ATTR_SOAP_ENV] = {XML_SINGLE, 0, NULL, {{"xmlns:soap_env", XML_STRING, 0, NULL}, {"xmlns:soap_enc", XML_STRING, 0, NULL}, {"xmlns:xsd", XML_STRING, 0, NULL}, {"xmlns:xsi", XML_STRING, 0, NULL}}} @@ -253,30 +253,33 @@ int load_change_du_state_operation(mxml_node_t *b, struct xml_data_struct *xml_a int cdu_ref = 0; int type = 0; + if (xml_attrs->cdu_type == NULL) { + CWMP_LOG(ERROR, "Not able to load CDU operation"); + return FAULT_CPE_INTERNAL_ERROR; + + } if (strcmp(operation, "cwmp:InstallOpStruct") == 0) { cdu_ref = SOAP_REQ_DU_INSTALL; type = DU_INSTALL; } else if (strcmp(operation, "cwmp:UpdateOpStruct") == 0) { - cdu_ref = SOAP_REQ_DU_INSTALL; + cdu_ref = SOAP_REQ_DU_UPDATE; type = DU_UPDATE; } + else if (strcmp(operation, "cwmp:UninstallOpStruct") == 0) { - cdu_ref = SOAP_REQ_DU_INSTALL; + cdu_ref = SOAP_REQ_DU_UNINSTALL; type = DU_UNINSTALL; } - // cppcheck-suppress autoVariables - xml_attrs->cdu_type = &type; + *(xml_attrs->cdu_type) = type; if (cdu_ref == 0) return FAULT_CPE_INVALID_ARGUMENTS; - int fault = load_xml_node_data(cdu_ref, b, xml_attrs); if (fault) return fault; - return FAULT_CPE_NO_FAULT; } @@ -572,7 +575,6 @@ int load_single_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_s default: break; } - } b = mxmlWalkNext(b, node, MXML_DESCEND); } @@ -681,6 +683,11 @@ void event_container_list_to_xml_data_list(struct list_head *event_container_lis struct event_container *event_container; list_for_each_entry (event_container, event_container_list, list) { + // cppcheck-suppress uninitvar + if (cwmp_main->session->session_status.is_heartbeat && event_container->code != EVENT_IDX_14HEARTBEAT) + continue; + if ((!cwmp_main->session->session_status.is_heartbeat) && (event_container->code == EVENT_IDX_14HEARTBEAT)) + continue; struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data)); list_add_tail(&xml_data->list, xml_data_list); xml_data->event_code = event_container->code; @@ -695,7 +702,6 @@ void get_xml_data_value_by_name(int type, int idx, struct xml_data_struct *xml_a bool *bol; long int *lint; time_t *time; - void **ptr = (void **)((char *)xml_attrs + idx * sizeof(char *)); switch(type) { case XML_STRING: @@ -820,6 +826,10 @@ int build_xml_list_node_data(int node_ref, mxml_node_t *node, struct xml_data_st xml_ref_data.fault_code = &xml_data->fault_code; xml_ref_data.current_state = &xml_data->current_state; xml_ref_data.du_ref = &xml_data->du_ref; + xml_ref_data.uuid = &xml_data->uuid; + xml_ref_data.version = &xml_data->version; + xml_ref_data.start_time = &xml_data->start_time; + xml_ref_data.complete_time = &xml_data->complete_time; int fault = build_xml_node_data(xml_nodes_data[node_ref].tag_node_ref, n, &xml_ref_data); @@ -925,7 +935,6 @@ int xml_recreate_namespace(mxml_node_t *tree) FREE(ns.xsd); FREE(ns.xsi); FREE(ns.cwmp); - if (tree) { do { char *c; @@ -957,7 +966,6 @@ int xml_recreate_namespace(mxml_node_t *tree) int i; for (i = 0; cwmp_urls[i] != NULL; i++) { const char *cwmp_urn = cwmp_urls[i]; - c = (char *)xml__get_attribute_name_by_value(b, cwmp_urn); if (c && *(c + 5) == ':') { FREE(ns.cwmp); @@ -966,10 +974,10 @@ int xml_recreate_namespace(mxml_node_t *tree) } } + if (ns.cwmp && ns.soap_env && ns.xsd && ns.soap_enc && ns.xsi) + return 0; } while ((b = mxmlWalkNext(b, tree, MXML_DESCEND))); - return 0; } - return -1; } @@ -982,20 +990,19 @@ void xml_exit(void) FREE(ns.cwmp); } -int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int xml_send_message(struct rpc *rpc) { char *s, *msg_out = NULL, *msg_in = NULL; char c[512]; int msg_out_len = 0, f, r = 0; mxml_node_t *b; - if (session->tree_out) { + if (cwmp_main->session->tree_out) { unsigned char *zmsg_out; - msg_out = mxmlSaveAllocString(session->tree_out, whitespace_cb); + msg_out = mxmlSaveAllocString(cwmp_main->session->tree_out, whitespace_cb); CWMP_LOG_XML_MSG(DEBUG, msg_out, XML_MSG_OUT); - if (cwmp->conf.compression != COMP_NONE) { - if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp->conf.compression)) { - CWMP_LOG(ERROR,"zlib_compress failed"); + if (cwmp_main->conf.compression != COMP_NONE) { + if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp_main->conf.compression)) { return -1; } FREE(msg_out); @@ -1006,8 +1013,7 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc } while (1) { f = 0; - if (icwmp_http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) { - CWMP_LOG(ERROR,"Failed to icwmp_http_send_message"); + if (icwmp_http_send_message(msg_out, msg_out_len, &msg_in)) { goto error; } if (msg_in) { @@ -1035,34 +1041,32 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc } } - session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK); - if (!session->tree_in) + cwmp_main->session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK); + if (!cwmp_main->session->tree_in) goto error; - - if (xml_recreate_namespace(session->tree_in) == -1) { + if (xml_recreate_namespace(cwmp_main->session->tree_in) == -1) { CWMP_LOG(ERROR, "Failed to get ns parameters"); goto error; } - /* get NoMoreRequests or HolRequest*/ - session->hold_request = false; + cwmp_main->session->hold_request = false; if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "NoMoreRequests") == -1) goto error; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b)) - session->hold_request = atoi(mxmlGetOpaque(b)); + cwmp_main->session->hold_request = atoi(mxmlGetOpaque(b)); } else { if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "HoldRequests") == -1) goto error; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b)) - session->hold_request = atoi(mxmlGetOpaque(b)); + cwmp_main->session->hold_request = atoi(mxmlGetOpaque(b)); } } @@ -1077,39 +1081,37 @@ error: return -1; } -int xml_prepare_msg_out(struct session *session) +int xml_prepare_msg_out() { - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); mxml_node_t *n; - load_response_xml_schema(&session->tree_out); - if (!session->tree_out) + load_response_xml_schema(&cwmp_main->session->tree_out); + if (!cwmp_main->session->tree_out) return -1; - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) { return -1; } mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(conf->amd_version) - 1]); - if (!session->tree_out) + if (!cwmp_main->session->tree_out) return -1; return 0; } -int xml_set_cwmp_id(struct session *session) +int xml_set_cwmp_id() { char c[32]; mxml_node_t *b; /* define cwmp id */ - if (snprintf(c, sizeof(c), "%u", ++(cwmp_main.cwmp_id)) == -1) + if (snprintf(c, sizeof(c), "%u", ++(cwmp_main->cwmp_id)) == -1) return -1; - b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); if (!b) return -1; @@ -1120,7 +1122,7 @@ int xml_set_cwmp_id(struct session *session) return 0; } -int xml_set_cwmp_id_rpc_cpe(struct session *session) +int xml_set_cwmp_id_rpc_cpe() { char c[512]; mxml_node_t *b; @@ -1129,16 +1131,16 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session) if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ID") == -1) return -1; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { /* ACS send ID parameter */ - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b)) return 0; snprintf(c, sizeof(c), "%s", mxmlGetOpaque(b)); - b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); if (!b) return -1; @@ -1147,7 +1149,7 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session) return -1; } else { /* ACS does not send ID parameter */ - int r = xml_set_cwmp_id(session); + int r = xml_set_cwmp_id(); return r; } return 0; @@ -1269,9 +1271,7 @@ error: void load_notification_xml_schema(mxml_node_t **tree) { char declaration[1024] = {0}; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); char *c = NULL; if (tree == NULL) @@ -1351,7 +1351,7 @@ void load_notification_xml_schema(mxml_node_t **tree) return; } - if (NULL == mxmlNewOpaque(oui, cwmp->deviceid.oui)) { + if (NULL == mxmlNewOpaque(oui, cwmp_main->deviceid.oui)) { MXML_DELETE(xml); return; } @@ -1362,7 +1362,7 @@ void load_notification_xml_schema(mxml_node_t **tree) return; } - if (NULL == mxmlNewOpaque(pclass, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "")) { + if (NULL == mxmlNewOpaque(pclass, cwmp_main->deviceid.productclass ? cwmp_main->deviceid.productclass : "")) { MXML_DELETE(xml); return; } @@ -1373,7 +1373,7 @@ void load_notification_xml_schema(mxml_node_t **tree) return; } - if (NULL == mxmlNewOpaque(slno, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "")) { + if (NULL == mxmlNewOpaque(slno, cwmp_main->deviceid.serialnumber ? cwmp_main->deviceid.serialnumber : "")) { MXML_DELETE(xml); return; } diff --git a/src/xml.h b/src/xml.h index 7d2c134..3b947b1 100644 --- a/src/xml.h +++ b/src/xml.h @@ -1,7 +1,7 @@ #ifndef __XML__H_ #define __XML__H_ -#include "xml_utils.h" +#include #include "session.h" #include "common.h" @@ -221,13 +221,13 @@ struct xml_node_data { } while (0) extern const char *cwmp_urls[]; -int xml_prepare_msg_out(struct session *session); +int xml_prepare_msg_out(); int xml_prepare_lwnotification_message(char **msg_out); -int xml_set_cwmp_id_rpc_cpe(struct session *session); +int xml_set_cwmp_id_rpc_cpe(); int xml_recreate_namespace(mxml_node_t *tree); const char *whitespace_cb(mxml_node_t *node, int where); -int xml_set_cwmp_id(struct session *session); -int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc); +int xml_set_cwmp_id(); +int xml_send_message(struct rpc *rpc); mxml_node_t *mxmlFindElementOpaque(mxml_node_t *node, mxml_node_t *top, const char *text, int descend); char *xml__get_attribute_name_by_value(mxml_node_t *node, const char *value); char *xml_get_cwmp_version(int version); diff --git a/src/xml_utils.h b/src/xml_utils.h deleted file mode 100644 index 75dd216..0000000 --- a/src/xml_utils.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __XML_UTILS -#define __XML_UTILS -#include - -#endif diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile index 778e50e..3f6583b 100644 --- a/test/cmocka/Makefile +++ b/test/cmocka/Makefile @@ -1,7 +1,7 @@ -LIB_LDFLAGS:= -luci -lblobmsg_json -lubox\ +LIB_LDFLAGS:= -lmxml -luci -lblobmsg_json -lubox\ -ljson-c -lubus -lpthread -lcurl\ - -lcrypto -lmxml + -lcrypto LIB_CFLAGS:= -fPIC -I../../ -DLOPENSSL -g -O0 UNIT_TESTS:= icwmp_unit_testd diff --git a/test/cmocka/icwmp_backup_session_unit_test.c b/test/cmocka/icwmp_backup_session_unit_test.c index 6d57ac0..a3c57e1 100644 --- a/test/cmocka/icwmp_backup_session_unit_test.c +++ b/test/cmocka/icwmp_backup_session_unit_test.c @@ -23,22 +23,30 @@ static struct cwmp cwmp_main_test = { 0 }; +static int bkp_session_unit_tests_init(void **state) +{ + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + return 0; +} + static int bkp_session_unit_tests_clean(void **state) { icwmp_cleanmem(); + clean_cwmp_session_structure(); + FREE(cwmp_main); return 0; } static void cwmp_backup_session_unit_test(void **state) { remove(CWMP_BKP_FILE); - struct cwmp *cwmp_test = &cwmp_main_test; mxml_node_t *backup_tree = NULL, *n = NULL; /* * Init backup session */ - int error = cwmp_init_backup_session(cwmp_test, NULL, ALL); + int error = cwmp_init_backup_session(NULL, ALL); assert_int_equal(error, 0); bkp_session_save(); FILE *pFile; @@ -270,5 +278,5 @@ int icwmp_backup_session_test(void) cmocka_unit_test(cwmp_backup_session_unit_test), }; - return cmocka_run_group_tests(tests, NULL, bkp_session_unit_tests_clean); + return cmocka_run_group_tests(tests, bkp_session_unit_tests_init, bkp_session_unit_tests_clean); } diff --git a/test/cmocka/icwmp_cli_unit_test.c b/test/cmocka/icwmp_cli_unit_test.c index 3e8713b..9de89e7 100644 --- a/test/cmocka/icwmp_cli_unit_test.c +++ b/test/cmocka/icwmp_cli_unit_test.c @@ -50,17 +50,20 @@ static void restore_output() static int cwmp_cli_unit_tests_init(void **state) { - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); return 0; } static int cwmp_cli_unit_tests_clean(void **state) { - icwmp_cleanmem(); - FREE(add_instance); icwmp_free_list_services(); - cwmp_uci_exit(); - + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); + FREE(add_instance); return 0; } diff --git a/test/cmocka/icwmp_datamodel_interface_unit_test.c b/test/cmocka/icwmp_datamodel_interface_unit_test.c index d4009f6..5dccb34 100644 --- a/test/cmocka/icwmp_datamodel_interface_unit_test.c +++ b/test/cmocka/icwmp_datamodel_interface_unit_test.c @@ -23,9 +23,45 @@ #include "session.h" #include "log.h" +static LIST_HEAD(list_set_param_value); +static LIST_HEAD(faults_array); +static LIST_HEAD(parameters_list); + +static int dm_iface_unit_tests_init(void **state) +{ + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + cwmp_session_init(); + global_conf_init(); + return 0; +} + static int dm_iface_unit_tests_clean(void **state) { - icwmp_cleanmem(); + icwmp_free_list_services(); + clean_cwmp_session_structure(); + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.custom_notify_json); + FREE(cwmp_main); + cwmp_free_all_list_param_fault(&faults_array); + cwmp_free_all_dm_parameter_list(&list_set_param_value); + cwmp_session_exit(); return 0; } @@ -35,7 +71,6 @@ static int dm_iface_unit_tests_clean(void **state) static void dm_get_parameter_values_test(void **state) { char *fault = NULL; - LIST_HEAD(parameters_list); /* * Test of valid parameter path */ @@ -89,8 +124,6 @@ static void dm_set_multiple_parameter_values_test(void **state) int fault_code = 0; char *fault_name = NULL; struct cwmp_param_fault *param_fault = NULL; - LIST_HEAD(list_set_param_value); - LIST_HEAD(faults_array); /* * Test of one valid parameter @@ -194,6 +227,7 @@ static void dm_set_multiple_parameter_values_test(void **state) assert_int_equal(fault, 0); assert_in_set(flag, flag_values, 15); cwmp_transaction_commit(); + cwmp_free_all_list_param_fault(&faults_array); cwmp_free_all_dm_parameter_list(&list_set_param_value); /* @@ -285,7 +319,6 @@ static void dm_delete_object_test(void **state) static void dm_get_parameter_names_test(void **state) { char *fault = NULL; - LIST_HEAD(parameters_list); /* * Valid multi-instance object path @@ -331,5 +364,5 @@ int icwmp_datamodel_interface_test(void) cmocka_unit_test(dm_get_parameter_names_test), }; - return cmocka_run_group_tests(tests, NULL, dm_iface_unit_tests_clean); + return cmocka_run_group_tests(tests, dm_iface_unit_tests_init, dm_iface_unit_tests_clean); } diff --git a/test/cmocka/icwmp_notifications_unit_test.c b/test/cmocka/icwmp_notifications_unit_test.c index 8ebe930..baeaab3 100644 --- a/test/cmocka/icwmp_notifications_unit_test.c +++ b/test/cmocka/icwmp_notifications_unit_test.c @@ -17,6 +17,8 @@ #include "common.h" #include "notifications.h" #include "cwmp_uci.h" +#include "session.h" + /* * Common functions */ @@ -26,15 +28,21 @@ LIST_HEAD(parameters_list); static int cwmp_notifications_unit_tests_init(void **state) { - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); return 0; } static int cwmp_notifications_unit_tests_clean(void **state) { - icwmp_cleanmem(); + clean_list_param_notify(); + clean_list_value_change(); cwmp_free_all_dm_parameter_list(¶meters_list); - cwmp_uci_exit(); + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); return 0; } @@ -264,6 +272,7 @@ static void cwmp_check_value_change_1_unit_test(void **state) assert_int_equal((int)list_empty(&list_value_change), 0); assert_int_equal((int)list_empty(&list_lw_value_change), 1); assert_int_equal(get_parameter_in_list_value_change("Device.DeviceInfo.UpTime"), 1); + clean_list_value_change(); } int icwmp_notifications_test(void) diff --git a/test/cmocka/icwmp_soap_msg_unit_test.c b/test/cmocka/icwmp_soap_msg_unit_test.c index 3e0faad..7a3fbb9 100644 --- a/test/cmocka/icwmp_soap_msg_unit_test.c +++ b/test/cmocka/icwmp_soap_msg_unit_test.c @@ -27,10 +27,8 @@ #include "xml.h" #include "icwmp_soap_msg_unit_test.h" +#include "cwmp_event.h" -static struct cwmp cwmp_main_test = { 0 }; -static struct cwmp *cwmp_test; -static struct session *session_test = NULL; static int instance = 0; #define INVALID_PARAM_KEY "ParameterKeyParameterKeyParameter" @@ -41,23 +39,23 @@ static int instance = 0; */ static void clean_config() { - FREE(cwmp_test->deviceid.manufacturer); - FREE(cwmp_test->deviceid.serialnumber); - FREE(cwmp_test->deviceid.productclass); - FREE(cwmp_test->deviceid.oui); - FREE(cwmp_test->deviceid.softwareversion); - FREE(cwmp_test->conf.lw_notification_hostname); - FREE(cwmp_test->conf.ip); - FREE(cwmp_test->conf.ipv6); - FREE(cwmp_test->conf.acsurl); - FREE(cwmp_test->conf.acs_userid); - FREE(cwmp_test->conf.acs_passwd); - FREE(cwmp_test->conf.interface); - FREE(cwmp_test->conf.cpe_userid); - FREE(cwmp_test->conf.cpe_passwd); - FREE(cwmp_test->conf.ubus_socket); - FREE(cwmp_test->conf.connection_request_path); - FREE(cwmp_test->conf.default_wan_iface); + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); } static void clean_name_space() @@ -69,11 +67,11 @@ static void clean_name_space() FREE(ns.cwmp); } -static void unit_test_remove_all_events_by_session(struct session *session) +static void unit_test_remove_all_session_events() { - while (session->head_event_container.next != &(session->head_event_container)) { + while (cwmp_main->session->events.next != &(cwmp_main->session->events)) { struct event_container *event_container; - event_container = list_entry(session->head_event_container.next, struct event_container, list); + event_container = list_entry(cwmp_main->session->events.next, struct event_container, list); free(event_container->command_key); cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); list_del(&(event_container->list)); @@ -83,12 +81,7 @@ static void unit_test_remove_all_events_by_session(struct session *session) static void unit_test_end_test_destruction() { - struct session *session = NULL; - while (cwmp_test->head_session_queue.next != &(cwmp_test->head_session_queue)) { - session = list_entry(cwmp_test->head_session_queue.next, struct session, list); - unit_test_remove_all_events_by_session(session); - cwmp_session_destructor(session); - } + unit_test_remove_all_session_events(); } /* @@ -96,28 +89,22 @@ static void unit_test_end_test_destruction() */ static int soap_unit_tests_init(void **state) { - cwmp_test = &cwmp_main_test; - INIT_LIST_HEAD(&(cwmp_test->head_session_queue)); - memcpy(&(cwmp_test->env), &cwmp_test, sizeof(struct env)); - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); log_set_severity_idx("DEBUG"); return 0; } static int soap_unit_tests_clean(void **state) { - icwmp_cleanmem(); - if (session_test != NULL) { - MXML_DELETE(session_test->tree_in); - MXML_DELETE(session_test->tree_out); - session_test->head_rpc_acs.next = NULL; - session_test->head_rpc_cpe.next = NULL; - cwmp_session_destructor(session_test); - } icwmp_free_list_services(); clean_name_space(); clean_config(); - cwmp_uci_exit(); + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); return 0; } @@ -126,51 +113,34 @@ static int soap_unit_tests_clean(void **state) */ static void get_config_test(void **state) { - int error = get_preinit_config(&(cwmp_test->conf)); + int error = get_preinit_config(); assert_int_equal(error, CWMP_OK); - error = get_global_config(&(cwmp_test->conf)); + error = get_global_config(); } static void get_deviceid_test(void **state) { - int error = cwmp_get_deviceid(cwmp_test); + int error = cwmp_get_deviceid(); assert_int_equal(error, CWMP_OK); } static void add_event_test(void **state) { struct event_container *event_container; - event_container = cwmp_add_event_container(cwmp_test, EVENT_IDX_1BOOT, ""); + event_container = cwmp_add_event_container(EVENT_IDX_1BOOT, ""); assert_non_null(event_container); assert_string_equal(EVENT_CONST[event_container->code].CODE, "1 BOOT"); } -static int create_session(struct session **session) -{ - *session = calloc(1, sizeof(struct session)); - if (*session == NULL) - return 0; - - list_add_tail(&((*session)->list), &(cwmp_test->head_session_queue)); - - INIT_LIST_HEAD(&((*session)->head_event_container)); - *session = list_entry((&(cwmp_test->head_session_queue))->next, struct session, list); - return 1; -} - static void soap_inform_message_test(void **state) { mxml_node_t *env = NULL, *n = NULL, *device_id = NULL, *cwmp_inform = NULL; - struct session *session = NULL; struct rpc *rpc_acs; - create_session(&session); - session_test = session; - rpc_acs = list_entry(&(session->head_rpc_acs), struct rpc, list); + rpc_acs = list_entry(&(cwmp_main->session->head_rpc_acs), struct rpc, list); + cwmp_rpc_acs_prepare_message_inform(rpc_acs); - cwmp_rpc_acs_prepare_message_inform(cwmp_test, session, rpc_acs); - - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -200,33 +170,32 @@ static void soap_inform_message_test(void **state) n = mxmlFindElement(cwmp_inform, cwmp_inform, "ParameterList", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); unit_test_end_test_destruction(); clean_config(); - session_test = NULL; } -static void prepare_session_for_rpc_method_call(struct session *session) +static void prepare_session_for_rpc_method_call() { mxml_node_t *b; char *c; icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body"); - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); - session->body_in = b; - xml_prepare_msg_out(session); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); + cwmp_main->session->body_in = b; + xml_prepare_msg_out(); } -static void prepare_gpv_soap_request(struct session *session, char *parameters[], int len) +static void prepare_gpv_soap_request(char *parameters[], int len) { mxml_node_t *params = NULL, *n = NULL; int i; - session->tree_in = mxmlLoadString(NULL, CWMP_GETPARAMETERVALUES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - params = mxmlFindElement(session->tree_in, session->tree_in, "ParameterNames", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_GETPARAMETERVALUES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + params = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "ParameterNames", NULL, NULL, MXML_DESCEND); for (i = 0; i < len; i++) { n = mxmlNewElement(params, "string"); n = mxmlNewOpaque(n, parameters[i]); @@ -235,27 +204,23 @@ static void prepare_gpv_soap_request(struct session *session, char *parameters[] static void soap_get_param_value_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *name = NULL, *value = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid parameter path */ char *valid_parameters[1] = { "Device.ManagementServer.PeriodicInformEnable" }; - prepare_gpv_soap_request(session, valid_parameters, 1); + prepare_gpv_soap_request(valid_parameters, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -276,8 +241,8 @@ static void soap_get_param_value_message_test(void **state) value = mxmlFindElement(n, n, "Value", NULL, NULL, MXML_DESCEND); assert_non_null(value); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong parameter path @@ -285,14 +250,14 @@ static void soap_get_param_value_message_test(void **state) mxml_node_t *fault_code = NULL, *fault_string = NULL, *detail = NULL, *detail_code = NULL, *detail_string = NULL; char *invalid_parameter[1] = { "Device.ManagementServereriodicInformEnable" }; - prepare_gpv_soap_request(session, invalid_parameter, 1); + prepare_gpv_soap_request(invalid_parameter, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -316,22 +281,21 @@ static void soap_get_param_value_message_test(void **state) detail_string = mxmlFindElement(detail, detail, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(detail_string); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - session->head_rpc_acs.next = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } -static void prepare_addobj_soap_request(struct session *session, char *object, char *parameter_key) +static void prepare_addobj_soap_request(char *object, char *parameter_key) { mxml_node_t *add_node = NULL, *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_ADDOBJECT_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - add_node = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:AddObject", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_ADDOBJECT_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + add_node = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:AddObject", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(add_node, add_node, "ObjectName", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, object); n = mxmlFindElement(add_node, add_node, "ParameterKey", NULL, NULL, MXML_DESCEND); @@ -340,23 +304,20 @@ static void prepare_addobj_soap_request(struct session *session, char *object, c static void soap_add_object_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *add_resp = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path & writable object */ - prepare_addobj_soap_request(session, "Device.WiFi.SSID.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSID.", "add_object_test"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -372,21 +333,21 @@ static void soap_add_object_message_test(void **state) n = mxmlFindElement(add_resp, add_resp, "Status", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "1"); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong object path */ mxml_node_t *cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.WiFi.SSI.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSI.", "add_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -405,20 +366,20 @@ static void soap_add_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not writable & Valid object path */ cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.DeviceInfo.Processor.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.DeviceInfo.Processor.", "add_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -437,20 +398,20 @@ static void soap_add_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid parameterkey */ cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.WiFi.SSID.", INVALID_PARAM_KEY); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSID.", INVALID_PARAM_KEY); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -469,22 +430,21 @@ static void soap_add_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9003"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } -static void prepare_delobj_soap_request(struct session *session, char *object, char *parameter_key) +static void prepare_delobj_soap_request(char *object, char *parameter_key) { mxml_node_t *del_node = NULL, *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_DELOBJECT_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - del_node = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:DeleteObject", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_DELOBJECT_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + del_node = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:DeleteObject", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(del_node, del_node, "ObjectName", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, object); n = mxmlFindElement(del_node, del_node, "ParameterKey", NULL, NULL, MXML_DESCEND); @@ -493,26 +453,22 @@ static void prepare_delobj_soap_request(struct session *session, char *object, c static void soap_delete_object_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *add_resp = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path & writable object */ char del_obj[32]; snprintf(del_obj, sizeof(del_obj), "Device.WiFi.SSID.%d.", instance); - prepare_delobj_soap_request(session, del_obj, "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request(del_obj, "del_object_test"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -525,21 +481,21 @@ static void soap_delete_object_message_test(void **state) n = mxmlFindElement(add_resp, add_resp, "Status", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "1"); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong object path */ mxml_node_t *cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.WiFi.SID.1", "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.WiFi.SID.1", "del_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -558,20 +514,20 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not writable & Valid object path */ cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.DeviceInfo.Processor.2.", "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.DeviceInfo.Processor.2.", "del_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -590,20 +546,20 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid parameterkey */ cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.WiFi.SSID.1.", INVALID_PARAM_KEY); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.WiFi.SSID.1.", INVALID_PARAM_KEY); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -622,22 +578,21 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(n)), "9003"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } -static void prepare_gpa_soap_request(struct session *session, char *parameter) +static void prepare_gpa_soap_request(char *parameter) { mxml_node_t *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_GETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - n = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:GetParameterAttributes", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_GETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:GetParameterAttributes", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(n, n, "ParameterNames", NULL, NULL, MXML_DESCEND); n = mxmlNewElement(n, "string"); n = mxmlNewOpaque(n, parameter); @@ -645,25 +600,21 @@ static void prepare_gpa_soap_request(struct session *session, char *parameter) static void soap_get_parameter_attributes_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *param_attr = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path */ - prepare_gpa_soap_request(session, "Device.DeviceInfo.UpTime"); - prepare_session_for_rpc_method_call(session); + prepare_gpa_soap_request("Device.DeviceInfo.UpTime"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_get_parameter_attributes(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_get_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -685,8 +636,8 @@ static void soap_get_parameter_attributes_message_test(void **state) n = mxmlFindElement(param_attr, param_attr, "AccessList", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid path @@ -694,14 +645,14 @@ static void soap_get_parameter_attributes_message_test(void **state) mxml_node_t *fault_code = NULL, *fault_string = NULL, *detail = NULL, *detail_code = NULL, *detail_string = NULL; char *invalid_parameter[1] = { "Device.DeviceInfo.pTime" }; - prepare_gpv_soap_request(session, invalid_parameter, 1); + prepare_gpv_soap_request(invalid_parameter, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -724,22 +675,21 @@ static void soap_get_parameter_attributes_message_test(void **state) assert_string_equal(mxmlGetOpaque(mxmlGetFirstChild(detail_code)), "9005"); detail_string = mxmlFindElement(detail, detail, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(detail_string); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } -static void prepare_spa_soap_request(struct session *session, char *parameter, char *notification, char *notification_change) +static void prepare_spa_soap_request(char *parameter, char *notification, char *notification_change) { mxml_node_t *n = NULL, *set_attr = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_SETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - set_attr = mxmlFindElement(session->tree_in, session->tree_in, "SetParameterAttributesStruct", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_SETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + set_attr = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "SetParameterAttributesStruct", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(set_attr, set_attr, "Name", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, parameter); n = mxmlFindElement(set_attr, set_attr, "Notification", NULL, NULL, MXML_DESCEND); @@ -750,25 +700,21 @@ static void prepare_spa_soap_request(struct session *session, char *parameter, c static void soap_set_parameter_attributes_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "1", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "1", "true"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -779,20 +725,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(n, n, "cwmp:SetParameterAttributesResponse", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_null(mxmlGetFirstChild(n)); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid path */ mxml_node_t *cwmp_fault = NULL; - prepare_spa_soap_request(session, "Device.DeviceInfo.pTime", "1", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.pTime", "1", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -812,19 +758,19 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid Notification value */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "8", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "8", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -844,20 +790,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid Notification String */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "balabala", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "balabala", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -877,20 +823,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid NotificationChange */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "2", "5"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "2", "5"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -910,13 +856,12 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } int icwmp_soap_msg_test(void) diff --git a/test/files/etc/config/cwmp b/test/files/etc/config/cwmp index 30086d5..7ef4ab4 100644 --- a/test/files/etc/config/cwmp +++ b/test/files/etc/config/cwmp @@ -13,6 +13,7 @@ config acs 'acs' option retry_interval_multiplier '2000' option ipv6_enable '0' option ip_version '4' + config cpe 'cpe' option enable '1' diff --git a/test/files/usr/libexec/rpcd/rpc-sys b/test/files/usr/libexec/rpcd/rpc-sys index b525dbb..34b61ce 100755 --- a/test/files/usr/libexec/rpcd/rpc-sys +++ b/test/files/usr/libexec/rpcd/rpc-sys @@ -18,6 +18,8 @@ case "$1" in ;; upgrade_start) cat /tmp/rpc_sys.data 2>/dev/null + sleep 7 + supervisorctl stop icwmpd >> ./funl-test-debug.log ;; esac ;; diff --git a/test/script/test_seq.txt b/test/script/test_seq.txt new file mode 100644 index 0000000..9bf01ec --- /dev/null +++ b/test/script/test_seq.txt @@ -0,0 +1,7 @@ +verify_download_method.sh +verify_add_method.sh +verify_delete_method.sh +verify_get_method.sh +verify_set_method.sh +verify_cmd_line.sh + diff --git a/test/script/verify_download_method.sh b/test/script/verify_download_method.sh index 2f81637..4d02ea4 100755 --- a/test/script/verify_download_method.sh +++ b/test/script/verify_download_method.sh @@ -23,7 +23,9 @@ fi remove_icwmp_log echo "Restarting icwmpd in order to apply the new firmware" >> ./funl-test-debug.log supervisorctl stop icwmpd >> ./funl-test-debug.log -check_valgrind_xml +sleep 20 +cp memory-report.xml memory-report-download.xml +#check_valgrind_xml supervisorctl start icwmpd >> ./funl-test-debug.log check_cwmp_status sleep 5