blob: fde08d66da588f07794b4694c92af5d5cac628f8 [file] [log] [blame]
#include <stdio.h>
#include <pthread.h>
#include "soap.h"
#include "rpc.h"
#include "tr069.h"
#include "tr098.h"
#include "tr069_download.h"
#include "tr069_service.h"
#include "tr069_uci.h"
#include "tr069_msgq.h"
#include "tr069_sys.h"
//#define __return_address() __builtin_return_address(1)
#define __return_address() 0
int post_factory_reset(void);
int send_tr069_command_delay(struct tr069_task_command * command, unsigned int delay);
int wifi_device_add_trigger(void);
int wifi_ssid_change_trigger(void);
int ipv4_address_change_trigger(void);
int post_add_object(const char * path, const char * name);
int post_system_reset(void);
int tr069_build_oui(void);
void stun_init(void);
extern struct uloop_fd tr069_client_fd;
extern struct tr069_obj root_obj[];
static char * response_data = NULL;
static int response_len = 0;
#define PRINT_BUF_SIZE 65
static char print_buf[PRINT_BUF_SIZE];
unsigned int imcomplete_id = 0;
static void print_string(const char * string)
{
int len = strlen(string);
int printed = 0;
while (printed != len) {
if ((len - printed) > (PRINT_BUF_SIZE - 1)) {
memcpy(print_buf, string + printed, (PRINT_BUF_SIZE - 1));
printed += (PRINT_BUF_SIZE - 1);
print_buf[PRINT_BUF_SIZE - 1] = '\0';
} else {
sprintf(print_buf, "%s", string + printed);
printed = len;
}
TR069_DEBUG("[value]%s", print_buf);
}
}
static struct tr069_msg * private_msg = NULL; // This only used in tr069 task
static void tr069_response_cb(char * data, int len, int num, void *cbdata)
{
UNUSED(num);
UNUSED(cbdata);
char * temp;
TR069_DEBUG("[tr069]Get response length %d", len);
temp = tr069_malloc(response_len + len + 1); // Always end by '\0'
if (!temp) {
TR069_ERR("[tr069]Malloc for response store failed...");
return;
}
memset(temp, 0, response_len + len + 1);
if (response_data) {
TR069_DEBUG("[tr069]Have old string...");
print_string(response_data);
memcpy(temp, response_data, response_len);
tr069_free(response_data);
response_data = NULL;
}
memcpy(&temp[response_len], data, len);
response_data = temp;
response_len += len;
print_string(temp);
TR069_DEBUG("[tr069]Totoal content length %d", response_len);
}
static void modify_prefix_if_need(void)
{
int temp_index = 0, temp_flag = 0;
temp_index = strlen(tr069_string_prefix) - 1;
while (temp_index > 0) {
if (tr069_string_prefix[temp_index] == '.') {
if (temp_flag == 0) {
temp_flag = 1;
} else {
// Try modify string, if need
char * temp_string = &tr069_string_prefix[temp_index + 1];
TR069_DEBUG("%s: %s", __func__, temp_string);
if ('0' <= tr069_string_prefix[temp_index + 1] &&
'9' >= tr069_string_prefix[temp_index + 1]) {
TR069_DEBUG("need modify");
tr069_string_prefix[temp_index + 1] = '\0';
}
return;
}
}
temp_index--;
}
}
static int process_main_tr069_event(void)
{
char * temp_buf = NULL;
char * msg = NULL;
soap_rpc_node * xml_result = NULL;
MrvXMLResults err_info;
struct tr069_msg * tr069_msg = NULL;
struct tr069_rpc_method * method = NULL;
struct http_client * client = NULL;
struct http_client_list * header = NULL;
int state = 1, len = 0, http_response_code = 0;
int fault = 0;
int err = 0;
if (cpe.enable == 0) {
TR069_ERR("TR069 be disabled");
return 0;
}
if (imcomplete_id) {
TR069_ERR("send_download_imcompete_msg imcomplete_id=%d\n",imcomplete_id);
send_download_imcompete_msg(imcomplete_id);
}
temp_buf = tr069_malloc(BUF_SIZE);
if (!temp_buf) {
TR069_ERR("Malloc failed!@%s:%d", __func__, __LINE__);
err = -1;
goto done;
}
memset(temp_buf, 0, BUF_SIZE);
// Init http client code
// Set URL
client = http_client_init();
// Set response callback
http_client_setopt(client, HTTPCLIENT_OPT_RESPONSECB, tr069_response_cb);
http_client_setopt(client, HTTPCLIENT_OPT_METHOD, HTTPCLIENT_REQUEST_POST);
http_client_setopt(client, HTTPCLIENT_OPT_AUTH_TYPE, HTTP_AUTH_TYPE_BASE);
http_client_setopt(client, HTTPCLIENT_OPT_AUTH_USERNAME, cpe.username);
http_client_setopt(client, HTTPCLIENT_OPT_AUTH_PASSWORD, cpe.password);
// if (!private_msg) {
// TR069_DEBUG("Send Inform msg to ACS");
// private_msg = tr069_build_msg("1234");
// tr069_inform_acs(private_msg);
// } else {
// TR069_DEBUG("Send private msg to ACS");
// }
// tr069_msg = private_msg;
len = 0;
tr069_msg = tr069_build_msg("1234");
tr069_inform_acs(tr069_msg);
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
TR069_DEBUG("Send to ACS message length: %d", len);
print_string(msg);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
http_client_setopt(client, HTTPCLIENT_OPT_URL, cpe.conn_url);
// Response process main function
do {
// Send SOAP data or empty http ACK, according user setting
TR069_DEBUG("Get SOAP message length %d", len);
if (len > 0) {
// Set private http header, like http type
header = http_client_list_append(header, "Content-Type: text/xml;charset=UTF-8\r\n");
header = http_client_list_append(header, "SOAPAction:\r\n");
http_client_setopt(client, HTTPCLIENT_OPT_HTTPHEADER, header);
// Set post data and length
http_client_setopt(client, HTTPCLIENT_OPT_POSTDATA, msg);
http_client_setopt(client, HTTPCLIENT_OPT_POSTLENGTH, len);
} else {
http_client_setopt(client, HTTPCLIENT_OPT_HTTPHEADER, NULL);
http_client_setopt(client, HTTPCLIENT_OPT_POSTDATA, NULL);
http_client_setopt(client, HTTPCLIENT_OPT_POSTLENGTH, 0);
}
// Call http client perform function
http_client_perform(client);
if (msg) {
tr069_free(msg);
msg = NULL;
}
if (header) {
// Free private HTTP header
http_client_list_destroy(header);
header = NULL;
}
http_client_getinfo(client, HTTPCLIENT_GETINFO_RESPONSE_CODE, &http_response_code);
if (http_response_code != 200 && http_response_code != 204) {
TR069_DEBUG("ACS response is not 'HTTP OK'(%d), break process", http_response_code);
err = -1;
state = 0;
break;
}
// Here will be done post data and receive response
if (response_data == NULL) {
TR069_DEBUG("HTTP client recv null string, break process.");
state = 0;
break;
}
// Cover response to xml tree
xml_result = MrvParseXML(response_data, &err_info);
if (!xml_result) {
TR069_DEBUG("Convert response to xml tree failed!");
break;
}
tr069_free(response_data);
response_data = NULL;
response_len = 0;
// Walk and parse XML tree
walk_and_parse_soap(root, xml_result, &method);
// Free XML tree
TR069_DEBUG("Try free xml tree");
MrvDeleteRoot(xml_result);
if (method == NULL) {
// If can not get rpc method, break process
TR069_DEBUG("Response to rpc method failed, break process.");
state = 0;
break;
}
// Process ACS response according type
TR069_DEBUG("Get RPC method %d", method->type);
fault = 0;
switch (method->type) {
case RPC_TYPE_FAULT:
TR069_ERR("Handle FAULT!!!");
state = 0;
break;
case RPC_TYPE_TRANSFER_COMPLETE_RESPONSE:
case RPC_TYPE_INFORM_RESPONSE: {
// If has inform response, means register succssfully
err = 1;
// continue process and send empty http response
if (private_msg) {
msg = MrvCreateXMLString(private_msg->root, 1, &len);
tr069_msg_destroy(private_msg);
private_msg = NULL;
} else {
len = 0;
}
break;
}
case RPC_TYPE_GET_RPC_METHOD: {
// continue process
TR069_DEBUG("Get RPC method list");
tr069_msg = tr069_build_msg(method->id);
build_get_rpc_method_response(method, tr069_msg);
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
break;
}
case RPC_TYPE_GET_PARAMETER_NAME: {
char * path = method->body.get_param_name.parameter_path;
TR069_DEBUG("Get parameter name");
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:GetParameterNamesResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterList", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", "cwmp:ParameterInfoStruct[!^^!]");
if (path) {
if (is_partial_path(path)) {
struct tr069_obj * p_obj = find_obj(root_obj, path);
if (p_obj) {
tr069_string_prefix = tr069_strdup(path);
modify_prefix_if_need();
walk_obj_and_paramet(p_obj, top_instance(), parameter_name_dup, tr069_msg, 0);
tr069_free(tr069_string_prefix);
tr069_string_prefix = NULL;
} else {
TR069_ERR("failed @%d: %s", __LINE__, path);
fault = 9003;
}
} else {
struct tr069_param * p_parmet = find_param(root_obj, path);
if (p_parmet) {
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", path);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Writable", p_parmet->rw == TR069_R ? "0" : "1");
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack); /* End of ParameterInfoStruct */
} else {
TR069_ERR("failed @%d: %s", __LINE__, path);
fault = 9003;
}
}
} else {
walk_obj_and_paramet(root_obj, NULL, parameter_name_dup, tr069_msg, 0);
}
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (method->body.get_param_name.parameter_path)
tr069_free(method->body.get_param_name.parameter_path);
if (method->body.get_param_name.next_level)
tr069_free(method->body.get_param_name.next_level);
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_GET_PARAMETER_VALUE: {
struct method_get_param_value * p, *temp_p;
TR069_DEBUG("Get parameter value");
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:GetParameterValuesResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterList", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", "cwmp:ParameterValueStruct[!^^!]");
p = method->body.get_param_value;
if (p == NULL) {
// Need response all parameter value
walk_obj_and_paramet(root_obj, NULL, parameter_value_dup, tr069_msg, 0);
}
while (p) {
temp_p = p->next;
TR069_DEBUG(" parameter path %s", p->string);
if (is_partial_path(p->string)) {
struct tr069_obj * p_obj = find_obj(root_obj, p->string);
if (p_obj == NULL) {
TR069_ERR("Find object failed!");
tr069_free(p->string);
tr069_free(p);
p = temp_p;
fault = 9003;
continue;
}
tr069_string_prefix = tr069_strdup(p->string);
modify_prefix_if_need();
walk_obj_and_paramet(p_obj, top_instance(), parameter_value_dup, tr069_msg, 0);
tr069_free(tr069_string_prefix);
tr069_string_prefix = NULL;
} else {
struct tr069_param * p_parameter = find_param(root_obj, p->string);
char * value = NULL;
int get_result;
if ((p_parameter == NULL) || (p_parameter->get_value == NULL)) {
TR069_ERR("Find parameter failed!");
tr069_free(p->string);
tr069_free(p);
p = temp_p;
fault = 9003;
continue;
}
get_result = p_parameter->get_value(top_instance(), &value);
if (get_result) {
TR069_ERR("Get value failed: %s", p->string);
fault = get_result;
}
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", p->string);
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(p_parameter->type));
if (value) tr069_free(value);
pop_soap_node(&tr069_msg->body_stack);
pop_soap_node(&tr069_msg->body_stack); /* End of ParameterInfoStruct */
}
tr069_free(p->string);
tr069_free(p);
p = temp_p;
}
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_SET_PARAMETER_VALUE: {
struct method_set_param_value * p = &method->body.set_param_value;
struct method_set_param_value_value * p_value = p->value, * temp;
int set_parameters_invalid = 0;
TR069_DEBUG("Set parameter value with Parameter key: %s", p->parameter_key);
temp = p_value;
// First check all parameters is valid
while (temp) {
struct tr069_param * p_parameter = find_param(root_obj, temp->name);
if (!p_parameter) {
set_parameters_invalid = 1;
TR069_ERR("Not found avalid parameters!");
fault = 9008;
break;
}
if (!p_parameter->set_value) {
set_parameters_invalid = 1;
TR069_ERR("The parameter not provide set function: %s", temp->name);
fault = 9008;
break;
}
TR069_DEBUG(" set value type is: %s:%s", rpc_type2string(temp->type), rpc_type2string(p_parameter->type));
if (temp->type != p_parameter->type) {
TR069_ERR("bad type!");
set_parameters_invalid = 1;
fault = 9008;
break;
}
temp = temp->next;
}
// Next, set parameters value and free struct. If all parameters is valid.
while (p_value) {
int set_result = 0;
struct tr069_param * p_parameter = find_param(root_obj, p_value->name);
temp = p_value->next;
if (set_parameters_invalid) {
TR069_DEBUG(" just free");
if (p_value->name) tr069_free(p_value->name);
if (p_value->value) tr069_free(p_value->value);
tr069_free(p_value);
p_value = temp;
continue;
}
#if 0
if (!p_parameter) {
TR069_DEBUG("Get parameter failed or no set function(%s)!", p_value->name);
if (p_value->name) tr069_free(p_value->name);
if (p_value->value) tr069_free(p_value->value);
tr069_free(p_value);
p_value = temp;
fault = 9003;
continue;
}
if (!p_parameter->set_value) {
TR069_DEBUG("Get parameter failed or no set function(%s)!", p_value->name);
if (p_value->name) tr069_free(p_value->name);
if (p_value->value) tr069_free(p_value->value);
tr069_free(p_value);
p_value = temp;
fault = 9008;
continue;
}
#endif
set_result = p_parameter->set_value(top_instance(), p_value->value);
if (set_result) fault = set_result;
if (p_value->name) tr069_free(p_value->name);
if (p_value->value) tr069_free(p_value->value);
tr069_free(p_value);
p_value = temp;
}
if (p->parameter_key) tr069_free(p->parameter_key);
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:SetParameterValuesResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Status", "0");
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_GET_PARAMETER_ATTR: {
struct method_get_attribute_value * p, *temp_p;
TR069_DEBUG("Get parameter attribute");
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:GetParameterAttributesResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "ParameterList", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", "cwmp:ParameterAttributeStruct[!^^!]");
p = method->body.get_param_attr;
if (p == NULL) {
// Need response all parameter value
walk_obj_and_paramet(root_obj, NULL, parameter_attr_dup, tr069_msg, 0);
}
while (p) {
temp_p = p->next;
TR069_DEBUG(" parameter path %s", p->string);
if (is_partial_path(p->string)) {
struct tr069_obj * p_obj = find_obj(root_obj, p->string);
if (p_obj == NULL) {
TR069_ERR("Find object failed!");
tr069_free(p->string);
tr069_free(p);
p = temp_p;
fault = 9003;
continue;
}
tr069_string_prefix = tr069_strdup(p->string);
modify_prefix_if_need();
walk_obj_and_paramet(p_obj, NULL, parameter_attr_dup, tr069_msg, 0);
tr069_free(tr069_string_prefix);
tr069_string_prefix = NULL;
} else {
struct tr069_param * p_parameter = find_param(root_obj, p->string);
char buf[5];
if (p_parameter == NULL) {
TR069_ERR("Find parameter failed!");
tr069_free(p->string);
tr069_free(p);
p = temp_p;
fault = 9003;
continue;
}
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", p->string);
pop_soap_node(&tr069_msg->body_stack);
sprintf(buf, "%d", p_parameter->notification);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Notification", buf);
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(p_parameter->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 */
}
tr069_free(p->string);
tr069_free(p);
p = temp_p;
}
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_SET_PARAMETER_ATTR: {
struct method_set_attribute_value * p, *temp_p;
TR069_DEBUG("Set parameter attribute");
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:SetParameterAttributesResponse", NULL);
p = method->body.set_param_attr;
if (p == NULL) {
fault = 9003;
}
while (p) {
temp_p = p->next;
TR069_DEBUG(" parameter path %s", p->name);
if (is_partial_path(p->name)) {
fault = 9003;
} else {
struct tr069_param * p_parameter = find_param(root_obj, p->name);
//char buf[5];
if (p_parameter == NULL) {
TR069_ERR("Find parameter failed!");
fault = 9003;
} else {
// Set new attribute to parameters
if (p->notification_change) {
p_parameter->notification = p->notification;
}
}
}
tr069_free(p->name);
tr069_free(p);
p = temp_p;
}
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_REBOOT: {
// Handle reboot command
// Need call reboot system API
struct method_reboot * reboot_des = &method->body.reboot;
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:RebootResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Event", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ATTR, "SOAP-ENC:arrayType", "cwmp:EventStruct[!^^!]");
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "EventStruct", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "EventCode", "M Reboot");
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "CommandKey", reboot_des->command_key);
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
tr069_set_uci_info(TR069_PSM_MODULE, "acs_mreboot", "1");
post_system_reboot();
break;
}
case RPC_TYPE_FACTORY_RESET: {
// Handle factory reset command
// Need call factory reset system API
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:FactoryResetResponse", NULL);
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
post_factory_reset();
break;
}
case RPC_TYPE_DELETE:
case RPC_TYPE_ADD: {
struct method_add_delete_obj * add_delete;
struct tr069_instance * is = NULL;
struct tr069_obj * obj;
int obj_ret = 0;
add_delete = &method->body.add_delete;
TR069_DEBUG("Add/Delete object with parameter key %s and name %s\n",
add_delete->parameter_key, add_delete->object_name);
obj = find_obj(root_obj, add_delete->object_name);
if (obj) {
// Need add check if object support instance mode
if (method->type == RPC_TYPE_ADD) {
is = malloc_instance(obj, top_instance(), -1);
} else {
is = top_instance();
// Add delete code
}
if (is) {
// Call user object add function
if (obj->add_obj && method->type == RPC_TYPE_ADD)
obj_ret = obj->add_obj(obj, is);
else if (obj->del_obj && method->type == RPC_TYPE_DELETE)
obj_ret = obj->del_obj(obj, is);
} else {
fault = 9003;
}
} else {
fault = 9003;
}
if (obj_ret && is) {
TR069_ERR("Add/Delete object failed...");
free_instance(obj, is);
is = NULL;
fault = obj_ret;
}
tr069_msg = tr069_build_msg(method->id);
if (method->type == RPC_TYPE_ADD) {
char buf[16];
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:AddObjectResponse", NULL);
sprintf(buf, "%d", is ? is->id : -1);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "InstanceNumber", buf);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Status", "0");
} else {
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:DeleteObjectResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Status", "0");
}
if (add_delete->object_name) tr069_free(add_delete->object_name);
if (add_delete->parameter_key) tr069_free(add_delete->parameter_key);
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
if (fault) {
len = 0;
goto failed;
}
break;
}
case RPC_TYPE_DOWNLOAD: {
if (cpe.upgrades_managed == 0) {
fault = 9003;
free_download_method(method);
goto failed;
}
if (handle_download_request(&method->body.download))
{
fault = 9003;
free_download_method(method);
goto failed;
}
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:DownloadResponse", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "Status", "1");
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "StartTime", UNKNOWN_TIME);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "CompleteTime", UNKNOWN_TIME);
pop_soap_node(&tr069_msg->body_stack);
len = 0;
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
// The download method memory will free at 'download complete response func'
break;
}
default:
fault = 9003;
TR069_DEBUG("Get unknown reponse type(%d)!", method->type);
failed:
if (tr069_msg) tr069_msg_destroy(tr069_msg);
tr069_msg = tr069_build_msg(method->id);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "SOAP-ENV:Fault", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "faultcode", "Client");
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "faultstring", "CWMP fault");
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "detail", NULL);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "cwmp:Fault", NULL);
sprintf(temp_buf, "%d", fault);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "FaultCode", temp_buf);
pop_soap_node(&tr069_msg->body_stack);
push_new_soap_node(&tr069_msg->body_stack, SOAP_NODE_TYPE_ELEMENT, "FaultString", fault2string(fault));
// Add code for SetParameterValues RPC call
len = 0;
if (msg) {
tr069_free(msg);
msg = NULL;
}
msg = MrvCreateXMLString(tr069_msg->root, 1, &len);
tr069_msg_destroy(tr069_msg);
tr069_msg = NULL;
}
if (method->id) {
snprintf(cpe.parameter_key, 33, "%s", method->id);
tr069_free(method->id);
}
tr069_free(method);
} while (state);
done:
if (client) http_client_shutdown(client);
if (temp_buf) tr069_free(temp_buf);
response_len = 0;
if (response_data) tr069_free(response_data);
response_data = NULL;
return err;
}
#define MAX_TR069_MSGQ_SIZE 16
int send_tr069_command(struct tr069_task_command * command)
{
TR069_DEBUG("%s,command_id=%d",__FUNCTION__,command->command_id);
TR069_DEBUG("%s,%p",__FUNCTION__,command);
int len=tr069_MsgQSend((void *)&command,MAX_TR069_MSG_SIZE);
assert(len == MAX_TR069_MSG_SIZE);
return 0;
}
/*
static void __send_tr069_command_delay(unsigned int ctx)
{
struct tr069_task_command * command = (struct tr069_task_command *)ctx;
int len=tr069_MsgQSend((void *)&command,MAX_TR069_MSG_SIZE);
assert(len == MAX_TR069_MSG_SIZE);
}
*/
int send_tr069_command_delay(struct tr069_task_command * command, unsigned int delay)
{
TR069_DEBUG("entry %s",__FUNCTION__);
TR069_DEBUG("%s,command_id=%d",__FUNCTION__,command->command_id);
TR069_DEBUG("%s,%p",__FUNCTION__,command);
int ret=tr069_MsgQSend_dealy((void *)command,delay);
TR069_DEBUG("leave %s",__FUNCTION__);
assert(ret == 0);
return 0;
}
int wifi_device_add_trigger(void)
{
struct tr069_task_command * command = NULL;
if (!tr069_feature_enable) return 0;
command = tr069_malloc(sizeof(struct tr069_task_command));
if (command) {
memset(command, 0, sizeof(struct tr069_task_command));
command->command_id = TR069_COMMAND_WIFI_DEVICE_ADD;
return send_tr069_command(command);
}
return 0;
}
int wifi_ssid_change_trigger(void)
{
struct tr069_task_command * command = NULL;
if (!tr069_feature_enable) return 0;
TR069_DEBUG("%s", __func__);
command = tr069_malloc(sizeof(struct tr069_task_command));
if (command) {
memset(command, 0, sizeof(struct tr069_task_command));
command->command_id = TR069_COMMAND_WIFI_SSID_CHANGE;
return send_tr069_command(command);
}
return 0;
}
int ipv4_address_change_trigger(void)
{
struct tr069_task_command * command = NULL;
if (!tr069_feature_enable) return 0;
TR069_DEBUG("%s", __func__);
command = tr069_malloc(sizeof(struct tr069_task_command));
if (command) {
memset(command, 0, sizeof(struct tr069_task_command));
command->command_id = TR069_COMMAND_NEW_IP_ADDRESS;
return send_tr069_command(command);
}
return 0;
}
int post_add_object(const char * path, const char * name)
{
struct tr069_task_command * cmd = NULL;
if (!tr069_feature_enable) return 0;
cmd = tr069_malloc(sizeof(struct tr069_task_command) + 4);
if (cmd) {
memset(cmd, 0, sizeof(struct tr069_task_command));
cmd->command_id = TR069_COMMAND_ADDOBJ;
if (path) cmd->msg = (int)tr069_strdup(path);
if (name) cmd->payload[0] = (int)tr069_strdup(name);
return send_tr069_command(cmd);
}
return -1;
}
int post_system_reboot(void)
{
TR069_DEBUG("enter %s",__FUNCTION__);
/* Will be called in tr069 task context */
struct tr069_task_command * cmd = tr069_malloc(sizeof(struct tr069_task_command));
if (!cmd) {
TR069_ERR("%s: failed", __func__);
return -1;
}
memset(cmd, 0, sizeof(struct tr069_task_command));
cmd->command_id = TR069_COMMAND_REBOOT;
cmd->msg = (unsigned int)__return_address();
TR069_DEBUG("leave %s",__FUNCTION__);
return send_tr069_command(cmd);
}
int post_system_reset(void)
{
/* Will be called in tr069 task context */
struct tr069_task_command * cmd = tr069_malloc(sizeof(struct tr069_task_command));
if (!cmd) {
TR069_ERR("%s: failed", __func__);
return -1;
}
memset(cmd, 0, sizeof(struct tr069_task_command));
cmd->command_id = TR069_COMMAND_RESET;
cmd->msg = (unsigned int)__return_address();
return send_tr069_command(cmd);
}
int post_factory_reset(void)
{
/* Will be called in tr069 task context */
struct tr069_task_command * cmd = tr069_malloc(sizeof(struct tr069_task_command));
if (!cmd) {
TR069_ERR("%s: failed", __func__);
return -1;
}
memset(cmd, 0, sizeof(struct tr069_task_command));
cmd->command_id = TR069_COMMAND_FACTORY_RESET;
cmd->msg = (unsigned int)__return_address();
return send_tr069_command(cmd);
}
int post_delay_func(tr069_delay_cb cb, void * context)
{
/* Will be called in tr069 task context */
struct tr069_task_command * msg = tr069_malloc(sizeof(struct tr069_task_command) + 8);
if (!msg) {
TR069_ERR("%s: Failed", __func__);
return -1;
}
memset(msg, 0, sizeof(struct tr069_task_command) + 8);
msg->command_id = TR069_COMMAND_DELAY_FUNC;
msg->msg = (unsigned int)cb;
msg->payload[0] = (unsigned int)context;
send_tr069_command(msg);
return 0;
}
struct tr069_helper_run_context * malloc_helper_context(void)
{
struct tr069_helper_run_context * context =
tr069_malloc(sizeof(struct tr069_helper_run_context));
if (context) {
memset(context, 0 , sizeof(sizeof(struct tr069_helper_run_context)));
}
return context;
}
void free_helper_context(struct tr069_helper_run_context * context)
{
context->sem = NULL;
tr069_free(context);
}
int post_to_helper(struct tr069_helper_run_context * context)
{
UNUSED(context);
TR069_DEBUG("%s", __func__);
return 0;
}
static int __tr069_factory_reset(struct tr069_helper_run_context * context) {
// Will run in 'Device management context'
TR069_DEBUG("%s", __func__);
context->result = tr069_malloc(64);
if (context->result) {
int ret=0;
memset(context->result, 0, 64);
TR069_DEBUG("enter %s",__FUNCTION__);
ret=tr069_router_factory_reset();
TR069_DEBUG("%s: result %d", __func__, ret);
}
return 0;
}
static int tr069_system_reset() {
TR069_DEBUG("enter %s",__FUNCTION__);
tr069_set_uci_info(TR069_PSM_MODULE,TR069_PSM_TAG_BOOT_STATE,"0");
tr069_router_reboot();
return TR069_OK;
}
static int tr069_factory_reset() {
struct tr069_helper_run_context * context = malloc_helper_context();
if (context) {
context->block = 1;
context->cb = __tr069_factory_reset;
post_to_helper(context);
if (context->result) {
tr069_free(context->result);
}
free_helper_context(context);
return TR069_OK;
}
return TR069_9003;
}
struct static_instance {
const char * path;
const char * name;
const char * default_value;
};
static struct static_instance si[] = {
{"Device.WiFi.SSID.", NULL, "true"},
{"Device.WiFi.AccessPoint.", NULL, "true"},
{"Device.Ethernet.Interface.", "LTE", NULL},
{"Device.DNS.Client.Server.", NULL, "true"},
};
static int init_static_instance()
{
int total = sizeof(si) / sizeof(struct static_instance);
char * temp = tr069_malloc(256);
int i;
for (i = 0; i < total; i++) {
struct tr069_instance * is;
int id;
const char * path = si[i].path;
const char * name = si[i].name;
id = rpc_add_obj_api(path, -1, &is);
if (name) {
// The TR181 interface object must contain 'Name'
if (temp) {
struct tr069_param * parameter;
snprintf(temp, 256, "%s%d.Name", path, id);
//TR069_DEBUG("Try find parameter: %s", temp);
parameter = find_param(root_obj, temp);
if (parameter && parameter->set_value) {
//TR069_DEBUG(" Set value %s", name);
parameter->set_value(top_instance(), (char *)name);
}
snprintf(temp, 256, "%s%d.Enable", path, id);
parameter = find_param(root_obj, temp);
//TR069_DEBUG("Try find parameter: %s", temp);
if (parameter && parameter->set_value && si[i].default_value) {
//TR069_DEBUG(" Set value %s", "true");
parameter->set_value(top_instance(), (char *)(si[i].default_value));
}
}
}
}
#define MAX_MO_PDP_NUMBER 10
for (i = 0; i < MAX_MO_PDP_NUMBER; i++) {
struct tr069_instance * is;
int id = rpc_add_obj_api("Device.IP.Interface.", -1, &is);
if (id > 0) {
snprintf(temp, 256, "Device.IP.Interface.%d.IPv4Address.", id);
rpc_add_obj_api(temp, -1, &is);
}
if (id > 0) {
snprintf(temp, 256, "Device.IP.Interface.%d.IPv6Address.", id);
rpc_add_obj_api(temp, -1, &is);
}
}
tr069_free(temp);
temp = NULL;
return 0;
}
extern int tr069_update_assoiated_device(void);
static unsigned int handle_tr069_command(struct tr069_task_command * command)
{
TR069_DEBUG("enter %s,ID=%d",__FUNCTION__,command->command_id);
switch (command->command_id) {
case TR069_COMMAND_IP_CHANGE: {
// TODO: Need add code
return 0;
}
case TR069_COMMAND_STUN_CHANGE: {
unsigned int * p = (unsigned int *)command->msg;
cpe.local_address = p[0];
cpe.udp_port = p[1];
struct in_addr temp_addr;
temp_addr.s_addr=cpe.local_address;
TR069_DEBUG("Handle new ip %s with port %d from stun",
inet_ntoa(temp_addr), cpe.udp_port);
cpe.nat_detect = 1;
set_tr069_event(TR069_EVENT_M_CHANGE_DU_STATE, "");
return 1;
}
case TR069_COMMAND_REQUEST_CONNECT: {
TR069_DEBUG("Handle ACS request connect...");
set_tr069_event(TR069_EVENT_CONNECTION_REQUEST, "");
return 1;
}
case TR069_COMMAND_DOWNLOAD_TRIGGER: {
TR069_DEBUG("%s: TR069_COMMAND_DOWNLOAD_TRIGGER", __FUNCTION__);
process_download_request((struct method_download *)command->msg, 1);
return 0;
}
case TR069_COMMAND_DOWNLOAD_COMPLETE: {
TR069_DEBUG("%s: TR069_COMMAND_DOWNLOAD_COMPLETE", __FUNCTION__);
char * psm_string=NULL;
psm_string=tr069_get_uci_info(TR069_PSM_MODULE,"tr069","dimcomplete");
unsigned int command_id = 0;
char temp_buf[64] = {0};
if (psm_string){
TR069_DEBUG("%s: get dimcomplete: %s",__FUNCTION__, psm_string);
memset(temp_buf, 0, 64);
sscanf(psm_string, "[%d]", &command_id);
//command_id=atoi(temp_buf);
if (command_id != 0) {
snprintf(temp_buf, 64, "%d", command_id);
}
TR069_DEBUG("%s: temp_buf %s",__FUNCTION__,temp_buf);
private_msg = (struct tr069_msg *)(command->msg);
set_tr069_event(TR069_EVENT_M_DOWNLOAD, temp_buf);
set_tr069_event(TR069_EVENT_TRANSFER_COMPLETE, temp_buf);
tr069_free(psm_string);
}
return 1;
}
case TR069_COMMAND_REBOOT: {
TR069_DEBUG("Handle reboot command sender %x", command->msg);
tr069_router_reboot();
return 0;
}
case TR069_COMMAND_RESET: {
TR069_DEBUG("Handle reset...");
tr069_system_reset();
return 0;
}
case TR069_COMMAND_FACTORY_RESET: {
TR069_DEBUG("Handle factory reset...");
tr069_factory_reset();
return 0;
}
case TR069_COMMAND_DELAY_FUNC: {
tr069_delay_cb cb = (tr069_delay_cb)command->msg;
TR069_DEBUG("Handle dleay function %p", cb);
cb((void *)command->payload[0]);
return 0;
}
case TR069_COMMAND_ADDOBJ: {
char * path = (char *)command->msg;
char * name = (char *)command->payload[0];
struct tr069_instance * is;
int id = 0;
if(path){
id = rpc_add_obj_api(path, -1, &is);
if (id < 0) {
TR069_ERR("AddObject failed!(%s)", path);
} else {
if (name) {
// The TR181 interface object must contain 'Name'
char * temp = tr069_malloc(256);
if (temp) {
struct tr069_param * parameter;
snprintf(temp, 256, "%s%d.Name", path, id);
TR069_DEBUG("Try find parameter: %s", temp);
parameter = find_param(root_obj, temp);
if (parameter && parameter->set_value) {
TR069_DEBUG(" Set value %s", name);
parameter->set_value(top_instance(), name);
}
snprintf(temp, 256, "%s%d.Enable", path, id);
parameter = find_param(root_obj, temp);
TR069_DEBUG("Try find parameter: %s", temp);
if (parameter && parameter->set_value) {
TR069_DEBUG(" Set value %s", "true");
parameter->set_value(top_instance(), "true");
}
tr069_free(temp);
temp = NULL;
}
}
// TODO: Test code
}
}
if (path) tr069_free(path);
if (name) tr069_free(name);
return 0;
}
case TR069_COMMAND_WIFI_DEVICE_ADD:
tr069_update_assoiated_device();
return 0;
case TR069_COMMAND_WIFI_SSID_CHANGE: {
#define WIFI_SSID_PATH "Device.WiFi.SSID.1.SSID"
struct tr069_parameter_change_list_struct * temp;
temp = tr069_malloc(sizeof(struct tr069_parameter_change_list_struct));
if (temp) {
struct tr069_param * param;
snprintf(&temp->parameter_name[0], 200, "%s", WIFI_SSID_PATH);
temp->next = tr069_parameter_change_list;
tr069_parameter_change_list = temp;
TR069_DEBUG("Insert to next info parameter list");
sleep(1); // Wait 1 sec... for WIFI SSID sync to PSM
param = find_param(root_obj, WIFI_SSID_PATH);
if (param && param->notification == TR069_ACTIVE_NOTIFICATION) {
set_tr069_event(TR069_EVENT_VALUE_CHANGE, "");
return 1; // Create session immediately
} else {
return 0; // If parameter not present or notification off, will free struct in next acs inform
}
} else {
TR069_ERR("malloc for SSID notify failed");
return 0;
}
}
case TR069_COMMAND_NEW_IP_ADDRESS: {
#define DEVICE_CONNECTION_REQUEST_URL_PATH "Device.ManagementServer.ConnectionRequestURL"
//1TODO: Now, ConnectionRequestURL in inform list, so not need insert to change_list
//1TODO: So, currently only check notification property, if active then set event to ValueChange
//struct tr069_parameter_change_list_struct * temp;
//temp = malloc(sizeof(struct tr069_parameter_change_list_struct));
if (1) {
struct tr069_param * param;
//snprintf(&temp->parameter_name[0], 200, "%s", DEVICE_CONNECTION_REQUEST_URL_PATH);
//temp->next = tr069_parameter_change_list;
//tr069_parameter_change_list = temp;
//TR069_DEBUG("Insert to next info parameter list");
param = find_param(root_obj, DEVICE_CONNECTION_REQUEST_URL_PATH);
if (param && param->notification == TR069_ACTIVE_NOTIFICATION) {
set_tr069_event(TR069_EVENT_VALUE_CHANGE, "");
return 1; // Create session immediately
} else {
return 0; // If parameter not present or notification off, will free struct in next acs inform
}
} else {
TR069_ERR("malloc for connection request URL notify failed");
return 0;
}
}
default:
TR069_ERR("Unknow command %d", command->command_id);
return 0;
}
}
static char oui[8] = {0};
int tr069_build_oui(void)
{
int oui_try_cnt = 3;
unsigned char buf[6];
while (oui_try_cnt)
{
if (GetWiFiInitStat())
{
if (tr069_get_wifi_mac((char *)buf))
{
TR069_ERR("Get OUI try cnt(%d)", oui_try_cnt);
} else {
int i = 0;
for (i = 0; i < 3; i++) {
sprintf(&oui[i*2], "%02x", buf[i]);
}
oui[6] = '\0';
tr069_oui = oui;
TR069_DEBUG("Get OUI result: %s", tr069_oui);
return 0;
}
}
oui_try_cnt--;
sleep(1);
}
if(oui_try_cnt==0){
if (tr069_get_br_lan_mac((char *)buf))
{
TR069_ERR("Get OUI failed(%d)", oui_try_cnt);
} else {
int i = 0;
for (i = 0; i < 3; i++) {
sprintf(&oui[i*2], "%02x", buf[i]);
}
oui[6] = '\0';
tr069_oui = oui;
TR069_DEBUG("Get OUI result: %s", tr069_oui);
return 0;
}
}
return -1;
}
static unsigned int retry_timer[] = {
(20 * 1000 / 5),
(35 * 1000 / 5),
(60 * 1000 / 5),
(90 * 1000 / 5),
(180 * 1000 / 5),
(320 * 1000 / 5),
(640 * 1000 / 5),
(1280 * 1000 / 5),
(5120 * 1000 / 5),
};
char IMEI_WEB[MAX_SIM_INFO_STR_LEN] = {0};
static int retry_index = 0;
#define MAX_RETRY_COUNT (sizeof(retry_timer)/sizeof(unsigned int))
extern void tr069_wps_notify_cb(unsigned char state);
static int tr069_wait_network_ready()
{
ENTER();
struct tr069_usock_head receive_msg;
int read_len;
#ifdef __TR069_DEBUG__
UNUSED(receive_msg);
UNUSED(read_len);
return 0;
#else
loop:
read_len = read(tr069_client_fd.fd, &receive_msg, sizeof(struct tr069_usock_head));
if(receive_msg.get_id!=TR069_GET_NETWORK_STATUS_ID)
{
goto loop;
}
TR069_DEBUG("%s,network ready:len = %d,id=%d",__FUNCTION__,read_len,receive_msg.get_id);
return 0;
#endif
}
static void * tr069_task(void *data)
{
UNUSED(data);
tr069_client_fd.fd = usock(USOCK_UNIX, TR069_INNER_CONN_SOCKET, NULL);
if (tr069_client_fd.fd < 0) {
TR069_ERR("%s,Failed to connect to server\n",__FUNCTION__);
return NULL;
}
/*
struct timeval timeout_usock={5,0};
int ret = setsockopt(tr069_client_fd.fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_usock, sizeof(struct timeval));
if (ret < 0) {
TR069_ERR("tr069_client_fd.fd set tcp recv timeout failed(%d)", ret);
}
*/
TR069_INFO("%s,client fd %d", __FUNCTION__,tr069_client_fd.fd);
unsigned int timeout = 0;
struct tr069_task_command * msg = NULL;
unsigned int inform = 0, event = 0, boot_state = 0, mboot = 0;
TR069_DEBUG("Data: %s %s\n", __DATE__, __TIME__);
tr069_set_firewall_uci_info();
cpe.enable = 1;
cpe.CWMPRetryIntervalMultiplier = 2000;
cpe.CWMPRetryMiniWaitInterval = 5;
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *opt_val = NULL;
if(tr069_MsgQconnect()==-1)
{
return NULL;
}
tr069_wait_network_ready();
local_ctx = (struct uci_context*)uci_tr069_ctx_get();
if (!local_ctx)
{
assert(0);
}
uci_foreach_element(&local_ctx->root, e)
{
if (strcmp(e->name, TR069_PSM_MODULE) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p)
{
uci_load(local_ctx, TR069_PSM_MODULE, &p);
}
if(p)
{
uci_foreach_element(&p->sections, e)
{
uci_sec = uci_to_section(e);
if(strcmp(uci_sec->type, "tr069") == 0)
{
/*dimcomplete*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dimcomplete");
if(opt_val && strcmp(opt_val, "0"))
{
TR069_INFO("dimcomplete message valid\n");
if (1 != sscanf(opt_val, "[%d]", &imcomplete_id)) {
TR069_ERR("imcomplete message parse failed!\n");
imcomplete_id = 0;
}
}
/*boot_state*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_BOOT_STATE);
if(opt_val && (strcmp(opt_val, "1") == 0))
{
boot_state=1;
}
TR069_DEBUG("dimcomplete:%d boot_state:%d\n",imcomplete_id,boot_state);
/*acs_mreboot*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "acs_mreboot");
if(opt_val && (strcmp(opt_val, "1") == 0))
{
mboot = 1;
tr069_set_uci_info(TR069_PSM_MODULE,"acs_mreboot","0");
}
TR069_DEBUG("got the tr069 acs_mreboot:%s\n",opt_val);
// Start Inform ACS with bootup
if (boot_state) {
set_tr069_event(TR069_EVENT_BOOT, "");
if (mboot){
set_tr069_event(TR069_EVENT_M_REBOOT, "");
} else {
set_tr069_event(TR069_EVENT_BOOTSTRAP, "");
}
}
/*username*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_CONNECT_REQUEST_NAME);
if(opt_val)
{
snprintf(cpe.conn_req_username, 32, "%s", opt_val);
}
/*password*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_CONNECT_REQUEST_PSW);
if(opt_val)
{
strncpy(cpe.password, opt_val,32);
}
TR069_DEBUG("Get connection username:%s password:%s\n", cpe.conn_req_username,cpe.password);
/*ACS URL*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_ACSURL);
if (opt_val) {
strncpy(cpe.conn_url, opt_val,90);
} else {
strncpy(cpe.conn_url, tr069_acs_url,90);
}
/*acs_username*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_ACSUSERNAME);
if (opt_val) {
strncpy(cpe.username, opt_val,32);
} else {
strncpy(cpe.username, tr069_acs_username,32);
}
/*ACS password*/
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_ACSUSERPASSWORD);
if (opt_val) {
strncpy(cpe.password, opt_val,32);
} else {
strncpy(cpe.password, tr069_acs_password,32);
}
TR069_DEBUG("Get ACS URL:[%s] username:[%s] password[%s]\n",
cpe.conn_url,
cpe.username,
cpe.password);
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_INFORM_ENABLE);
if (opt_val) {
cpe.periodic_inform_enable = atoi(opt_val);
} else {
cpe.periodic_inform_enable = tr069_periodic_inform_enable;
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, TR069_PSM_TAG_INFORM_INTERVAL);
if (opt_val) {
TR069_DEBUG("Get INFORM INTERVAL from uci %s\n", opt_val);
cpe.periodic_inform_interval = atoi(opt_val);
} else {
cpe.periodic_inform_interval = tr069_periodic_inform_interval;
}
TR069_DEBUG("Get INFORM enable[%d] interval[%d]\n",
cpe.periodic_inform_enable,
cpe.periodic_inform_interval);
break;
}
}
}
free_tr069_uci_ctx();
strcpy(cpe.parameter_key, "1234");
cpe.upgrades_managed = 1;
cpe.connect_request_path = tr069_connect_request_path;
strncpy(cpe.stun_server, stun_server_address,64);
cpe.stun_server_port = stun_server_port;
cpe.stun_enable = stun_enable;
cpe.stun_max_period = cpe.stun_min_period = stun_interval;
sleep(4);
if (!tr069_serial_number) {
memset(IMEI_WEB,0,MAX_SIM_INFO_STR_LEN);
int res=tr069_get_imei_from_ril(IMEI_WEB);
//sint res = TR069_FAIL;
if(res == TR069_SUCCESS){
TR069_DEBUG("Use IMEI:%s",IMEI_WEB);
tr069_serial_number = (const char *)IMEI_WEB;
}else
{
TR069_DEBUG("Use default SN");
tr069_serial_number = "5883900";
}
}
// Wait network prepare... Maybe need change
init_static_instance();
sleep(4);
if (tr069_oui == NULL) {
tr069_build_oui();
tr069_oui = oui;
}
do {
int err = 0;
// Recv signal event and process
if (msg) {
// Handle message, like download complete or other situation
event = handle_tr069_command(msg);
if (event) {
inform = 1;
}
} else {
inform = 1;
if (cpe.bootstarp_flag) set_tr069_event(TR069_EVENT_PERIODIC, "");
}
if (!cpe.bootstarp_flag) {
if (boot_state) {
set_tr069_event(TR069_EVENT_BOOT, "");
if (mboot) set_tr069_event(TR069_EVENT_M_REBOOT, "");
} else {
set_tr069_event(TR069_EVENT_BOOTSTRAP, "");
}
}
if (inform) {
err = process_main_tr069_event();
if (err < 0) {
TR069_ERR("[tr069]tr069 main event process failed...");
} else if (err > 0) {
TR069_DEBUG("[tr069]Handle at least one HTTP OK");
cpe.bootstarp_flag = 1;
if (!boot_state) {
tr069_set_uci_info(TR069_PSM_MODULE,TR069_PSM_TAG_BOOT_STATE,"1");
}
} else {
}
}
// Clear msg and wait new...
if (msg) {
if (msg->tsk_cmd_cb) msg->tsk_cmd_cb(msg, err);
tr069_free(msg);
msg = NULL;
}
// If periodic inform enabled, recv signal event and timeout
timeout = cpe.periodic_inform_enable ?
(cpe.periodic_inform_interval * 1000 / 5) : 0;
TR069_DEBUG("Inform is %s, timeout %u",
cpe.periodic_inform_enable ? "enable" : "disable",
cpe.periodic_inform_enable ? cpe.periodic_inform_interval : 0);
inform = 0;
if (private_msg) {
tr069_msg_destroy(private_msg);
private_msg = NULL;
}
if (!cpe.bootstarp_flag) {
timeout = retry_timer[retry_index++];
if ((unsigned int)retry_index >= MAX_RETRY_COUNT) {
retry_index = MAX_RETRY_COUNT - 1;
}
}
tr069_MsgQRecv((void *)&msg, MAX_TR069_MSG_SIZE, timeout);
} while (1);
}
static pthread_t s_tid_StunTask;
extern void * stun_task(void * data);
void stun_init(void)
{
int ret = 0;
ret = pthread_create(&s_tid_StunTask, NULL, stun_task, NULL);
if(ret < 0){
TR069_ERR("Failed to create stun_task thread, ret:%d",ret);
return;
}
}
static pthread_t s_tid_tr069Server;
void tr069_init(void)
{
if(tr069_feature_enable)
{
TR069_DEBUG("tr069_init...");
int ret = 0;
ret = pthread_create(&s_tid_tr069Server, NULL, tr069_task, NULL);
if(ret < 0){
TR069_ERR("Failed to create tr069_task thread, ret:%d",ret);
return;
}
tr069_MsgQCreate();
stun_init();
}
}