Ticket refs #6914: icwmp: migrate from multithreading to uloop

This commit is contained in:
Omar Kallel 2022-09-08 16:10:24 +01:00
parent 19a3ba5412
commit 34499c1cb3
59 changed files with 2988 additions and 3314 deletions

2
.gitignore vendored
View file

@ -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

View file

@ -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

View file

@ -8,21 +8,6 @@ pwd
trap cleanup EXIT
trap cleanup SIGINT
function check_valgrind_xml() {
echo "Checking memory leaks..."
grep -q "<kind>UninitCondition</kind>" memory-report.xml
error_on_zero $?
grep -q "<kind>Leak_PossiblyLost</kind>" memory-report.xml
error_on_zero $?
grep -q "<kind>Leak_DefinitelyLost</kind>" memory-report.xml
error_on_zero $?
grep -q "<kind>Leak_StillReachable</kind>" 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"

View file

@ -148,15 +148,19 @@ function install_uspd()
function check_valgrind_xml() {
echo "Checking memory leaks..."
echo "checking UninitCondition"
grep -q "<kind>UninitCondition</kind>" memory-report.xml
error_on_zero $?
echo "checking Leak_PossiblyLost"
grep -q "<kind>Leak_PossiblyLost</kind>" memory-report.xml
error_on_zero $?
echo "checking Leak_DefinitelyLost"
grep -q "<kind>Leak_DefinitelyLost</kind>" memory-report.xml
error_on_zero $?
echo "checking Leak_StillReachable"
grep -q "<kind>Leak_StillReachable</kind>" memory-report.xml
error_on_zero $?
}

View file

@ -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);

View file

@ -14,7 +14,7 @@
#ifndef _BACKUPSESSION_H__
#define _BACKUPSESSION_H__
#include "xml_utils.h"
#include <mxml.h>
#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);

View file

@ -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;
}

View file

@ -12,11 +12,16 @@
#ifndef __CCOMMON_H
#define __CCOMMON_H
#include <stdbool.h>
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>
#include <math.h>
#include <libubox/list.h>
#include <pthread.h>
#include <libubox/uloop.h>
#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

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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

50
src/cwmp_event.c Normal file
View file

@ -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 <omar.kallel@pivasoftware.com>
*/
#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;
}

5
src/cwmp_event.h Normal file
View file

@ -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

51
src/cwmp_http.c Normal file
View file

@ -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 <omar.kallel@pivasoftware.com>
*/
#include <pthread.h>
#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);
}

8
src/cwmp_http.h Normal file
View file

@ -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

View file

@ -15,7 +15,6 @@
#include <uci.h>
#include "common.h"
//struct uci_context *cwmp_uci_ctx = ((void *)0);
#define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery"

View file

@ -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)

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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

View file

@ -17,30 +17,33 @@
#include "download.h"
#include "upload.h"
#include "log.h"
#include "session.h"
#include "cwmp_event.h"
//#include <libubox/list.h>
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;

View file

@ -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_ */

View file

@ -10,6 +10,7 @@
*/
#include <pthread.h>
#include <unistd.h>
#include <libubox/uloop.h>
#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;
}

View file

@ -12,13 +12,11 @@
#define HEARTBEAT_H
#include <stdbool.h>
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

View file

@ -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) {

View file

@ -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

View file

@ -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);

View file

@ -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_ */

View file

@ -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 <amin.benramdhane@pivasoftware.com>
*
* See LICENSE file for license related information.
* Copyright (C) 2021 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include <unistd.h>
#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);
}
}

View file

@ -14,7 +14,7 @@
#include "common.h"
void launch_reboot_methods(struct cwmp *cwmp);
void launch_reboot_methods();
#endif //_REBOOT_H__

357
src/rpc.c

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -10,22 +10,493 @@
*/
#include <stdlib.h>
#include <mxml.h>
#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;
}

View file

@ -12,14 +12,29 @@
#ifndef SESSION_H_
#define SESSION_H_
#include "xml_utils.h"
#include <mxml.h>
#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_ */

View file

@ -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};

146
src/subprocess.c Normal file
View file

@ -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 <omar.kallel@pivasoftware.com>
*
*/
#include <stdbool.h>
#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;
}

7
src/subprocess.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef SUB_PROC_H
#define SUB_PROC_H
#include <libubox/blobmsg_json.h>
typedef char* (*task_function)(char *task_arg);
int subprocess_start(task_function task_fun);
char *execute_task_in_subprocess(char *task);
#endif

View file

@ -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;

View file

@ -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__ */

View file

@ -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);
}
}

View file

@ -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

112
src/xml.c
View file

@ -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;
}

View file

@ -1,7 +1,7 @@
#ifndef __XML__H_
#define __XML__H_
#include "xml_utils.h"
#include <mxml.h>
#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);

View file

@ -1,5 +0,0 @@
#ifndef __XML_UTILS
#define __XML_UTILS
#include <mxml.h>
#endif

View file

@ -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

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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(&parameters_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)

View file

@ -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)

View file

@ -14,6 +14,7 @@ config acs 'acs'
option ipv6_enable '0'
option ip_version '4'
config cpe 'cpe'
option enable '1'
option interface 'eth0'

View file

@ -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
;;

7
test/script/test_seq.txt Normal file
View file

@ -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

View file

@ -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