blob: 72752f26fcfe818e91567dae63b14e70f0a63d30 [file] [log] [blame]
#include "soap.h"
#include "rpc.h"
#include "tr069.h"
extern struct tr069_obj root_obj[];
char * tr069_string_prefix = NULL;
int is_partial_path(const char * string)
{
return (string[(strlen(string) - 1)] == '.');
}
// ----- SOAP RPC Relation -----
static int envelope_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(value);
UNUSED(data_type);
struct tr069_rpc_method ** pp_method = (struct tr069_rpc_method **)userdata;
// Malloc new rpc method
*pp_method = (struct tr069_rpc_method *)tr069_malloc(sizeof(struct tr069_rpc_method));
if (*pp_method == NULL) {
TR069_ERR("Failed @%s:%d, cannot malloc memory!", __func__, __LINE__);
return 0;
}
memset(*pp_method, 0, sizeof(struct tr069_rpc_method));
return 0;
}
static int id_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
if (p_method == NULL) {
TR069_ERR("Failed @%s:%d, why rpc method is null?", __func__, __LINE__);
return 0;
}
if (type == SOAP_NODE_TYPE_VALUE) {
p_method->id = tr069_strdup(value);
TR069_ERR("Get response with ID %s", value);
}
return 0;
}
static int fault_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("fault...type(%d),value(%s)", type, value);
if (p_method == NULL) {
TR069_ERR("Fault failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_FAULT;
return 0;
}
static int inform_response_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(value);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: InformResponse");
if (p_method == NULL) {
TR069_ERR("InformResponse failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_INFORM_RESPONSE;
return 0;
}
static int get_rpc_method_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(value);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: GetRPCMethods");
if (p_method == NULL) {
TR069_ERR("GetRPCMethods failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_GET_RPC_METHOD;
return 0;
}
static int get_param_names_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(value);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: GetParameterNames");
if (p_method == NULL) {
TR069_ERR("GetParameterNames failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_GET_PARAMETER_NAME;
return 0;
}
static int parameter_path_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: ParameterPath");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) p_method->body.get_param_name.parameter_path = tr069_strdup(value);
return 0;
}
static int next_level_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: NextLevel");
if (p_method == NULL) {
TR069_ERR("NextLevel failed, because userdata is null...");
return -1;
}
if (value) p_method->body.get_param_name.next_level = tr069_strdup(value);
return 0;
}
static struct soap_rpc_node_table get_param_names_desc[] = {
{NULL, "ParameterPath", parameter_path_func, NULL},
{NULL, "NextLevel", next_level_func, NULL},
{NULL}
};
static int parameter_value_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: ParameterNames-string");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_get_param_value * p = tr069_malloc(sizeof(struct method_get_param_value));
if (p == NULL) {
TR069_ERR("Malloc failed, @parameter_value_func:%d", __LINE__);
return -1;
}
TR069_DEBUG(" ParameterNames-string: %s", value);
p->string = tr069_strdup(value);
p->next = p_method->body.get_param_value;
p_method->body.get_param_value = p;
}
return 0;
}
static struct soap_rpc_node_table get_param_value_desc1[] = {
{NULL, "string", parameter_value_value_func, NULL},
{NULL}
};
static struct soap_rpc_node_table get_param_value_desc[] = {
{NULL, "ParameterNames", NULL, get_param_value_desc1},
{NULL}
};
static int get_param_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: GetParameterValues");
if (p_method == NULL) {
TR069_ERR("GetParameterNames failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_GET_PARAMETER_VALUE;
return 0;
}
static int get_param_attr_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: GetParameterAttributes");
if (p_method == NULL) {
TR069_ERR("GetParameterAttributes failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_GET_PARAMETER_ATTR;
return 0;
}
static int parameter_attr_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: ParameterNames-string");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_get_attribute_value * p = tr069_malloc(sizeof(struct method_get_attribute_value));
if (p == NULL) {
TR069_ERR("Malloc failed, @parameter_value_func:%d", __LINE__);
return -1;
}
p->string = tr069_strdup(value);
p->next = p_method->body.get_param_attr;
p_method->body.get_param_attr = p;
}
return 0;
}
static struct soap_rpc_node_table get_param_attr_desc1[] = {
{NULL, "string", parameter_attr_value_func, NULL},
{NULL}
};
static struct soap_rpc_node_table get_param_attr_desc[] = {
{NULL, "ParameterNames", NULL, get_param_attr_desc1},
{NULL}
};
static int set_attr_name_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: SetattributeValue-Name");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_set_attribute_value * p = p_method->body.set_param_attr;
if (p == NULL) {
TR069_ERR("Failed, @Not process struct??? %d", __LINE__);
return -1;
}
p->name = tr069_strdup(value);
}
return 0;
}
static int set_attr_nc_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: NotificationChange");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_set_attribute_value * p = p_method->body.set_param_attr;
if (p == NULL) {
TR069_ERR("Failed, @Not process struct??? %d", __LINE__);
return -1;
}
p->notification_change = atoi(value);
}
return 0;
}
static int set_attr_n_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: NotificationChange");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_set_attribute_value * p = p_method->body.set_param_attr;
if (p == NULL) {
TR069_ERR("Failed, @Not process struct??? %d", __LINE__);
return -1;
}
p->notification = atoi(value);
}
return 0;
}
static struct soap_rpc_node_table set_param_attr_struct_desc[] = {
{NULL, "Name", set_attr_name_func, NULL},
{NULL, "NotificationChange", set_attr_nc_func, NULL},
{NULL, "Notification", set_attr_n_func, NULL},
{NULL, "AccessListChange", NULL, NULL},
{NULL, "AccessList", NULL, NULL},
{NULL}
};
static int set_attr_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method description: SetParameterAttributesStruct");
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (1) { // In this case, not have value, so we need always malloc buffer
struct method_set_attribute_value * p = tr069_malloc(sizeof(struct method_set_attribute_value));
if (p == NULL) {
TR069_ERR("Malloc failed, @parameter_value_func:%d", __LINE__);
return -1;
}
memset(p, 0, sizeof(struct method_set_attribute_value));
p->next = p_method->body.set_param_attr;
p_method->body.set_param_attr = p;
}
return 0;
}
static struct soap_rpc_node_table set_param_attr_desc[] = {
{NULL, "SetParameterAttributesStruct", set_attr_func, set_param_attr_struct_desc},
{NULL}
};
static struct soap_rpc_node_table set_param_attr_list_desc[] = {
{NULL, "ParameterList", NULL, set_param_attr_desc},
{NULL}
};
static int set_param_attr_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: SetParameterAttributes");
if (p_method == NULL) {
TR069_ERR("SetParameterAttributes failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_SET_PARAMETER_ATTR;
return 0;
}
static int set_param_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: SetParameterValues");
if (p_method == NULL) {
TR069_ERR("GetParameterNames failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_SET_PARAMETER_VALUE;
return 0;
}
static int set_param_value_value_name_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_set_param_value_value * p = p_method->body.set_param_value.value;
if (p == NULL) {
TR069_ERR("Failed, @parameter_value_func:%d", __LINE__);
return -1;
}
// Add assert here
p->name = tr069_strdup(value);
}
return 0;
}
static int set_param_value_value_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
struct method_set_param_value_value * p = p_method->body.set_param_value.value;
if (p == NULL) {
TR069_ERR("Failed, @parameter_value_func:%d", __LINE__);
return -1;
}
// Add assert here
p->value = tr069_strdup(value);
p->type = data_type;
}
return 0;
}
static struct soap_rpc_node_table set_param_value_desc2[] = {
{NULL, "Name", set_param_value_value_name_func, NULL},
{NULL, "Value", set_param_value_value_value_func, NULL},
{NULL}
};
static int set_param_value_value_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
struct method_set_param_value_value * p = tr069_malloc(sizeof(struct method_set_param_value_value));
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (p == NULL) {
TR069_ERR("Malloc failed, @%s:%d", __func__, __LINE__);
return -1;
}
p->name = p->value = NULL;
p->type = TR069_UNKOWN;
p->next = p_method->body.set_param_value.value;
p_method->body.set_param_value.value = p;
return 0;
}
static int set_param_value_param_key_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
if (p_method == NULL) {
TR069_ERR("ParameterPath failed, because userdata is null...");
return -1;
}
if (value) {
TR069_ERR("%s: %s", __func__, value);
p_method->body.set_param_value.parameter_key = tr069_strdup(value);
}
return 0;
}
static struct soap_rpc_node_table set_param_value_desc1[] = {
{NULL, "ParameterValueStruct", set_param_value_value_func, set_param_value_desc2},
{NULL}
};
static struct soap_rpc_node_table set_param_value_desc[] = {
{NULL, "ParameterList", NULL, set_param_value_desc1},
{NULL, "ParameterKey", set_param_value_param_key_func, NULL},
{NULL}
};
static int reboot_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: Reboot");
if (p_method == NULL) {
TR069_ERR("Reboot failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_REBOOT;
return 0;
}
static int reboot_command_key_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method reboot key: %s", value);
if (p_method == NULL) {
TR069_ERR("Reboot failed, because userdata is null...");
return -1;
}
if (value) {
p_method->body.reboot.command_key = tr069_strdup(value);
}
return 0;
}
static struct soap_rpc_node_table reboot_desc[] = {
{NULL, "CommandKey", reboot_command_key_func, NULL},
{NULL}
};
static int factory_reset_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: FactoryReset");
if (p_method == NULL) {
TR069_ERR("FactoryReset failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_FACTORY_RESET;
return 0;
}
static int transfer_complete_response_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: TransferCompleteResponse");
if (p_method == NULL) {
TR069_ERR("TransferCompleteResponse failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_TRANSFER_COMPLETE_RESPONSE;
return 0;
}
static int download_string_dup_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
char ** p = NULL;
TR069_DEBUG("Get RPC method %s with value %s", tag, value);
if (p_method == NULL) {
TR069_ERR("Download failed, because userdata is null...");
return -1;
}
if (!strcmp(tag, "CommandKey")) {
p = &p_method->body.download.command_key;
} else if (!strcmp(tag, "FileType")) {
p = &p_method->body.download.file_type;
} else if (!strcmp(tag, "URL")) {
p = &p_method->body.download.url;
} else if (!strcmp(tag, "Username")) {
p = &p_method->body.download.username;
} else if (!strcmp(tag, "Password")) {
p = &p_method->body.download.password;
} else if (!strcmp(tag, "TargetFileName")) {
p = &p_method->body.download.target_file_name;
} else if (!strcmp(tag, "SuccessURL")) {
p = &p_method->body.download.success_url;
} else if (!strcmp(tag, "FailureURL")) {
p = &p_method->body.download.failure_url;
}
if (value && p) {
*p = tr069_strdup(value);
}
return 0;
}
void free_download_method(struct tr069_rpc_method * method)
{
if (method->body.download.command_key) tr069_free(method->body.download.command_key);
if (method->body.download.file_type) tr069_free(method->body.download.file_type);
if (method->body.download.url) tr069_free(method->body.download.url);
if (method->body.download.username) tr069_free(method->body.download.username);
if (method->body.download.password) tr069_free(method->body.download.password);
if (method->body.download.target_file_name) tr069_free(method->body.download.target_file_name);
if (method->body.download.success_url) tr069_free(method->body.download.success_url);
if (method->body.download.failure_url) tr069_free(method->body.download.failure_url);
if (method->body.download.start_time) tr069_free(method->body.download.start_time);
if (method->body.download.complete_time) tr069_free(method->body.download.complete_time);
}
static int download_delay_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method %s delay with value %s", tag, value);
p_method->body.download.delay_seconds = atoi(value);
return 0;
}
static struct soap_rpc_node_table download_desc[] = {
{NULL, "CommandKey", download_string_dup_func, NULL},
{NULL, "FileType", download_string_dup_func, NULL},
{NULL, "URL", download_string_dup_func, NULL},
{NULL, "Username", download_string_dup_func, NULL},
{NULL, "Password", download_string_dup_func, NULL},
{NULL, "FileSize", NULL, NULL},
{NULL, "TargetFileName", download_string_dup_func, NULL},
{NULL, "DelaySeconds", download_delay_func, NULL},
{NULL, "SuccessURL", download_string_dup_func, NULL},
{NULL, "FailureURL", download_string_dup_func, NULL},
{NULL}
};
static int download_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: Download");
if (p_method == NULL) {
TR069_ERR("Download failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_DOWNLOAD;
return 0;
}
static int add_delete_obj_string_dup_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
char ** pp = NULL;
TR069_DEBUG("Get RPC method %s with value %s", tag, value);
if (p_method == NULL) {
TR069_ERR("Add object failed, because userdata is null...");
return -1;
}
if (!strcmp(tag, "ParameterKey")) {
pp = &p_method->body.add_delete.parameter_key;
} else if (!strcmp(tag, "ObjectName")) {
pp = &p_method->body.add_delete.object_name;
}
if (value && pp) {
*pp = tr069_strdup(value);
}
return -1;
}
static struct soap_rpc_node_table add_delete_obj_desc[] = {
{NULL, "ParameterKey", add_delete_obj_string_dup_func, NULL},
{NULL, "ObjectName", add_delete_obj_string_dup_func, NULL},
{NULL}
};
static int add_obj_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: Add object");
if (p_method == NULL) {
TR069_ERR("Add object failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_ADD;
return 0;
}
static int delete_obj_func(void * userdata, const char * tag, int type, const char * value, int data_type)
{
UNUSED(tag);
UNUSED(value);
UNUSED(type);
UNUSED(data_type);
struct tr069_rpc_method * p_method = *(struct tr069_rpc_method **)userdata;
TR069_DEBUG("Get RPC method: Delete object");
if (p_method == NULL) {
TR069_ERR("Delete object failed, because userdata is null...");
return -1;
}
p_method->type = RPC_TYPE_DELETE;
return 0;
}
static struct soap_rpc_node_table body[] = {
{NULL, "Fault", fault_func, NULL},
{NULL, "InformResponse", inform_response_func, NULL}, // namespace: cwmp
{NULL, "GetRPCMethods", get_rpc_method_func, NULL},
{NULL, "GetParameterNames", get_param_names_func, get_param_names_desc},
{NULL, "GetParameterValues", get_param_value_func, get_param_value_desc},
{NULL, "SetParameterValues", set_param_value_func, set_param_value_desc},
{NULL, "GetParameterAttributes", get_param_attr_func, get_param_attr_desc},
{NULL, "SetParameterAttributes", set_param_attr_func, set_param_attr_list_desc},
{NULL, "Reboot", reboot_func, reboot_desc},
{NULL, "FactoryReset", factory_reset_func, NULL},
{NULL, "TransferCompleteResponse", transfer_complete_response_func, NULL},
{NULL, "GetRPCMethodsResponse", NULL, NULL},
{NULL, "AddObject", add_obj_func, add_delete_obj_desc},
{NULL, "DeleteObject", delete_obj_func, add_delete_obj_desc},
{NULL, "Download", download_func, download_desc},
{NULL}
};
static struct soap_rpc_node_table header[] = {
{NULL, "ID", id_func, NULL}, // namespace: cwmp
{NULL, "HoldRequests", NULL, NULL},
{NULL}
};
static struct soap_rpc_node_table envelope[] = {
{NULL, "Header", NULL, header}, // namespace: env
{NULL, "Body", NULL, body},
{NULL}
};
struct soap_rpc_node_table root[] = {
{NULL, "Envelope", envelope_func, envelope}, // namespace: env
{NULL}
};
int build_get_rpc_method_response(struct tr069_rpc_method * method, struct tr069_msg * msg)
{
UNUSED(method);
struct soap_rpc_node_table * ptr = &body[2];
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:GetRPCMethodsResponse", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "MethodList", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ATTR, "arrayType", "string[!^^!]");
while (ptr->tag) {
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "string", ptr->tag);
pop_soap_node(&msg->body_stack);
ptr++;
}
pop_soap_node(&msg->body_stack);
pop_soap_node(&msg->body_stack);
return 0;
}
static const char * tr069_infor_device_id[] = {
"Manufacturer",
"ManufacturerOUI",
"ModelName",
"ProductClass",
"SerialNumber",
NULL
};
static const char * inform_paramet_list[] ={
"Device.RootDataModelVersion",
"Device.DeviceInfo.HardwareVersion",
"Device.DeviceInfo.SoftwareVersion",
"Device.DeviceInfo.ProvisioningCode",
"Device.ManagementServer.ParameterKey",
"Device.ManagementServer.ConnectionRequestURL",
//"Device.ManagementServer.NATDetected",
//"Device.ManagementServer.UDPConnectionRequestAddress",
};
struct tr069_parameter_change_list_struct * tr069_parameter_change_list = NULL;
#define TR069_EVET_FLAG_BOOTSTRAP (1 << TR069_EVENT_BOOTSTRAP)
#define TR069_EVET_FLAG_BOOT (1 << TR069_EVENT_BOOT)
#define TR069_EVET_FLAG_PERIODIC (1 << TR069_EVENT_PERIODIC)
#define TR069_EVET_FLAG_SCHEDULED (1 << TR069_EVENT_SCHEDULED)
#define TR069_EVET_FLAG_VALUE_CHANGE (1 << TR069_EVENT_VALUE_CHANGE)
#define TR069_EVET_FLAG_CONNECTION_REQUEST (1 << TR069_EVENT_CONNECTION_REQUEST)
#define TR069_EVET_FLAG_TRANSFER_COMPLETE (1 << TR069_EVENT_TRANSFER_COMPLETE)
#define TR069_EVET_FLAG_REQUEST_DOWNLOAD (1 << TR069_EVENT_REQUEST_DOWNLOAD)
#define TR069_EVET_FLAG_M_REBOOT (1 << TR069_EVENT_M_REBOOT)
#define TR069_EVET_FLAG_M_SCHEDULE_INFORM (1 << TR069_EVENT_M_SCHEDULE_INFORM)
#define TR069_EVET_FLAG_M_DOWNLOAD (1 << TR069_EVENT_M_DOWNLOAD)
#define TR069_EVET_FLAG_M_SCHEDULE_DOWNLOAD (1 << TR069_EVENT_M_SCHEDULE_DOWNLOAD)
#define TR069_EVET_FLAG_M_UPLOAD (1 << TR069_EVENT_M_UPLOAD)
#define TR069_EVET_FLAG_M_CHANGE_DU_STATE (1 << TR069_EVENT_M_CHANGE_DU_STATE)
static const char * event_string[TR069_EVENT_MAX] = {
"0 BOOTSTRAP",
"1 BOOT",
"2 PERIODIC",
"3 SCHEDULED",
"4 VALUE CHANGE",
"6 CONNECTION REQUEST",
"7 TRANSFER COMPLETE",
"9 REQUEST DOWNLOAD",
"M Reboot",
"M ScheduleInform",
"M Download",
"M ScheduleDownload",
"M Upload",
"M ChangeDUState",
};
static char event_command_key[TR069_EVENT_MAX][32] = {
{0}
};
static unsigned int tr069_event = 0;
struct cpe_struct cpe = {0};
void set_tr069_event(unsigned int event, const char * command_key)
{
if (event < TR069_EVENT_MAX) {
tr069_event |= (1 << event);
snprintf(&event_command_key[event][0], 32, "%s", command_key);
}
}
struct tr069_msg * tr069_build_msg(const char * id)
{
struct tr069_msg * msg = tr069_malloc(sizeof(struct tr069_msg));
if (!msg) {
TR069_ERR("Can not malloc memory for tr069_build_msg");
return NULL;
}
// Build Header and body msg
msg->root = MrvCreateRoot();
msg->env = new_soap_node(msg->root, SOAP_NODE_TYPE_ELEMENT, "SOAP-ENV:Envelope", NULL);
new_soap_node(msg->env, SOAP_NODE_TYPE_ATTR, "xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
new_soap_node(msg->env, SOAP_NODE_TYPE_ATTR, "xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
new_soap_node(msg->env, SOAP_NODE_TYPE_ATTR, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
new_soap_node(msg->env, SOAP_NODE_TYPE_ATTR, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
new_soap_node(msg->env, SOAP_NODE_TYPE_ATTR, "xmlns:cwmp", "urn:dslforum-org:cwmp-1-0");
msg->header_node = new_soap_node(msg->env, SOAP_NODE_TYPE_ELEMENT, "SOAP-ENV:Header", NULL);
msg->body_node = new_soap_node(msg->env, SOAP_NODE_TYPE_ELEMENT, "SOAP-ENV:Body", NULL);
memset(&msg->header_stack, 0, sizeof(struct soap_trace_stack));
msg->header_stack.stack[0] = msg->header_node;
push_new_soap_node(&msg->header_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:ID", id);
push_new_soap_node(&msg->header_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENV:mustUnderstand", "1");
memset(&msg->body_stack, 0, sizeof(struct soap_trace_stack));
msg->body_stack.stack[0] = msg->body_node;
return msg;
}
void tr069_msg_destroy(struct tr069_msg * msg)
{
MrvDeleteRoot(msg->root);
tr069_free(msg);
}
int tr069_inform_acs(struct tr069_msg * msg)
{
const char ** pchar;
char * temp_buf;
int addition_list_size = 0;
temp_buf = (char *)tr069_malloc(128);
if (temp_buf == NULL) {
TR069_ERR("Inform to acs failed@%d!", __LINE__);
return -1;
}
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:Inform", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "DeviceId", NULL);
// Add device info element
pchar = &tr069_infor_device_id[0];
while (*pchar) {
struct tr069_param * param;
sprintf(temp_buf, "%s.DeviceInfo.%s", root_obj[0].name, *pchar);
param = find_param(root_obj, temp_buf);
if (param) {
char * string = NULL;
const char * temp = *pchar;
if (param->get_value) {
if (!strcmp(*pchar, "ManufacturerOUI"))
temp = "OUI";
param->get_value(NULL, &string);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, temp, string);
pop_soap_node(&msg->body_stack);
if (string) tr069_free(string);
}
}
pchar++;
}
pop_soap_node(&msg->body_stack); /* End of DeviceId */
if (tr069_parameter_change_list) {
struct tr069_parameter_change_list_struct * temp = tr069_parameter_change_list;
set_tr069_event(TR069_EVENT_VALUE_CHANGE, "");
while (temp) {
addition_list_size++;
temp = temp->next;
}
TR069_DEBUG("Additional info list size %d", addition_list_size);
}
// Add event code struct
if (tr069_event) {
unsigned int event = tr069_event;
int i = 0;
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Event", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", "cwmp:EventStruct[!^^!]");
while (event && (i < TR069_EVENT_MAX)) {
if (event & 0x01) {
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "EventStruct", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "EventCode", event_string[i]);
pop_soap_node(&msg->body_stack);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "CommandKey", &event_command_key[i][0]);
pop_soap_node(&msg->body_stack);
pop_soap_node(&msg->body_stack);
TR069_DEBUG("add event code: %s, command key %s", event_string[i], &event_command_key[i][0]);
}
event >>= 1;
i++;
}
pop_soap_node(&msg->body_stack); /* End of Event */
}
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "MaxEnvelopes", "1");
pop_soap_node(&msg->body_stack);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "CurrentTime", "1370933262");
pop_soap_node(&msg->body_stack);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "RetryCount", "2");
pop_soap_node(&msg->body_stack);
//if (inform_paramet_list) {
if (1) {
int size = sizeof(inform_paramet_list) / sizeof(char *);
int i;
struct tr069_param * param;
char buf[sizeof("cwmp:ParameterValueStruct[%d]") + 5];
sprintf(buf, "cwmp:ParameterValueStruct[%d]", size + addition_list_size);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterList", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", buf);
for (i = 0; i < size; i++) {
char * string = NULL;
param = find_param(root_obj, inform_paramet_list[i]);
if (!param) {
TR069_ERR("Failed, when try find object paramet(%s)!", inform_paramet_list[i]);
continue;
}
if (!param->get_value) {
TR069_ERR("Why parameter not have value?");
continue;
}
param->get_value(NULL, &string);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterValueStruct", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Name", inform_paramet_list[i]);
pop_soap_node(&msg->body_stack);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Value", string);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ATTR, "xsi:stype", rpc_type2string(param->type));
pop_soap_node(&msg->body_stack);
pop_soap_node(&msg->body_stack);
if (string) tr069_free(string);
}
}
while (tr069_parameter_change_list) {
struct tr069_parameter_change_list_struct * temp = tr069_parameter_change_list;
do {
char * string = NULL;
struct tr069_param * param;
param = find_param(root_obj, temp->parameter_name);
if (!param) {
TR069_ERR("Failed, when try find object paramet(%s)!", temp->parameter_name);
break; // Failed, goto free and process next parameter
}
if (param->notification == TR069_NOTIFICATION_OFF) {
break; // This parameter not need update to ACS
}
if (!param->get_value) {
TR069_ERR("Why parameter not have value?");
break; // Failed, goto free and process next parameter
}
param->get_value(top_instance(), &string);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterValueStruct", NULL);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Name", temp->parameter_name);
pop_soap_node(&msg->body_stack);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Value", string);
push_new_soap_node(&msg->body_stack, SOAP_NODE_TYPE_ATTR, "xsi:stype", rpc_type2string(param->type));
pop_soap_node(&msg->body_stack);
pop_soap_node(&msg->body_stack);
if (string) tr069_free(string);
} while (0);
tr069_parameter_change_list = temp->next;
tr069_free(temp);
temp = NULL;
}
pop_soap_node(&msg->body_stack);
//done:
// Clear event
tr069_event = 0;
if (temp_buf) {
tr069_free(temp_buf);
temp_buf = NULL;
}
return 0;
}
int parameter_attr_dup(struct tr069_obj * obj, struct tr069_param * param,
struct tr069_instance * instance, struct walk_context * context, int type)
{
UNUSED(obj);
UNUSED(instance);
struct tr069_msg * tr069_msg = context->userdata;
int i, end, pos;
if (type != TR069_TYPE_PARAMETER) return 0;
if (!param) return 0;
pos = 0;
end = context->index == 0 ? 0 : context->index - 1;
if (tr069_string_prefix) {
i = 1;
pos += sprintf(&context->tempbuf[pos], "%s", tr069_string_prefix);
} else {
i = 0;
}
for (; i <= end; i++) {
pos += sprintf(&context->tempbuf[pos], "%s.", context->stack[i]);
}
if (end != context->index) {
pos += sprintf(&context->tempbuf[pos], "%s%s", context->stack[context->index],
type == TR069_TYPE_OBJECT ? "." : "");
}
if (pos >= 256) TR069_ERR("Failed! %s:%d", __func__, __LINE__);
if (context->index >= 30) TR069_ERR("Failed! %s:%d", __func__, __LINE__);
TR069_DEBUG("parameter attribute dup: %s", context->tempbuf);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterAttributeStruct", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Name", context->tempbuf);
pop_soap_node(&tr069_msg->body_stack);
sprintf(context->tempbuf, "%d", param->notification);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Notification", context->tempbuf);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "AccessList", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", rpc_type2string(param->type));
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "string", "Subscriber");
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack); /* End of ParameterAttributeStruct */
return 0;
}
int parameter_value_dup(struct tr069_obj * obj, struct tr069_param * param,
struct tr069_instance * instance, struct walk_context * context, int type)
{
UNUSED(obj);
struct tr069_msg * tr069_msg = context->userdata;
int i, end, pos, ret;
char * value = NULL;
if (type != TR069_TYPE_PARAMETER) return 0;
if (!param || !param->get_value) return 0;
ret = param->get_value(instance, &value);
if (ret) {
TR069_ERR("Get value failed: %s", param->name);
}
pos = 0;
end = context->index == 0 ? 0 : context->index - 1;
if (tr069_string_prefix) {
i = 1;
pos += sprintf(&context->tempbuf[pos], "%s", tr069_string_prefix);
} else {
i = 0;
}
for (; i <= end; i++) {
pos += sprintf(&context->tempbuf[pos], "%s.", context->stack[i]);
}
if (end != context->index) {
pos += sprintf(&context->tempbuf[pos], "%s%s", context->stack[context->index],
type == TR069_TYPE_OBJECT ? "." : "");
}
if (pos >= 256) TR069_ERR("Failed! %s:%d", __func__, __LINE__);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterValueStruct", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Name", context->tempbuf);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Value", value);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "xsi:type", rpc_type2string(param->type));
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack); /* End of ParameterInfoStruct */
if (value) tr069_free(value);
return 0;
}
int parameter_name_dup(struct tr069_obj * obj, struct tr069_param * param,
struct tr069_instance * instance, struct walk_context * context, int type)
{
UNUSED(obj);
UNUSED(instance);
struct tr069_msg * tr069_msg = context->userdata;
int i, end, pos;
if (type != TR069_TYPE_PARAMETER) return 0;
pos = 0;
end = context->index == 0 ? 0 : context->index - 1;
if (tr069_string_prefix) {
i = 1;
pos += sprintf(&context->tempbuf[pos], "%s", tr069_string_prefix);
} else {
i = 0;
}
for (; i <= end; i++) {
pos += sprintf(&context->tempbuf[pos], "%s.", context->stack[i]);
}
if (end != context->index) {
pos += sprintf(&context->tempbuf[pos], "%s%s", context->stack[context->index],
type == TR069_TYPE_OBJECT ? "." : "");
}
if (pos >= 256) TR069_ERR("Failed! %s:%d", __func__, __LINE__);
TR069_DEBUG("Parameter dup: %s", context->tempbuf);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterInfoStruct", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Name", context->tempbuf);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Writable", param->rw == TR069_R ? "0" : "1");
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack); /* End of ParameterInfoStruct */
return 0;
}
const char * fault2string(int fault)
{
switch (fault) {
case 9003: return "Invalid Argments";
case 9005: return "Invalid Parameter Name";
case 9006: return "Invalid Parameter Type";
case 9007: return "Invalid Parameter Value";
case 9008: return "Attempt to set a non-writable parameter";
case 9015: return "File transfer failure: unable to contact file server";
case 9017: return "File transfer failure: unable to complete download";
case 9018: return "File transfer failure: file corrupted";
case 9012: return "File transfer server authentication failure";
case 9020: return "File transfer failure: unable to complete download with specified time windows";
case 9021: return "Cancelation of file transfer not permitted in current transfer state";
default:
return "Unknown";
}
}