/******************************************************************************
* Copyright (c) 2018-2018 TP-Link Systems Inc.
*
* Filename: soap.c
* Version: 1.0
* Description: soap 处理函数
* Author: liyijie<liyijie@tp-link.com.cn>
* Date: 2018-12-03
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include "onvif_passthrough.h"
#include "soap_global.h"
#include "soap_parse.h"
#include "soap_pack.h"
#define SOAP_TAG_NUM 256
typedef struct _SOAP_TAG_HANDLE
{
char tag[LEN_TAG];
S32 (*handle)(SOAP_CONTEXT *soap);
}SOAP_TAG_HANDLE;
LOCAL SOAP_TAG_HANDLE g_soap_tag_handle[SOAP_TAG_NUM];
/******************************************************************************
* 函数名称: new_soap()
* 函数描述: 申请soap结构体
* 输 入: N/A
* 输 出: N/A
* 返 回 值: soap结构体地址
******************************************************************************/
SOAP_CONTEXT *new_soap()
{
SOAP_CONTEXT *soap = NULL;
soap = (SOAP_CONTEXT *)ONVIF_MALLOC(sizeof(SOAP_CONTEXT));
if (soap == NULL)
{
ONVIF_ERROR("malloc g_soap_for_discv failed");
return NULL;
}
memset(soap, 0, sizeof(SOAP_CONTEXT));
if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN))
{
ONVIF_FREE(soap);
return NULL;
}
return soap;
}
/******************************************************************************
* 函数名称: free_soap()
* 函数描述: 释放soap结构体
* 输 入: soap -- soap结构体地址
* 输 出: N/A
* 返 回 值: N/A
******************************************************************************/
void free_soap(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
return;
}
if (soap->fault != NULL)
{
ONVIF_FREE(soap->fault->soap_env_value);
ONVIF_FREE(soap->fault->soap_env_subcode_1);
ONVIF_FREE(soap->fault->soap_env_subcode_2);
ONVIF_FREE(soap->fault->soap_env_reason);
ONVIF_FREE(soap->fault);
}
onvif_free_buf(&soap->xml_buf);
ONVIF_FREE(soap);
return;
}
/******************************************************************************
* 函数名称: soap_init()
* 函数描述: 初始化soap结构体
* 输 入: soap -- soap结构体地址
* 输 出: N/A
* 返 回 值: N/A
******************************************************************************/
void soap_init(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
ONVIF_WARN("soap == NULL.");
return;
}
soap->error = OK;
soap->in_ip = 0;
soap->ifindex = -1;
soap->has_header = FALSE;
memset(&soap->header, 0, sizeof(SOAP_ENV_HEADER));
if (soap->fault != NULL)
{
ONVIF_FREE(soap->fault->soap_env_value);
ONVIF_FREE(soap->fault->soap_env_subcode_1);
ONVIF_FREE(soap->fault->soap_env_subcode_2);
ONVIF_FREE(soap->fault->soap_env_reason);
ONVIF_FREE(soap->fault);
soap->fault = NULL;
}
soap->tag[0] = '\0';
soap->request_begin = NULL;
soap->request_end = NULL;
soap->types[0] = '\0';
soap->scopes_item[0] = '\0';
soap->scopes_matchby[0] = '\0';
if (soap->xml_buf.start == NULL ||
(soap->xml_buf.end - soap->xml_buf.start) > ONVIF_DISCV_BUF_LEN)
{
if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN))
{
soap->xml_buf.start = NULL;
soap->xml_buf.last = NULL;
soap->xml_buf.end = NULL;
}
}
soap->xml_buf.last = soap->xml_buf.start;
return;
}
/******************************************************************************
* 函数名称: soap_out_env_fault()
* 函数描述: 组装错误信息报文内容
* 输 入: xml_buf -- 存放输出xml字串的内存地址
* fault_data -- 错误信息
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_out_env_fault(ONVIF_BUF *xml_buf, SOAP_ENV_FAULT *fault_data)
{
char attr[LEN_ANY] = {0};
if (xml_buf == NULL)
{
ONVIF_WARN("xml_buf == NULL.");
return ERROR;
}
/* SOAP-ENV:Fault begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, G_SOAP_ENV_FAULT_STR, NULL));
/* SOAP-ENV:Code begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Code", NULL));
/* SOAP-ENV:Value */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_value, NULL));
if (fault_data && fault_data->soap_env_subcode_1)
{
/* SOAP-ENV:Subcode begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Subcode", NULL));
/* SOAP-ENV:Value */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_1, NULL));
if (fault_data->soap_env_subcode_2)
{
/* SOAP-ENV:Subcode begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Subcode", NULL));
/* SOAP-ENV:Value */
SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_2, NULL));
/* SOAP-ENV:Subcode end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode"));
}
/* SOAP-ENV:Subcode end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode"));
}
/* SOAP-ENV:Code end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Code"));
/* SOAP-ENV:Reason begin */
SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Reason", NULL));
/* SOAP-ENV:Text */
snprintf(attr, sizeof(attr), "xml:lang=\"en\"");
SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Text", fault_data->soap_env_reason, attr));
/* SOAP-ENV:Reason end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Reason"));
/* SOAP-ENV:Fault end */
SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, G_SOAP_ENV_FAULT_STR));
return OK;
}
/******************************************************************************
* 函数名称: soap_fault()
* 函数描述: 填充错误信息结构体内容
* 输 入: soap -- soap结构体地址
* code -- 错误码
* subcode1 -- 子错误码1
* subcode2 -- 子错误码2
* reason -- 错误原因
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
S32 soap_fault(SOAP_CONTEXT *soap, char *code, char *subcode1, char *subcode2, char *reason)
{
ONVIF_TRACE("Onvif_fault\n");
if (soap == NULL || code == NULL || subcode1 == NULL)
{
ONVIF_TRACE("soap == NULL || code == NULL || subcode1 == NULL.");
return ERROR;
}
if (soap->fault)
{
ONVIF_FREE(soap->fault->soap_env_value);
ONVIF_FREE(soap->fault->soap_env_subcode_1);
ONVIF_FREE(soap->fault->soap_env_subcode_2);
ONVIF_FREE(soap->fault->soap_env_reason);
}
else
{
soap->fault = ONVIF_MALLOC(sizeof(SOAP_ENV_FAULT));
}
if (NULL == soap->fault)
{
ONVIF_WARN("ONVIF_MALLOC fault failed.");
return ERROR;
}
memset(soap->fault, 0, sizeof(SOAP_ENV_FAULT));
soap->fault->soap_env_value = ONVIF_STRDUP(code);
if (NULL == soap->fault->soap_env_value)
{
ONVIF_WARN("ONVIF_STRDUP soap_env_value failed.");
return ERROR;
}
soap->fault->soap_env_subcode_1 = ONVIF_STRDUP(subcode1);
if (NULL == soap->fault->soap_env_subcode_1)
{
ONVIF_WARN("ONVIF_STRDUP soap_env_subcode_1 failed.");
return ERROR;
}
if (subcode2)
{
soap->fault->soap_env_subcode_2 = ONVIF_STRDUP(subcode2);
if (NULL == soap->fault->soap_env_subcode_2)
{
ONVIF_WARN("ONVIF_STRDUP soap_env_subcode_2 failed.");
return ERROR;
}
}
if (reason)
{
soap->fault->soap_env_reason = ONVIF_STRDUP(reason);
if (NULL == soap->fault->soap_env_reason)
{
ONVIF_WARN("ONVIF_STRDUP soap_env_reason failed.");
return ERROR;
}
}
return OK;
}
/******************************************************************************
* 函数名称: soap_generate_fault()
* 函数描述: 组装错误报文xml内容
* 输 入: soap -- soap结构体地址
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 soap_generate_fault(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
ONVIF_WARN("soap == NULL.");
return ERROR;
}
//soap_set_fault(soap);
if (soap->fault == NULL)
{
return ERROR;
}
if (soap->error < 200 && soap->error != SOAP_FAULT)
{
soap->has_header = FALSE;
}
return soap_generate_xml((p_out_fun)(soap_out_env_fault), soap, soap->fault);
}
/******************************************************************************
* 函数名称: soap_serve_request()
* 函数描述: soap请求处理函数入口
* 输 入: soap -- soap结构体地址
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
S32 soap_serve_request(SOAP_CONTEXT *soap)
{
U32 index = 0;
PASSTHROUGH_RET ret = 0;
if (soap == NULL || soap->tag[0] == '\0')
{
return ERROR;
}
ret = onvif_serve_passthrough(soap);
if (PASSTHROUGH_ERROR == ret)
{
return ERROR;
}
else if (PASSTHROUGH_SOAP_FAULT == ret)
{
SOAP_IF_FAIL_RET(soap_generate_fault(soap));
}
else if (PASSTHROUGH_NOT_MATCH == ret)
{
for (index = 0; index < SOAP_TAG_NUM; index++)
{
if (NULL == g_soap_tag_handle[index].handle)
{
SOAP_IF_FAIL_RET(soap_fault(soap, "SOAP-ENV:Receiver", "ter:ActionNotSupported", NULL, NULL));
soap->error = SOAP_FAULT;
SOAP_IF_FAIL_RET(soap_generate_fault(soap));
break;
}
if (soap_match_tag(soap->tag, g_soap_tag_handle[index].tag))
{
if (g_soap_tag_handle[index].handle(soap))
{
if (soap->fault == NULL)
{
soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "error");
soap->error = SOAP_FAULT;
}
SOAP_IF_FAIL_RET(soap_generate_fault(soap));
}
break;
}
}
if (index >= SOAP_TAG_NUM)
{
SOAP_IF_FAIL_RET(soap_fault(soap, "SOAP-ENV:Receiver", "ter:ActionNotSupported", NULL, NULL));
soap->error = SOAP_FAULT;
SOAP_IF_FAIL_RET(soap_generate_fault(soap));
}
}
/* UDP直接回复,HTTP在上一层回复 */
if (soap->use_udp == TRUE &&
soap->xml_buf.start != NULL &&
soap->xml_buf.start != soap->xml_buf.last)
{
return onvif_send_udp_packet(soap->sock, soap->in_ip, soap->sin_port,
soap->xml_buf.start, (soap->xml_buf.last - soap->xml_buf.start));
}
return OK;
}
LOCAL S32 soap_env_fault_handle(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
ONVIF_WARN("soap == NULL.");
return ERROR;
}
ONVIF_TRACE("SOAP-ENV:Fault handle.");
/* do nothing and no response */
return OK;
}
/******************************************************************************
* 函数名称: soap_tag_handle_add()
* 函数描述: 注册soap请求处理函数
* 输 入: tag -- 请求tag
* handle -- 处理函数
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
void soap_tag_handle_add(char *tag, void *handle)
{
U32 index = 0;
if ((NULL == tag) || (strlen(tag) >= 64) || (NULL == handle))
{
ONVIF_ERROR("soap handle add error, invalid arg.");
return;
}
while ((index < SOAP_TAG_NUM) &&
(NULL != g_soap_tag_handle[index].handle))
{
index++;
}
if (index >= SOAP_TAG_NUM)
{
ONVIF_ERROR("soap handle add error, max support %d tags.", SOAP_TAG_NUM);
return;
}
snprintf(g_soap_tag_handle[index].tag, sizeof(g_soap_tag_handle[index].tag), "%s", tag);
g_soap_tag_handle[index].handle = handle;
return;
}
/******************************************************************************
* 函数名称: soap_tag_handle_init()
* 函数描述: 初始化soap请求处理函数
* 输 入: N/A
* 输 出: N/A
* 返 回 值: ERROR/OK
******************************************************************************/
void soap_tag_handle_init()
{
U32 index = 0;
for (index = 0; index < SOAP_TAG_NUM; index++)
{
memset(g_soap_tag_handle[index].tag, 0, sizeof(g_soap_tag_handle[index].tag));
g_soap_tag_handle[index].handle = NULL;
}
soap_tag_handle_add("SOAP-ENV:Fault", soap_env_fault_handle);
return;
}
——+能不能详细地一行一行一个一个变量一个一个函数地给我解释下代码
最新发布