<think>
我们一行一行解释代码,但由于代码量较大,我们将分函数进行详细解释。每个函数的功能、输入输出、变量含义都会说明。
### 1. 头文件和宏定义
```c
/******************************************************************************
* 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 // 定义标签处理函数的最大数量
```
- 头文件:包含标准C库、网络操作等头文件,以及项目相关的头文件。
- `SOAP_TAG_NUM`:定义最多可以注册256个标签处理函数。
### 2. 结构体定义
```c
typedef struct _SOAP_TAG_HANDLE
{
char tag[LEN_TAG]; // 标签字符串,长度由LEN_TAG定义(例如64)
S32 (*handle)(SOAP_CONTEXT *soap); // 处理函数指针,参数为SOAP_CONTEXT指针,返回整型(S32)
} SOAP_TAG_HANDLE;
LOCAL SOAP_TAG_HANDLE g_soap_tag_handle[SOAP_TAG_NUM]; // 全局标签处理函数数组
```
- `SOAP_TAG_HANDLE`:结构体,包含一个标签字符串和一个处理函数指针。
- `g_soap_tag_handle`:全局数组,用于存储注册的标签处理函数。
### 3. `new_soap` 函数
```c
SOAP_CONTEXT *new_soap()
{
SOAP_CONTEXT *soap = NULL;
soap = (SOAP_CONTEXT *)ONVIF_MALLOC(sizeof(SOAP_CONTEXT)); // 分配SOAP_CONTEXT结构体内存
if (soap == NULL)
{
ONVIF_ERROR("malloc g_soap_for_discv failed");
return NULL;
}
memset(soap, 0, sizeof(SOAP_CONTEXT)); // 初始化为0
// 创建XML缓冲区,大小为ONVIF_DISCV_BUF_LEN(可能是4096等)
if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN))
{
ONVIF_FREE(soap); // 如果创建失败,释放soap内存
return NULL;
}
return soap; // 返回soap结构体指针
}
```
- 功能:创建并初始化一个SOAP_CONTEXT结构体,分配内存并设置XML缓冲区。
- 输入:无。
- 输出:成功返回SOAP_CONTEXT指针,失败返回NULL。
- 变量:
- `soap`:指向SOAP_CONTEXT结构体的指针。
### 4. `free_soap` 函数
```c
void free_soap(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
return;
}
// 释放fault结构体内部成员
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); // 释放fault结构体本身
}
onvif_free_buf(&soap->xml_buf); // 释放XML缓冲区
ONVIF_FREE(soap); // 释放soap结构体
return;
}
```
- 功能:释放SOAP_CONTEXT结构体及其内部所有动态分配的内存。
- 输入:`soap` - 要释放的SOAP_CONTEXT指针。
- 输出:无。
### 5. `soap_init` 函数
```c
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)); // 清零header
// 释放并重置fault
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';
// 检查XML缓冲区是否存在或是否过大,如果是则重新创建
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))
{
// 创建失败,将缓冲区指针置为NULL
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_CONTEXT结构体,用于复用该结构体处理新的请求。
- 输入:`soap` - 要初始化的SOAP_CONTEXT指针。
- 输出:无。
### 6. `soap_out_env_fault` 函数
```c
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));
// 如果有子错误码1
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));
// 如果有子错误码2
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错误报文(XML格式)并写入缓冲区。
- 输入:
- `xml_buf`:XML缓冲区。
- `fault_data`:错误信息结构体。
- 输出:成功返回OK,失败返回ERROR。
- 变量:
- `attr`:临时存储XML属性。
### 7. `soap_fault` 函数
```c
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;
}
// 如果已有fault,先释放其内部成员
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
{
// 否则分配新的fault结构体
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;
}
// 复制子错误码1
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;
}
// 如果有子错误码2,复制
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错误信息到soap->fault结构体中。
- 输入:
- `soap`:SOAP上下文。
- `code`:主错误码。
- `subcode1`:子错误码1。
- `subcode2`:子错误码2(可选)。
- `reason`:错误原因文本(可选)。
- 输出:成功返回OK,失败返回ERROR。
### 8. `soap_generate_fault` 函数
```c
LOCAL S32 soap_generate_fault(SOAP_CONTEXT *soap)
{
if (soap == NULL)
{
ONVIF_WARN("soap == NULL.");
return ERROR;
}
if (soap->fault == NULL)
{
return ERROR;
}
// 如果不是SOAP_FAULT错误且错误码小于200,则标记为没有头部
if (soap->error < 200 && soap->error != SOAP_FAULT)
{
soap->has_header = FALSE;
}
// 调用soap_generate_xml生成错误报文,使用soap_out_env_fault作为输出函数
return soap_generate_xml((p_out_fun)(soap_out_env_fault), soap, soap->fault);
}
```
- 功能:生成SOAP错误报文,并存储到soap的XML缓冲区中。
- 输入:`soap` - SOAP上下文。
- 输出:成功返回OK,失败返回ERROR。
### 9. `soap_serve_request` 函数
```c
S32 soap_serve_request(SOAP_CONTEXT *soap)
{
U32 index = 0;
PASSTHROUGH_RET ret = 0;
if (soap == NULL || soap->tag[0] == '\0') // 检查soap和标签是否有效
{
return ERROR;
}
// 先尝试透传处理
ret = onvif_serve_passthrough(soap);
// 处理透传返回结果
if (PASSTHROUGH_ERROR == ret)
{
return ERROR;
}
else if (PASSTHROUGH_SOAP_FAULT == ret) // 需要返回SOAP错误
{
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))
{
// 如果处理函数返回非0(错误),并且没有设置fault,则设置一个默认错误
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传输,并且缓冲区有数据,则直接发送UDP响应
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;
}
```
- 功能:处理SOAP请求的入口函数,根据标签分发请求。
- 输入:`soap` - SOAP上下文。
- 输出:成功返回OK,失败返回ERROR。
- 变量:
- `index`:循环索引。
- `ret`:透传处理函数的返回值。
### 10. `soap_env_fault_handle` 函数
```c
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-ENV:Fault标签的函数。这里什么也不做,因为没有请求需要响应。
- 输入:`soap` - SOAP上下文。
- 输出:始终返回OK。
### 11. `soap_tag_handle_add` 函数
```c
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;
}
```
- 功能:注册一个标签处理函数到全局数组中。
- 输入:
- `tag`:标签字符串。
- `handle`:处理函数指针。
- 输出:无。
### 12. `soap_tag_handle_init` 函数
```c
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;
}
// 注册内置的Fault处理函数
soap_tag_handle_add("SOAP-ENV:Fault", soap_env_fault_handle);
return;
}
```
- 功能:初始化标签处理函数数组,并注册内置的处理函数(如SOAP-ENV:Fault)。
- 输入:无。
- 输出:无。
### 整体模块结构
1. **初始化**:调用`soap_tag_handle_init`初始化路由表。
2. **创建上下文**:`new_soap`创建一个新的SOAP上下文。
3. **初始化上下文**:`soap_init`初始化或重置上下文。
4. **解析请求**:由外部函数(如`soap_parse_request`)解析请求,填充上下文(如设置`tag`)。
5. **处理请求**:调用`soap_serve_request`,根据标签查找处理函数并执行。
6. **错误处理**:若处理出错,使用`soap_fault`设置错误信息,然后`soap_generate_fault`生成错误报文。
7. **发送响应**:如果是UDP,直接发送;如果是HTTP,由上层发送。
8. **释放资源**:调用`free_soap`释放上下文。
### 对外接口
- `soap_serve_request`:请求处理入口。
- `soap_fault`:业务函数用于报告错误。
- `soap_tag_handle_add`:业务模块注册处理函数。
- `soap_tag_handle_init`:模块初始化(系统启动时调用)。
---
§§相关问题§§
1. 在`soap_serve_request`函数中,为什么处理完请求后需要判断`use_udp`标志?
2. `soap_match_tag`函数是如何实现标签匹配的?
3. 如果业务处理函数返回错误但没有设置`soap->fault`,会发生什么?
4. 如何扩展支持更多的标签处理函数(超过256个)?
</think>
### SOAP 处理模块逐行详解
#### 1. 头文件与数据结构
```c
#include "soap_global.h" // SOAP核心数据结构定义
#include "soap_parse.h" // XML解析相关函数
#include "soap_pack.h" // XML打包相关函数
#define SOAP_TAG_NUM 256 // 标签处理器最大数量
typedef struct _SOAP_TAG_HANDLE {
char tag[LEN_TAG]; // 存储SOAP标签名(如"tds:GetDeviceInformation")
S32 (*handle)(SOAP_CONTEXT*); // 标签处理函数指针
} SOAP_TAG_HANDLE;
LOCAL SOAP_TAG_HANDLE g_soap_tag_handle[SOAP_TAG_NUM]; // 全局标签处理路由表
```
- **关键数据结构**:
- `SOAP_CONTEXT`:SOAP请求处理上下文
- `ONVIF_BUF`:XML缓冲区管理结构
- `SOAP_ENV_FAULT`:错误信息容器
---
### 核心函数详解
#### 1. 上下文管理
```c
SOAP_CONTEXT* new_soap() {
SOAP_CONTEXT* soap = ONVIF_MALLOC(sizeof(SOAP_CONTEXT)); // 动态分配上下文内存
memset(soap, 0, sizeof(SOAP_CONTEXT)); // 清零初始化
onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN); // 创建XML缓冲区(默认4KB)
return soap;
}
void free_soap(SOAP_CONTEXT* soap) {
// 释放错误结构体内存
if (soap->fault) {
ONVIF_FREE(soap->fault->soap_env_value); // 释放主错误码字符串
ONVIF_FREE(soap->fault->soap_env_subcode_1); // 释放子错误码1
// ...其他错误字段释放...
ONVIF_FREE(soap->fault); // 释放错误结构体本身
}
onvif_free_buf(&soap->xml_buf); // 释放XML缓冲区
ONVIF_FREE(soap); // 释放上下文本身
}
void soap_init(SOAP_CONTEXT* soap) {
soap->error = OK; // 重置错误状态
soap->in_ip = 0; // 清空来源IP
memset(&soap->header, 0, sizeof(SOAP_ENV_HEADER)); // 清空SOAP头部
// 重置XML缓冲区指针
soap->xml_buf.last = soap->xml_buf.start;
}
```
---
#### 2. 错误处理机制
```c
S32 soap_fault(SOAP_CONTEXT* soap, char* code, char* subcode1, char* subcode2, char* reason) {
// 动态分配并填充错误结构体
soap->fault->soap_env_value = ONVIF_STRDUP(code); // "SOAP-ENV:Sender"
soap->fault->soap_env_subcode_1 = ONVIF_STRDUP(subcode1); // "ter:InvalidArgVal"
// ...其他字段赋值...
}
LOCAL S32 soap_out_env_fault(ONVIF_BUF* xml_buf, SOAP_ENV_FAULT* fault_data) {
// 生成标准SOAP错误报文
soap_element_begin_out(xml_buf, "SOAP-ENV:Fault", NULL); // <SOAP-ENV:Fault>
soap_element_begin_out(xml_buf, "SOAP-ENV:Code", NULL); // <Code>
soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_value, NULL); // <Value>...
// ...完整错误树构建...
}
```
---
#### 3. 请求处理引擎
```c
S32 soap_serve_request(SOAP_CONTEXT* soap) {
PASSTHROUGH_RET ret = onvif_serve_passthrough(soap); // 1. 尝试透传模式
if (ret == PASSTHROUGH_NOT_MATCH) { // 2. 本地处理模式
for (index = 0; index < SOAP_TAG_NUM; index++) {
// 路由匹配:比较请求标签和注册标签
if (soap_match_tag(soap->tag, g_soap_tag_handle[index].tag)) {
// 调用注册的处理函数
if (g_soap_tag_handle[index].handle(soap)) {
// 处理失败时生成错误响应
soap_generate_fault(soap);
}
break;
}
}
}
// 3. UDP协议直接发送响应
if (soap->use_udp) {
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;
}
```
---
#### 4. 标签路由注册
```c
void soap_tag_handle_add(char* tag, void* handle) {
// 在路由表中查找空槽位
while (index < SOAP_TAG_NUM && g_soap_tag_handle[index].handle)
index++;
// 注册标签处理函数
snprintf(g_soap_tag_handle[index].tag, sizeof(...), "%s", tag);
g_soap_tag_handle[index].handle = handle; // 存储函数指针
}
void soap_tag_handle_init() {
// 初始化路由表:注册内置错误处理器
soap_tag_handle_add("SOAP-ENV:Fault", soap_env_fault_handle);
}
```
---
#### 5. 特殊错误处理器
```c
LOCAL S32 soap_env_fault_handle(SOAP_CONTEXT* soap) {
ONVIF_TRACE("SOAP-ENV:Fault handle.");
/* 空实现:对错误报文不响应 */
return OK;
}
```
---
### 关键变量说明
| 变量名 | 类型 | 作用描述 |
|--------------------------|--------------------|-----------------------------------|
| `soap->xml_buf` | ONVIF_BUF | XML输入/输出缓冲区 |
| `soap->tag[64]` | char | 当前处理的SOAP请求标签 |
| `soap->fault` | SOAP_ENV_FAULT* | 错误信息容器 |
| `soap->use_udp` | BOOL | 传输协议标识(UDP=1/HTTP=0) |
| `g_soap_tag_handle` | SOAP_TAG_HANDLE[256] | 标签-处理函数映射表 |
| `fault_data->soap_env_value` | char* | 主错误码(如"SOAP-ENV:Sender") |
---
### 完整工作流程
```mermaid
sequenceDiagram
participant Client
participant soap_serve_request
participant Passthrough
participant TagRouter
participant Handler
Client->>soap_serve_request: SOAP请求
soap_serve_request->>Passthrough: 尝试透传
alt 透传成功
Passthrough-->>Client: 直接响应
else 本地处理
soap_serve_request->>TagRouter: 路由匹配
TagRouter->>Handler: 调用注册函数
Handler->>Business: 执行业务逻辑
Business-->>soap_serve_request: 生成响应
soap_serve_request->>Client: 返回响应
end
```
---