Bug 概述
在 sofia_glue.c 的 sofia_glue_set_extra_headers 函数中, switch_channel_api_on 函数使用了错误的前缀字符串,导致 execute_on_sip_ph_prefix 钩子变量被错误地作为 API 命令执行两次,第二次执行时没有 session 上下文。
影响版本
FreeSWITCH 1.10.12 及更早版本
问题文件
src/mod/endpoints/mod_sofia/sofia_glue.c ,第 970-973 行
switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_channel_api_on(channel, pstr); // BUG: 使用了错误的前缀
问题分析
switch_channel_api_on 函数使用 strncasecmp(var, variable_prefix, strlen(variable_prefix)) 进行前缀匹配。当 pstr = "execute_on_sip_ph_prefix" 时:
- switch_channel_execute_on 正确匹配 execute_on_sip_ph_prefix 变量,作为 Dialplan Application 执行,session 正常注入
- switch_channel_api_on 错误地也匹配 execute_on_sip_ph_prefix 变量,作为 API 命令执行,session 为 NULL
测试例子:
<action application="export" data="nolocal:execute_on_sip_ph_prefix=lua demo.lua"/>
Lua: demo.lua
if not session then
freeswitch.consoleLog("ERR", "session is nil\n")
else
freeswitch.consoleLog("INFO", "session exists\n")
end
钩子执行流程:
收到 SIP 183/180 响应
↓
sofia_glue_set_extra_headers() 被调用
↓
switch_channel_execute_on(channel, "execute_on_sip_ph_prefix")
→ 匹配 execute_on_sip_ph_prefix=lua demo.lua
→ 执行 lua(demo.lua) 作为 Application
→ session 存在
↓
switch_channel_api_on(channel, "execute_on_sip_ph_prefix") <<===BUG
→ 错误匹配 execute_on_sip_ph_prefix=lua demo.lua
→ 执行 lua demo.lua 作为 API 命令
→ do_api_on() 传递 NULL
→ session 不存在
LOG:
EXECUTE [depth=1] sofia/external/9999 lua(demo.lua) ← Application execution
demo.lua log: session exist!! ← session exists
destroy/unlink session from object ← Session object destroyed
demo.lua log: session not found. ← session not found
switch_channel.c:3692 process lua demo.lua: lua(demo.lua) ← API execution
影响范围:
此 bug 影响所有使用 execute_on_sip_ph_prefix 或 execute_on_sip_rh_prefix 钩子的场景:
- 依赖 session 上下文的回调逻辑无法正常工作
- 脚本被重复执行,可能会导致不可预期的结果。
修复方案(fix):
switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_snprintf(pstr, sizeof(pstr), "api_on_%sprefix", prefix); // add 使用api_on_前缀
switch_channel_api_on(channel, pstr);
补丁文件 / Patch File
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -969,7 +969,8 @@ void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *s
switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
- switch_channel_api_on(channel, pstr);
+ switch_snprintf(pstr, sizeof(pstr), "api_on_%sprefix", prefix);
+ switch_channel_api_on(channel, pstr);
switch_channel_execute_on(channel, "execute_on_sip_extra_headers");
switch_channel_api_on(channel, "api_on_sip_extra_headers");
Bug 概述
在 sofia_glue.c 的 sofia_glue_set_extra_headers 函数中, switch_channel_api_on 函数使用了错误的前缀字符串,导致 execute_on_sip_ph_prefix 钩子变量被错误地作为 API 命令执行两次,第二次执行时没有 session 上下文。
影响版本
FreeSWITCH 1.10.12 及更早版本
问题文件
src/mod/endpoints/mod_sofia/sofia_glue.c ,第 970-973 行
switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_channel_api_on(channel, pstr); // BUG: 使用了错误的前缀
问题分析
switch_channel_api_on 函数使用 strncasecmp(var, variable_prefix, strlen(variable_prefix)) 进行前缀匹配。当 pstr = "execute_on_sip_ph_prefix" 时:
测试例子:
<action application="export" data="nolocal:execute_on_sip_ph_prefix=lua demo.lua"/>Lua: demo.lua
钩子执行流程:
收到 SIP 183/180 响应
↓
sofia_glue_set_extra_headers() 被调用
↓
switch_channel_execute_on(channel, "execute_on_sip_ph_prefix")
→ 匹配 execute_on_sip_ph_prefix=lua demo.lua
→ 执行 lua(demo.lua) 作为 Application
→ session 存在
↓
switch_channel_api_on(channel, "execute_on_sip_ph_prefix") <<===BUG
→ 错误匹配 execute_on_sip_ph_prefix=lua demo.lua
→ 执行 lua demo.lua 作为 API 命令
→ do_api_on() 传递 NULL
→ session 不存在
LOG:
EXECUTE [depth=1] sofia/external/9999 lua(demo.lua) ← Application execution
demo.lua log: session exist!! ← session exists
destroy/unlink session from object ← Session object destroyed
demo.lua log: session not found. ← session not found
switch_channel.c:3692 process lua demo.lua: lua(demo.lua) ← API execution
影响范围:
此 bug 影响所有使用 execute_on_sip_ph_prefix 或 execute_on_sip_rh_prefix 钩子的场景:
修复方案(fix):
switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_snprintf(pstr, sizeof(pstr), "api_on_%sprefix", prefix); // add 使用api_on_前缀
switch_channel_api_on(channel, pstr);
补丁文件 / Patch File