/******************************************************************************
* Copyright (c) 2018-2018 TP-Link Systems Inc.
*
* Filename: tds_passthrough.c
* Version: 1.0
* Description: TDS请求中,与透传相关的指令处理接口
* Author: liyijie<liyijie@tp-link.com.cn>
* Date: 2019-02-15
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "onvif_passthrough.h"
#include "soap_parse.h"
#include "soap_pack.h"
#include "soap_auth.h"
#include "soap_tds.h"
#define REBOOT_MSG "Rebooting in 30 seconds"
#ifndef ARRAY_LEN
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*********************************************************************************
* tds:SetSystemDateAndTime
*********************************************************************************/
/******************************************************************************
* 函数名称: soap_out_tds_set_sys_time_rsp()
* 函数描述: 组装tds:SetSystemDateAndTimeResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_sys_time_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetSystemDateAndTimeResponse */
if (xml_buf == NULL)
{
ONVIF_WARN("xml_buf == NULL.");
return ERROR;
}
/* tds:SetSystemDateAndTimeResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetSystemDateAndTimeResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_sys_time_rsp()
* 函数描述: tds:SetSystemDateAndTime请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_sys_time_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetSystemDateAndTime rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_sys_time_rsp), soap, NULL);
}
LOCAL BOOL cloud_storage_on()
{
CSTG_UPLOAD_ENABLE cstg_upload_enable = {0};
ds_read(CSTG_UPLOAD_ENABLE_PATH, &cstg_upload_enable, sizeof(CSTG_UPLOAD_ENABLE));
return cstg_upload_enable.enable;
}
LOCAL int check_onvif_set_sys_time(TT_DATE_TIME *time)
{
if (time == NULL || time->second < 0 || time->second >= 60 || time->minute < 0 || time->minute >= 60
|| time->hour < 0 || time->hour >=24 || time->day < 0 || time->month < 0 || time->month > 12
|| time->year < 0)
{
return ERROR;
}
switch (time->month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (time->day > 31)
{
return ERROR;
}
break;
case 4:
case 6:
case 9:
case 11:
if (time->day > 30)
{
return ERROR;
}
break;
case 2:
if (time->year % 400 == 0 || (time->year % 4 == 0 && time->year % 100 != 0))
{
if (time->day > 29)
{
return ERROR;
}
}
else
{
if (time->day > 28)
{
return ERROR;
}
}
default:
return ERROR;
}
return OK;
}
/******************************************************************************
* 函数名称: tds_set_sys_time_req_parse()
* 函数描述: 解析tds:SetSystemDateAndTime请求的具体内容
* 输 入: soap -- soap结构体
* 输 出: json_req -- 根据请求构造的json object
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_sys_time_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
TIMING_MODE timing_mode = 0;
TT_DATE_TIME time = {0};
time_t sec_from_1970 = 0;
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
JSON_OBJ *json_opt2 = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO] = {0};
char time_zone[LEN_INFO] = {0};
TIME_CALIBRATION time_cali = {0};
int dst_enabled = 0;
int have_dst_rule = 0;
char *find_rule;
int ret_stime = 0;
int set_timezome = 0;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetSystemDateAndTime parse.");
/* 需确认是否支持onvif设置系统时间和日期 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetSystemDateAndTime请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_WARN("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "DateTimeType"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tds:DateTimeType: %s", charbuf);
timing_mode = (strcmp(charbuf, "NTP") == 0) ? TIMING_MODE_NTP : TIMING_MODE_MANUAL;
continue;
}
if (TRUE == soap_match_tag(charbuf, "DaylightSavings"))
{
/* 暂不需要同步DaylightSavings */
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tds:DaylightSavings: %s", charbuf);
dst_enabled = (strcmp(charbuf, "true") == 0) ? 1 : 0;
continue;
}
if (TRUE == soap_match_tag(charbuf, "TimeZone"))
{
/* 暂不需要同步时区 */
continue;
}
if (TRUE == soap_match_tag(charbuf, "TZ"))
{
/* 暂不需要同步时区 */
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tds:TZ: %s", charbuf);
if (0 == strncmp(charbuf, "INVALIDTIMEZONE", 15))
{
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:InvalidTimeZone", "error timezone");
soap->error = SOAP_FAULT;
goto error_parse;
}
/* PST,UTC-08:00只用于适配过onvif认证 */
else if (!strncmp(charbuf, "PST", 3) || !strncmp(charbuf, "UTC-08:00", 9))
{
set_timezome = 1;
strncpy(time_zone, charbuf, LEN_INFO - 1);
}
find_rule = strstr(charbuf,",");
if (find_rule != NULL)
{
have_dst_rule = 1;
}
else
{
have_dst_rule = 0;
}
continue;
}
if (TRUE == soap_match_tag(charbuf, "UTCDateTime"))
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "Time"))
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "Hour"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Hour: %s", charbuf);
time.hour = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Minute"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Minute: %s", charbuf);
time.minute = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Second"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Second: %s", charbuf);
time.second = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Date"))
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "Year"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Year: %s", charbuf);
time.year = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Month"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Month: %s", charbuf);
time.month = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Day"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("tt:Day: %s", charbuf);
time.day = atoi(charbuf);
continue;
}
}
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
json_opt2 = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL || json_opt2 == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
jso_free_obj(json_opt);
jso_free_obj(json_opt2);
return ERROR;
}
jso_add_string(json_obj, "method", "set");
jso_obj_add(json_obj, "system", json_sec);
jso_obj_add(json_sec, "basic", json_opt);
jso_obj_add(json_sec, "dst", json_opt2);
if (set_timezome)
{
ONVIF_WARN("set timezome");
jso_add_string(json_opt, "timezone", time_zone);
jso_add_string(json_opt, "zone_id", "America/Los_Angeles"); /* UTC-08:00对应的唯一地区 */
}
if (timing_mode == TIMING_MODE_NTP || cloud_storage_on())
{
jso_add_string(json_opt, "timing_mode", "ntp");
}
else
{
jso_add_string(json_opt, "timing_mode", "manual");
if (check_onvif_set_sys_time(&time) == ERROR)
{
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:InvalidDateTime", "error time");
soap->error = SOAP_FAULT;
goto error_out;
}
/* 同步时间 */
sec_from_1970 = soap_mk_time(time.year, time.month, time.day,
time.hour, time.minute, time.second);
/* --946656000=2000/1/1 0:0:0 */
if (sec_from_1970 < 946656000)
{
ONVIF_TRACE("set time < 2000/1/1 0:0:0.");
goto error_out;
}
ret_stime = nvmp_set_time(sec_from_1970, USER_CALIBRATION);
if (OK == ret_stime)
{
ONVIF_DEBUG("set time successfully.");
/* nvr设置为手动校时,校时成功后发手动校时成功消息出来 */
time_cali.type = USER_CALIBRATION;
time_cali.status = TIME_CALIBRATION_SUCC;
NSD_SEND(TIME_CALIBRATION_MSG_ID, (U8*)&time_cali, sizeof(TIME_CALIBRATION));
}
else
{
ONVIF_ERROR("set time error: %d", ret_stime);
}
}
/* 还需要添加夏令时的enabled进入json_obj里,等到夏令时模块添加后再加相关代码 */
if (dst_enabled && have_dst_rule)
{
jso_add_string(json_opt2, "enabled", "1");
}
else
{
jso_add_string(json_opt2, "enabled", "0");
}
*json_req = json_obj;
return OK;
error_out:
jso_free_obj(json_obj);
error_parse:
return ERROR;
}
/*********************************************************************************
* tds:SetSystemFactoryDefault
*********************************************************************************/
/******************************************************************************
* 函数名称: soap_out_tds_set_sys_factory_default_rsp()
* 函数描述: 组装tds:SetSystemFactoryDefaultResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_sys_factory_default_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetSystemFactoryDefaultResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetSystemFactoryDefaultResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetSystemFactoryDefaultResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_sys_factory_default_json_to_xml()
* 函数描述: tds:SetSystemFactoryDefault请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_sys_factory_default_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetSystemFactoryDefault rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_sys_factory_default_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_sys_factory_default_xml_to_json()
* 函数描述: 解析tds:SetSystemFactoryDefault请求的具体内容
* 输 入: soap -- soap结构体
* 输 出: json_req -- 根据请求构造的json object
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_sys_factory_default_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetSystemFactoryDefault parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 不需要分析SetSystemFactoryDefault请求的具体内容 */
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
if (json_obj == NULL || json_sec == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
return ERROR;
}
jso_add_string(json_obj, "method", "do");
jso_obj_add(json_obj, "system", json_sec);
jso_add_string(json_sec, "reset", "null");
*json_req = json_obj;
return OK;
}
/*********************************************************************************
* tds:SystemReboot
*********************************************************************************/
/******************************************************************************
* 函数名称: soap_out_tds_sys_reboot_rsp()
* 函数描述: 组装tds:SystemRebootResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_sys_reboot_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SystemRebootResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SystemRebootResponse begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "tds:SystemRebootResponse", NULL));
/* tds:Message */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:Message", REBOOT_MSG, NULL));
/* tds:SystemRebootResponse end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "tds:SystemRebootResponse"));
return OK;
}
/******************************************************************************
* 函数名称: tds_sys_reboot_json_to_xml()
* 函数描述: tds:SystemReboot请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_sys_reboot_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SystemReboot rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_sys_reboot_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_sys_reboot_xml_to_json()
* 函数描述: 解析tds:SystemReboot请求的具体内容
* 输 入: soap -- soap结构体
* 输 出: json_req -- 根据请求构造的json object
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_sys_reboot_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SystemReboot parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 不需要分析SetSystemFactoryDefault请求的具体内容 */
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
if (json_obj == NULL || json_sec == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
return ERROR;
}
jso_add_string(json_obj, "method", "do");
jso_obj_add(json_obj, "system", json_sec);
jso_add_string(json_sec, "reboot", "null");
*json_req = json_obj;
return OK;
}
/*********************************************************************************
* tds:SetUser
*********************************************************************************/
/******************************************************************************
* 函数名称: soap_out_tds_set_dns_rsp()
* 函数描述: 组装tds:SetDNSResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_dns_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetDNSResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetDNSResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetDNSResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_dns_json_to_xml()
* 函数描述: tds:SetDNS请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_dns_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetDNS rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_dns_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: soap_out_tds_set_ntp_rsp()
* 函数描述: 组装tds:SetNTPResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_ntp_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetDNSResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetDNSResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetNTPResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_ntp_json_to_xml()
* 函数描述: tds:SetNTP请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_ntp_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
S32 error_code = 0;
if (soap == NULL || NULL == json_rsp)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNTP rsp.");
if (OK != jso_obj_get_int(json_rsp, "error_code", &error_code))
{
ONVIF_TRACE("no error code");
return ERROR;
}
if (0 != error_code)
{
ONVIF_TRACE("get information error, error_code = [%d]", error_code);
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:ConfigModify", "failed");
soap->error = SOAP_FAULT;
return ERROR;
}
return soap_generate_xml((p_out_fun)(soap_out_tds_set_ntp_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_dns_xml_to_json()
* 函数描述: tds:SetDNS请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_dns_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO * 2] = {0};
char temp_dns[2][STR_IP_LEN] = {{0}};
BOOL DHCP_flag = FALSE;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetDNS parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetDNS请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "FromDHCP"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("FromDHCP: %s", charbuf);
if (0 == strcasecmp(charbuf, "True"))
{
DHCP_flag = TRUE;
}
}
if (TRUE == soap_match_tag(charbuf, "IPv4Address"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("IPv4Address: %s", charbuf);
if ('\0' == temp_dns[0][0])
{
snprintf(temp_dns[0], STR_IP_LEN, "%s", charbuf);
}
else if ('\0' == temp_dns[1][0])
{
snprintf(temp_dns[1], STR_IP_LEN, "%s", charbuf);
}
}
}
ONVIF_INFO("Set dns(dhcp %s):%s, %s", DHCP_flag ? "on" : "off", temp_dns[0], temp_dns[1]);
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
jso_free_obj(json_opt);
goto error_parse;
}
jso_add_string(json_obj, "method", "set");
jso_obj_add(json_obj, "protocol", json_sec);
jso_obj_add(json_sec, "wan", json_opt);
if (TRUE == DHCP_flag)
{
jso_add_string(json_opt, "wan_type", "dhcp");
jso_add_string(json_opt, "proto", "dhcp");
}
else
{
jso_add_string(json_opt, "wan_type", "static");
jso_add_string(json_opt, "proto", "static");
json_opt = jso_new_obj();
jso_obj_add(json_sec, "static", json_opt);
if ('\0' != temp_dns[0][0])
{
jso_add_string(json_opt, "pri_dns", temp_dns[0]);
}
if ('\0' != temp_dns[1][0])
{
jso_add_string(json_opt, "snd_dns", temp_dns[1]);
}
}
*json_req = json_obj;
return OK;
error_parse:
return ERROR;
}
/******************************************************************************
* 函数名称: tds_set_ntp_xml_to_json()
* 函数描述: tds:SetNTP请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_ntp_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_sec2 = NULL;
JSON_OBJ *json_opt = NULL;
JSON_OBJ *json_opt2 = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO] = {0};
char ip_addr[LEN_VALUE] = {0};
BOOL have_dhcp = FALSE;
BOOL dhcp_flag = FALSE;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNTP parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetNetworkInterfaces请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "no content");
soap->error = SOAP_FAULT;
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "FromDHCP"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
have_dhcp = TRUE;
if (0 == strcasecmp(charbuf, "true"))
{
dhcp_flag = TRUE;
}
}
else if (TRUE == soap_match_tag(charbuf, "Type"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Type: %s.", charbuf);
if (strcasecmp(charbuf, "IPv4"))
{
ONVIF_ERROR("IP Type: %s is not supported.", charbuf); /* IPv6设置NTP IP也用该函数,暂未支持,此处先做打印提示 */
}
}
else if (TRUE == soap_match_tag(charbuf, "IPv4Address"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("IPv4Address: %s.", charbuf);
snprintf(ip_addr, LEN_VALUE, "%s", charbuf);
}
}
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_ERROR("jso_new_obj error.");
goto error_parse;
}
jso_add_string(json_obj, "method", "set");
if(have_dhcp)
{
json_sec2 = jso_new_obj();
json_opt2 = jso_new_obj();
if (json_sec2 == NULL || json_opt2 == NULL)
{
ONVIF_ERROR("jso_new_obj error.");
goto error_parse;
}
jso_obj_add(json_obj, "network", json_sec2);
jso_obj_add(json_sec2, "wan_status", json_opt2);
if (TRUE == dhcp_flag)
{
jso_add_string(json_opt2, "proto", "dhcp");
}
else
{
jso_add_string(json_opt2, "proto", "static");
}
}
jso_obj_add(json_obj, "system", json_sec);
jso_obj_add(json_sec, "ntp", json_opt);
jso_add_string(json_opt, "server", ip_addr);
*json_req = json_obj;
return OK;
error_parse:
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "error");
soap->error = SOAP_FAULT;
jso_free_obj(json_opt);
jso_free_obj(json_opt2);
jso_free_obj(json_sec2);
jso_free_obj(json_sec);
jso_free_obj(json_obj);
return ERROR;
}
/******************************************************************************
* 函数名称: soap_out_tds_set_hostname_rsp()
* 函数描述: 组装tds:SetHostnameResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_hostname_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetHostnameResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetHostnameResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetHostnameResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_hostname_json_to_xml()
* 函数描述: tds:SetHostname请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_hostname_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
S32 error_code = 0;
if (soap == NULL || NULL == json_rsp)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetHostname rsp.");
if (OK != jso_obj_get_int(json_rsp, "error_code", &error_code))
{
ONVIF_TRACE("no error code");
return ERROR;
}
if (0 != error_code)
{
ONVIF_TRACE("get information error, error_code = [%d]", error_code);
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:ConfigModify", "failed");
soap->error = SOAP_FAULT;
return ERROR;
}
return soap_generate_xml((p_out_fun)(soap_out_tds_set_hostname_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_hostname_xml_to_json()
* 函数描述: tds:SetHostname请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_hostname_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO] = {0};
char name[LEN_VALUE] = {0};
int i;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetHostname parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetHostname请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_out;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "no content");
soap->error = SOAP_FAULT;
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_out;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "Name"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_out;
}
ONVIF_TRACE("Name: %s.", charbuf);
snprintf(name, LEN_TAG, "%s", charbuf);
for (i = 0; i < strlen(name); i++)
{
/* 根据RFC 952和RFC 1123,hostname字符取值范围为数字, 字母, '-', '.' */
if ((name[i] < '0' || (name[i] > '9' && name[i] < 'A') || (name[i] > 'Z' && name[i] < 'a') || name[i] > 'z')
&& name[i] != '-' && name[i] != '.')
{
goto error_out;
}
}
}
}
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_ERROR("jso_new_obj error.");
goto error_out;
}
jso_add_string(json_obj, "method", "set");
jso_obj_add(json_obj, "protocol", json_sec);
jso_obj_add(json_sec, "dhcp", json_opt);
jso_add_string(json_opt, "hostname", name);
*json_req = json_obj;
return OK;
error_out:
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:InvalidHostname", "error");
soap->error = SOAP_FAULT;
jso_free_obj(json_opt);
jso_free_obj(json_sec);
jso_free_obj(json_obj);
return ERROR;
}
/******************************************************************************
* 函数名称: soap_out_tds_set_gateway_rsp()
* 函数描述: 组装tds:SetNetworkDefaultGatewayResponse element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_gateway_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetNetworkDefaultGatewayResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetNetworkDefaultGatewayResponse */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "tds:SetNetworkDefaultGatewayResponse", NULL, NULL));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_gateway_json_to_xml()
* 函数描述: tds:SetNetworkDefaultGateway请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_gateway_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkDefaultGateway rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_gateway_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_gateway_xml_to_json()
* 函数描述: tds:SetNetworkDefaultGateway请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_gateway_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO * 2] = {0};
char temp_gateway[STR_IP_LEN] = {0};
char ip_addr[STR_IP_LEN] = {0};
LINK_STATUS link_status = {0};
#ifdef AUTO_GW_SUPPORT
GATEWAY_MODE_CFG gateway_mode = {0};
WAN_CONN_INFO ewan_dhcp_ip = {0};
U32 link_ipaddr = 0;
#endif
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkDefaultGateway parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetNetworkDefaultGateway请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "tt:IPv4Address"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
snprintf(temp_gateway, STR_IP_LEN, "%s", charbuf);
}
}
if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS)))
{
ONVIF_ERROR("ds read %s error", LINK_STATUS_PATH);
goto error_parse;
}
#ifdef AUTO_GW_SUPPORT
if (0 == ds_read(GATEWAY_MODE_CFG_PATH, (U8*)&gateway_mode, sizeof(GATEWAY_MODE_CFG)))
{
ONVIF_ERROR("ds read %s error", GATEWAY_MODE_CFG_PATH);
goto error_parse;
}
if (0 == ds_read(EWAN_DHCP_IP_PATH, &ewan_dhcp_ip, sizeof(WAN_CONN_INFO)))
{
ONVIF_ERROR("ds read %s error", EWAN_DHCP_IP_PATH);
goto error_parse;
}
if (GW_MODE_AUTO_ADAPTIVE == gateway_mode.gateway_mode)
{
link_ipaddr = ewan_dhcp_ip.ipaddr;
}
else if (GW_MODE_ETH_PRIOR == gateway_mode.gateway_mode)
{
link_ipaddr = link_status.ipaddr;
}
#endif
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
jso_free_obj(json_opt);
goto error_parse;
}
jso_add_string(json_obj, "method", "set");
jso_obj_add(json_obj, "protocol", json_sec);
jso_obj_add(json_sec, "wan", json_opt);
jso_add_string(json_opt, "wan_type", "static");
jso_add_string(json_opt, "proto", "static");
json_opt = jso_new_obj();
jso_obj_add(json_sec, "static", json_opt);
jso_add_string(json_opt, "gateway", temp_gateway);
/* 若当前为dhcp,则将当前ip地址与静态ip地址同步,以保证设置前后ip地址保持不变 */
if (PROTO_DHCP == link_status.proto)
{
#ifdef AUTO_GW_SUPPORT
soap_ipv4_ntop(ntohl(link_ipaddr), ip_addr, STR_IP_LEN);
#else
soap_ipv4_ntop(ntohl(link_status.ipaddr), ip_addr, STR_IP_LEN);
#endif
jso_add_string(json_opt, "ipaddr", ip_addr);
}
*json_req = json_obj;
return OK;
error_parse:
return ERROR;
}
/******************************************************************************
* 函数名称: soap_out_tds_set_network_interfaces_rsp()
* 函数描述: 组装tds:SetNetworkInterfaces element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_network_interfaces_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetNetworkInterfacesResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetNetworkInterfacesResponse begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "tds:SetNetworkInterfacesResponse", NULL));
/* tds:RebootNeeded */
SOAP_IF_FAIL_RET(soap_element_bool_type(xml_buf, "tds:RebootNeeded", FALSE, NULL));
/* tds:SetNetworkInterfacesResponse end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "tds:SetNetworkInterfacesResponse"));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_network_interfaces_json_to_xml()
* 函数描述: tds:SetNetworkInterfaces请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_network_interfaces_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkInterfaces rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_network_interfaces_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_network_interfaces_xml_to_json()
* 函数描述: tds:SetNetworkInterfaces请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_network_interfaces_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO * 2] = {0};
char temp_ip[STR_IP_LEN] = {0};
BOOL DHCP_flag = FALSE;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkInterfaces parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetNetworkInterfaces请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "DHCP"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
if (0 == strcasecmp(charbuf, "True"))
{
DHCP_flag = TRUE;
}
}
if (TRUE == soap_match_tag(charbuf, "Address"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
snprintf(temp_ip, STR_IP_LEN, "%s", charbuf);
}
}
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_TRACE("jso_new_obj error.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
jso_free_obj(json_opt);
goto error_parse;
}
jso_add_string(json_obj, "method", "set");
jso_obj_add(json_obj, "protocol", json_sec);
jso_obj_add(json_sec, "wan", json_opt);
if (TRUE == DHCP_flag)
{
jso_add_string(json_opt, "wan_type", "dhcp");
jso_add_string(json_opt, "proto", "dhcp");
}
else
{
jso_add_string(json_opt, "wan_type", "static");
jso_add_string(json_opt, "proto", "static");
json_opt = jso_new_obj();
jso_obj_add(json_sec, "static", json_opt);
jso_add_string(json_opt, "ipaddr", temp_ip);
}
*json_req = json_obj;
return OK;
error_parse:
return ERROR;
}
/******************************************************************************
* 函数名称: soap_out_tds_set_network_protocols_rsp()
* 函数描述: 组装tds:SetNetworkProtocols element内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* data -- 为空
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_tds_set_network_protocols_rsp(ONVIF_BUF *xml_buf, void *data)
{
/* tds:SetNetworkProtocolsResponse */
if (xml_buf == NULL)
{
ONVIF_TRACE("xml_buf == NULL.");
return ERROR;
}
/* tds:SetNetworkProtocolsResponse begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "tds:SetNetworkProtocolsResponse", NULL));
/* tds:SetNetworkProtocolsResponse end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "tds:SetNetworkProtocolsResponse"));
return OK;
}
/******************************************************************************
* 函数名称: tds_set_network_protocols_json_to_xml()
* 函数描述: tds:SetNetworkProtocols请求的应答报文构造函数
* 输 入: soap -- soap结构体
* json_rsp -- 应答的json数据
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_network_protocols_json_to_xml(SOAP_CONTEXT *soap, JSON_OBJ *json_rsp)
{
if (soap == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkProtocols rsp.");
return soap_generate_xml((p_out_fun)(soap_out_tds_set_network_protocols_rsp), soap, NULL);
}
/******************************************************************************
* 函数名称: tds_set_network_protocols_xml_to_json()
* 函数描述: tds:SetNetworkProtocols请求的处理函数
* 输 入: soap -- soap结构体
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tds_set_network_protocols_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJ **json_req)
{
JSON_OBJ *json_obj = NULL;
JSON_OBJ *json_sec = NULL;
JSON_OBJ *json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO * 2] = {0};
int i = 0;
JSON_OBJ *json_tmp_obj = NULL;
char json_cmd_str[LEN_INFO] = {0};
struct _network_protocol{
const char *proto_type_name; /* 协议名称 */
SWITCH enabled; /* 当前协议是否需要设置 */
int port; /* 端口号 */
const char *module; /* 该协议所属模块 */
const char *fromat_str; /* 用于设置字符串,里面需要添加端口信息 */
};
int cur_proto_num = -1; /* 记录当前设置的proto序号,表示的是network_protocol的下标 */
struct _network_protocol network_protocol[] ={
{.proto_type_name = "HTTP", .module = "uhttpd", .fromat_str = "{\"main\":{\"listen_http\":\"%d\"}}"},
{.proto_type_name = "RTSP", .module = "cet",.fromat_str = "{\"rtsp\":{\"port\":\"%d\"}}"},
};
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("tds:SetNetworkInterfaces parse.");
/* 需要鉴权 */
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
/* 分析SetNetworkInterfaces请求的具体内容 */
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
/* 每一个NetworkProtocols的tag出现时,就说明来了一个新的协议 */
if (TRUE == soap_match_tag(charbuf, "NetworkProtocols"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
cur_proto_num = -1;
}
/* 根据Name来判断当前设置的协议 */
if (TRUE == soap_match_tag(charbuf, "Name"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
/* 上一个协议还未结束 */
if (-1 != cur_proto_num)
{
ONVIF_WARN("%s comes,but former proto is not end.", charbuf);
continue;
}
for (i = 0; i < ARRAY_LEN(network_protocol); ++i)
{
if (0 == strcmp(network_protocol[i].proto_type_name, charbuf))
{
network_protocol[i].enabled = TRUE;
cur_proto_num = i;
}
}
if (-1 == cur_proto_num)
{
ONVIF_WARN("Unsupport protocols = %s.", charbuf);
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:ServiceNotSupported", "NVT does not support the service");
soap->error = SOAP_FAULT;
goto error_parse;
}
}
if (TRUE == soap_match_tag(charbuf, "Enabled"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
if (-1 == cur_proto_num)
{
ONVIF_WARN("Not get a proto name.");
continue;
}
if (0 != strcasecmp("true", charbuf))
{
ONVIF_WARN("Protoclo %s is disabled.", network_protocol[cur_proto_num].proto_type_name);
network_protocol[cur_proto_num].enabled = FALSE;
}
}
if (TRUE == soap_match_tag(charbuf, "Port"))
{
if (OK != soap_parse_element_value(xml_start, request_len, p, ch, charbuf, sizeof(charbuf)))
{
goto error_parse;
}
if (-1 == cur_proto_num)
{
ONVIF_WARN("Not get a proto name.");
continue;
}
if (0 >= (network_protocol[cur_proto_num].port = atoi(charbuf)))
{
ONVIF_WARN("Get port of protoclo %s fail, port = %s.",
network_protocol[cur_proto_num].proto_type_name, charbuf);
network_protocol[cur_proto_num].enabled = FALSE;
}
}
}
/* 组织json object */
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (json_obj == NULL || json_sec == NULL || json_opt == NULL)
{
ONVIF_ERROR("jso_new_obj error.");
goto error_parse;
}
jso_add_string(json_obj, "method", "set");
for (i = 0; i < ARRAY_LEN(network_protocol); ++i)
{
if (TRUE == network_protocol[i].enabled
&& 0 < network_protocol[i].port
&& NULL != network_protocol[i].module
&& NULL != network_protocol[i].fromat_str)
{
snprintf(json_cmd_str, LEN_INFO, network_protocol[i].fromat_str, network_protocol[i].port);
json_tmp_obj = jso_from_string(json_cmd_str);
if (NULL == json_tmp_obj)
{
continue;
}
jso_obj_add(json_obj, network_protocol[i].module, json_tmp_obj);
ONVIF_DEBUG("Set %s port = %d", network_protocol[i].proto_type_name, network_protocol[i].port);
}
}
jso_obj_add(json_obj, "rtsp", json_sec);
jso_obj_add(json_sec, "main", json_opt);
jso_add_string(json_opt, "enabled", network_protocol[1].enabled ? "on" : "off");
*json_req = json_obj;
return OK;
error_parse:
jso_free_obj(json_opt);
jso_free_obj(json_sec);
jso_free_obj(json_obj);
return ERROR;
}
/*********************************************************************************
* Soap tds Handles init
*********************************************************************************/
void tds_passthrough_init()
{
onvif_passthrough_handle_add("tds:SetSystemDateAndTime",
tds_set_sys_time_xml_to_json,
tds_set_sys_time_json_to_xml);
onvif_passthrough_handle_add("tds:SetSystemFactoryDefault",
tds_set_sys_factory_default_xml_to_json,
tds_set_sys_factory_default_json_to_xml);
onvif_passthrough_handle_add("tds:SystemReboot",
tds_sys_reboot_xml_to_json,
tds_sys_reboot_json_to_xml);
onvif_passthrough_handle_add("tds:SetDNS",
tds_set_dns_xml_to_json,
tds_set_dns_json_to_xml);
onvif_passthrough_handle_add("tds:SetNTP",
tds_set_ntp_xml_to_json,
tds_set_ntp_json_to_xml);
onvif_passthrough_handle_add("tds:SetHostname",
tds_set_hostname_xml_to_json,
tds_set_hostname_json_to_xml);
onvif_passthrough_handle_add("tds:SetNetworkDefaultGateway",
tds_set_gateway_xml_to_json,
tds_set_gateway_json_to_xml);
onvif_passthrough_handle_add("tds:SetNetworkInterfaces",
tds_set_network_interfaces_xml_to_json,
tds_set_network_interfaces_json_to_xml);
onvif_passthrough_handle_add("tds:SetNetworkProtocols",
tds_set_network_protocols_xml_to_json,
tds_set_network_protocols_json_to_xml);
}
_设备管理模块通过tds_passthrough.c实现系统时间设置功能,在解析UTC时间戳后优先检查NTP服务状态锁以防止配置冲突,随后通过SPI总线向RTC芯片写入校准值并同步触发时区配置文件更新。固件升级过程采用双重安全保障机制,包括数字签名验证和数据块CRC32校验,升级包被拆分写入独立Flash分区,看门狗线程以200ms间隔监控刷写进度,并在检测到断电时自动回滚至出厂备份区。整体模块设计确保设备配置的可靠性与安全性。_重新写,分三点,参照以下格式:“onvif_srv.c模块的核心功能可分为三个层面:
1. **服务初始化与监听**:通过`onvif_srv_start()`创建主服务端口监听,设置TCP缓冲区优化网络吞吐,并注册端口检查、数据处理和响应生成三个核心回调函数,其中关键操作包括绑定SOAP上下文到具体端口。
2. **请求处理中枢**:在`onvif_proc_data_srv()`中实现报文有效性校验(HTTP200状态和有效内容长度),根据端口号动态选择主服务或订阅服务的SOAP上下文,通过`soap_xml_parse()`深度解析XML请求体内容,最终由`soap_serve_request()`将请求分派至具体业务模块(如设备管理的soap_tds.c)。
3. **响应与资源管理**:根据处理结果选择响应通道(成功时调用SOAP响应生成器,错误时返回HTTP状态码),通过`http_reset_context()`强制释放请求内存,并提供`onvif_srv_remove_socket()`和`onvif_srv_stop()`实现动态服务维护与资源回收机制。”