/* * 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. * Powered by Inteno Broadband Technology AB * * Copyright (C) 2013 Mohamed Kallel * Copyright (C) 2013 Ahmed Zribi * */ #include "cwmp.h" #include "backupSession.h" #include "xml.h" #include "log.h" static mxml_node_t *bkp_tree = NULL; pthread_mutex_t mutex_backup_session = PTHREAD_MUTEX_INITIALIZER; void bkp_session_save() { FILE *fp; pthread_mutex_lock (&mutex_backup_session); fp = fopen(CWMP_BKP_FILE, "w"); mxmlSaveFile(bkp_tree, fp, MXML_NO_CALLBACK); fclose(fp); pthread_mutex_unlock (&mutex_backup_session); } mxml_node_t *bkp_session_insert(mxml_node_t *tree, char *name, char *value) { mxml_node_t *b; b = mxmlNewElement(tree, name); if(value != NULL) { mxmlNewText(b, 0, value); } return b; } /* * The order of key array filling should be the same of insertion function */ mxml_node_t *bkp_session_node_found(mxml_node_t *tree, char *name, struct search_keywords *keys, int size) { mxml_node_t *b = tree, *c, *d; struct search_keywords; int i; b = mxmlFindElement(b, b, name, NULL, NULL, MXML_DESCEND_FIRST); while (b) { if(b && b->child) { c = b->child; i = 0; while(c && i < size) { if(c->type == MXML_ELEMENT && strcmp(keys[i].name, c->value.element.name) == 0) { d = c; d = mxmlWalkNext(d, c, MXML_DESCEND); if((keys[i].value == NULL)||(d && d->type == MXML_TEXT && keys[i].value != NULL && strcmp(keys[i].value, d->value.text.string) == 0)) i++; } c = mxmlWalkNext(c, b, MXML_NO_DESCEND); } } if(i == size) { break; } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } return b; } mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char *status) { struct search_keywords keys[1]; char parent_name[32]; char event_id[32]; char event_idx[32]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(parent_name,"%s_event",status); sprintf(event_id,"%d",id); sprintf(event_idx,"%d",index); keys[0].name = "id"; keys[0].value = event_id; b = bkp_session_node_found(bkp_tree, parent_name, keys, 1); if(!b) { b = bkp_session_insert(bkp_tree,parent_name,NULL); bkp_session_insert(b,"index",event_idx); bkp_session_insert(b,"id",event_id); bkp_session_insert(b,"command_key",command_key); } pthread_mutex_unlock (&mutex_backup_session); return b; } void bkp_session_delete_event(int id, char *status) { struct search_keywords keys[1]; char parent_name[32]; char event_id[32]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(parent_name,"%s_event",status); sprintf(event_id,"%d",id); keys[0].name = "id"; keys[0].value = event_id; 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_move_inform_to_inform_send () { mxml_node_t *b = bkp_tree; pthread_mutex_lock (&mutex_backup_session); while (b) { if (b && b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "queue_event") && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "cwmp")) { FREE(b->value.element.name); b->value.element.name = strdup("send_event"); } 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) { if (b && b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "send_event") && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "cwmp")) { FREE(b->value.element.name); b->value.element.name = strdup("queue_event"); } 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) { struct search_keywords keys[2]; char schedule_time[128]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(schedule_time,"%ld",time); keys[0].name = "command_key"; keys[0].value = command_key; keys[1].name = "time"; keys[1].value = schedule_time; b = bkp_session_node_found(bkp_tree, "schedule_inform", keys, 2); if(!b) { b = bkp_session_insert(bkp_tree,"schedule_inform",NULL); 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) { struct search_keywords keys[2]; char schedule_time[128]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(schedule_time,"%ld",time); keys[0].name = "command_key"; keys[0].value = command_key; keys[1].name = "time"; keys[1].value = schedule_time; b = bkp_session_node_found(bkp_tree, "schedule_inform", keys, 2); if(b) mxmlDelete(b); pthread_mutex_unlock (&mutex_backup_session); } void bkp_session_insert_download(struct download *pdownload) { struct search_keywords keys[7]; char schedule_time[128]; char file_size[128]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(schedule_time,"%ld",pdownload->scheduled_time); sprintf(file_size,"%d",pdownload->file_size); keys[0].name = "url"; keys[0].value = pdownload->url; keys[1].name = "command_key"; keys[1].value = pdownload->command_key; keys[2].name = "file_type"; keys[2].value = pdownload->file_type; keys[3].name = "username"; keys[3].value = pdownload->username; keys[4].name = "password"; keys[4].value = pdownload->password; keys[5].name = "file_size"; keys[5].value = file_size; keys[6].name = "time"; keys[6].value = schedule_time; b = bkp_session_node_found(bkp_tree, "download", keys, 7); if(!b) { b = bkp_session_insert(bkp_tree,"download",NULL); bkp_session_insert(b,"url",pdownload->url); bkp_session_insert(b,"command_key",pdownload->command_key); bkp_session_insert(b,"file_type",pdownload->file_type); bkp_session_insert(b,"username",pdownload->username); bkp_session_insert(b,"password",pdownload->password); bkp_session_insert(b,"file_size",file_size); bkp_session_insert(b,"time",schedule_time); } pthread_mutex_unlock (&mutex_backup_session); } void bkp_session_delete_download(struct download *pdownload) { struct search_keywords keys[7]; char schedule_time[128]; char file_size[128]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(schedule_time,"%ld",pdownload->scheduled_time); sprintf(file_size,"%d",pdownload->file_size); keys[0].name = "url"; keys[0].value = pdownload->url; keys[1].name = "command_key"; keys[1].value = pdownload->command_key; keys[2].name = "file_type"; keys[2].value = pdownload->file_type; keys[3].name = "username"; keys[3].value = pdownload->username; keys[4].name = "password"; keys[4].value = pdownload->password; keys[5].name = "file_size"; keys[5].value = file_size; keys[6].name = "time"; keys[6].value = schedule_time; b = bkp_session_node_found(bkp_tree, "download", keys, 7); if(b) mxmlDelete(b); pthread_mutex_unlock (&mutex_backup_session); } void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_complete) { struct search_keywords keys[4]; char fault_code[16]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(fault_code,"%d",ptransfer_complete->fault_code); keys[0].name = "command_key"; keys[0].value = ptransfer_complete->command_key; keys[1].name = "start_time"; keys[1].value = ptransfer_complete->start_time; keys[2].name = "complete_time"; keys[2].value = ptransfer_complete->complete_time; keys[3].name = "fault_code"; keys[3].value = fault_code; b = bkp_session_node_found(bkp_tree, "transfer_complete", keys, 4); if(!b) { b = bkp_session_insert(bkp_tree,"transfer_complete",NULL); bkp_session_insert(b,"command_key",ptransfer_complete->command_key); bkp_session_insert(b,"start_time",ptransfer_complete->start_time); bkp_session_insert(b,"complete_time",ptransfer_complete->complete_time); bkp_session_insert(b,"fault_code",fault_code); } pthread_mutex_unlock (&mutex_backup_session); } void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_complete) { struct search_keywords keys[4]; char fault_code[16]; mxml_node_t *b; pthread_mutex_lock (&mutex_backup_session); sprintf(fault_code,"%d",ptransfer_complete->fault_code); keys[0].name = "command_key"; keys[0].value = ptransfer_complete->command_key; keys[1].name = "start_time"; keys[1].value = ptransfer_complete->start_time; keys[2].name = "complete_time"; keys[2].value = ptransfer_complete->complete_time; keys[3].name = "fault_code"; keys[3].value = fault_code; b = bkp_session_node_found(bkp_tree, "transfer_complete", keys, 4); if(b) mxmlDelete(b); pthread_mutex_unlock (&mutex_backup_session); } /* * Load backup session */ char *load_child_value(mxml_node_t *tree, char *sub_name) { char *value = NULL; mxml_node_t *b = tree; if (b) { b = mxmlWalkNext(b, tree, MXML_DESCEND); if (b && b->type == MXML_ELEMENT && strcmp(b->value.element.name, sub_name) == 0) { b = mxmlWalkNext(b, tree, MXML_DESCEND); if (b && b->type == MXML_TEXT) { if(b->value.text.string != NULL) { value = strdup(b->value.text.string); } } } } return value; } void load_queue_event(mxml_node_t *tree,struct cwmp *cwmp) { char *command_key = NULL; mxml_node_t *b = tree, *c; int idx = -1, id; struct event_container *event_container_save = NULL; b = mxmlWalkNext(b, tree, MXML_DESCEND); while (b) { if (b && b->type == MXML_ELEMENT) { if(strcmp(b->value.element.name, "index") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { idx = atoi(c->value.text.string); } } } else if(strcmp(b->value.element.name, "id") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { id = atoi(c->value.text.string); } } } else if(strcmp(b->value.element.name, "command_key") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { command_key = strdup(c->value.text.string); } } 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:"")); if(event_container_save != NULL) { event_container_save->id = id; } } } FREE(command_key); } else if(strcmp(b->value.element.name, "parameter") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { if(event_container_save != NULL) { parameter_container_add(&(event_container_save->head_parameter_container), c->value.text.string, NULL, NULL, NULL); } } } } } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } } void load_schedule_inform(mxml_node_t *tree,struct cwmp *cwmp) { char *command_key; mxml_node_t *b = tree, *c; time_t scheduled_time; struct schedule_inform *schedule_inform = NULL; struct list_head *ilist = NULL; b = mxmlWalkNext(b, tree, MXML_DESCEND); while (b) { if (b && b->type == MXML_ELEMENT) { if (strcmp(b->value.element.name, "command_key") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { command_key = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "time") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { scheduled_time = atol(c->value.text.string); } } } } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } list_for_each(ilist,&(list_schedule_inform)) { schedule_inform = list_entry(ilist,struct schedule_inform, list); if (schedule_inform->scheduled_time > scheduled_time) { break; } } schedule_inform = calloc (1,sizeof(struct schedule_inform)); if (schedule_inform != NULL) { schedule_inform->commandKey = command_key; schedule_inform->scheduled_time = scheduled_time; list_add (&(schedule_inform->list), ilist->prev); } } void load_download(mxml_node_t *tree,struct cwmp *cwmp) { mxml_node_t *b = tree, *c; struct download *download_request = NULL; struct list_head *ilist = NULL; struct download *idownload_request = NULL; download_request = calloc(1,sizeof(struct download)); b = mxmlWalkNext(b, tree, MXML_DESCEND); while (b) { if (b && b->type == MXML_ELEMENT) { if (strcmp(b->value.element.name, "url") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->url = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "command_key") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->command_key = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "file_type") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->file_type = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "username") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->username = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "password") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->password = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name, "file_size") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->file_size = atoi(c->value.text.string); } } } else if (strcmp(b->value.element.name, "time") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { download_request->scheduled_time = atol(c->value.text.string); } } } } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } list_for_each(ilist,&(list_download)) { idownload_request = list_entry(ilist,struct download,list); if (idownload_request->scheduled_time > download_request->scheduled_time) { break; } } list_add (&(download_request->list), ilist->prev); if(download_request->scheduled_time != 0) count_download_queue++; } void load_transfer_complete(mxml_node_t *tree,struct cwmp *cwmp) { mxml_node_t *b = tree, *c; struct transfer_complete *ptransfer_complete; b = mxmlWalkNext(b, tree, MXML_DESCEND); ptransfer_complete = calloc (1,sizeof(struct transfer_complete)); while (b) { if (b && b->type == MXML_ELEMENT) { if (strcmp(b->value.element.name,"command_key") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { ptransfer_complete->command_key = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name,"start_time") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { ptransfer_complete->start_time = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name,"complete_time") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { ptransfer_complete->complete_time = strdup(c->value.text.string); } } } else if (strcmp(b->value.element.name,"fault_code") == 0) { c = mxmlWalkNext(b, b, MXML_DESCEND); if (c && c->type == MXML_TEXT) { if(c->value.text.string != NULL) { ptransfer_complete->fault_code = atoi(c->value.text.string); } } } } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } cwmp_root_cause_TransferComplete (cwmp, 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); bkp_tree = mxmlLoadString(NULL, CWMP_BACKUP_SESSION, MXML_NO_CALLBACK); fclose(pFile); pthread_mutex_unlock (&mutex_backup_session); } int bkp_session_check_file() { FILE *pFile; if(access(CWMP_BKP_FILE, F_OK) == -1) { bkp_session_create_file(); return -1; } if(bkp_tree == NULL) { pFile = fopen(CWMP_BKP_FILE, "r"); bkp_tree = mxmlLoadFile(NULL, pFile, MXML_NO_CALLBACK); fclose(pFile); } if(bkp_tree == NULL) { bkp_session_create_file(); return -1; } bkp_session_move_inform_to_inform_queue (); bkp_session_save(); return 0; } int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load) { int error; if(bkp_session_check_file()) return 0; error = cwmp_load_saved_session(cwmp, ret, load); return error; } int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading load) { mxml_node_t *b; b = bkp_tree; b = mxmlWalkNext(b, bkp_tree, MXML_DESCEND); while(b) { if(load == ACS) { if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "acs") == 0) { *ret = load_child_value(b, "url"); break; } } if(load == CR_IP) { if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "connection_request") == 0) { *ret = load_child_value(b, "ip"); break; } } if(load == ALL) { if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "queue_event") == 0) { load_queue_event(b,cwmp); } else if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "download") == 0) { load_download(b,cwmp); } else if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "transfer_complete") == 0) { load_transfer_complete(b,cwmp); } else if(b->type == MXML_ELEMENT && strcmp(b->value.element.name, "schedule_inform") == 0) { load_schedule_inform(b,cwmp); } } b = mxmlWalkNext(b, bkp_tree, MXML_NO_DESCEND); } return CWMP_OK; }