Kamailio uac_replace和uac_restore

2023-10-30 16:21
文章标签 replace restore uac kamailio

本文主要是介绍Kamailio uac_replace和uac_restore,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

uac模块包含的内容很多,本文仅讨论uac_replace和uac_restore

先比较二段路由代码:

# 路由1
$fU = "alice";
$tU = "bob";
$du = ...;
t_relay();
exit;# OpenSIPS3.2 似乎不允许这样修改主被叫,不清楚是出于什么样的考虑
# 路由2
uac_replace_from('"alice"', "sip:" + "alice" + "@" + $fd);
uac_replace_to('"bob"', "sip:" + "bob" + "@" + $td);
$du = ...;
t_relay();
exit;

路由2修改了主被叫,同时还保留了原始主被叫,就这就是二个路由的区别

示意如下:

uac                   kamailio                 uas<----->                      <----->原始主被叫保持不变             新的主叫和被叫

那么问题是原始主被叫保存到哪里呢?

回答是有二个选择:

  • rr头
  • 对话(dialog)变量

下面是二个完整的kamailio路由:

第一个路由是把原始主被叫保存到rr头,并且restore_mode配置为auto

测试的方法非常简单:一个sip ua以1001注册到kamailio(不认证),另外一个sip ua以1002注册到kamailio,1001呼叫1002,用sngrep抓包。

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
enable_sctp=nolisten=udp:192.168.100.200:5060# mpath="/usr/local/lib/kamailio/modules/"loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "textopsx.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"loadmodule "uac.so"modparam("sanity", "autodrop", 0)modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)modparam("rr", "enable_full_lr", 0)
modparam("rr", "append_fromtag", 1) /*vip*/
modparam("tm", "auto_inv_100", 0)modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
modparam("registrar", "max_expires", 3600)
modparam("registrar", "gruu_enabled", 0)
modparam("registrar", "use_path", 1)
modparam("registrar", "path_mode", 0)modparam("usrloc", "timer_interval", 60)
modparam("usrloc", "timer_procs", 1)
modparam("usrloc", "use_domain", 0)
modparam("usrloc", "db_mode", 0)modparam("uac", "rr_from_store_param", "vsf")
modparam("uac", "rr_to_store_param", "vst")
modparam("uac", "restore_mode", "auto")
modparam("uac", "restore_dlg", 0)
modparam("uac", "restore_passwd", "my_secret_passwd")request_route {xinfo("$rm|$fU!$tU|$ci from $si:$sp\n");route(REQINIT);route(NATDETECT);if (is_method("CANCEL")) {if (t_check_trans()) {route(RELAY);}exit;}if (!is_method("ACK")) {if(t_precheck_trans()) {t_check_trans();exit;}t_check_trans();}route(WITHINDLG);route(AUTH);remove_hf("Route");if (is_method("INVITE|SUBSCRIBE")) {record_route();}route(REGISTRAR);route(LOCATION);return;
}route[RELAY] {if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");}if (is_method("INVITE|SUBSCRIBE|UPDATE")) {if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");}if (is_method("INVITE")) {if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");}if (!t_relay()) {sl_reply_error();}exit;
}route[REQINIT] {set_reply_no_connect();force_rport();if (!mf_process_maxfwd_header("10")) {sl_send_reply("483", "Too Many Hops");exit;}if(is_method("OPTIONS")) {sl_send_reply("200", "OK");exit;}if(is_method("SUBSCRIBE")) {sl_send_reply("200", "OK");exit;}if(!sanity_check("17895", "7")) {xlog("Malformed SIP request from $si:$sp\n");exit;}
}route[WITHINDLG] {if (!has_totag()) return;if (loose_route()) {if (is_method("BYE")) {;} else if ( is_method("ACK") ) {route(NATMANAGE);} else if ( is_method("NOTIFY") ) {record_route();}route(RELAY);exit;}if ( is_method("ACK") ) {if ( t_check_trans() ) {route(RELAY);exit;} else {exit;}}sl_send_reply("404", "Not here");exit;
}route[REGISTRAR] {if (!is_method("REGISTER")) return;if (!save("location")) {sl_reply_error();}exit;
}route[LOCATION] {if (!lookup("location")) {$var(rc) = $rc;t_newtran();switch ($var(rc)) {case -1:case -3:send_reply("404", "Not Found");exit;case -2:send_reply("405", "Method Not Allowed");exit;}}uac_replace_from('"alice"', "sip:" + "alice" + "@" + $fd);uac_replace_to('"bob"', "sip:" + "bob" + "@" + $td);route(RELAY);exit;
}route[AUTH] {return;
}route[NATDETECT] {return;
}route[NATMANAGE] {return;
}branch_route[MANAGE_BRANCH] {xinfo("new branch [$T_branch_idx] to $ru\n");route(NATMANAGE);return;
}reply_route {if(!sanity_check("17604", "6")) {xlog("Malformed SIP response from $si:$sp\n");drop;}return;
}onreply_route[MANAGE_REPLY] {xinfo("incoming reply\n");return;
}failure_route[MANAGE_FAILURE] {route(NATMANAGE);if (t_is_canceled()) exit;return;
}

这是kamailio收到的invite:

INVITE sip:1002@192.168.100.200 SIP/2.0
Via: SIP/2.0/UDP 192.168.100.172:58116;branch=z9hG4bK-d87543-1e0d1449a250ef06-1--d87543-;rport
Max-Forwards: 70
Contact: <sip:1001@192.168.100.172:58116>
To: "1002"<sip:1002@192.168.100.200>
From: <sip:1001@192.168.100.200>;tag=dc79041f
Call-ID: YjlhMzAyZGJlMWFhMjRkOTYyNzY1YzY5ZWFiOTg1MzE.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
Content-Type: application/sdp
User-Agent: eyeBeam release 1011d stamp 40820
Content-Length: 292

kamailio t_relay()出去是这样:

INVITE sip:1002@192.168.100.172:11806 SIP/2.0
Record-Route: <sip:192.168.100.200;lr;ftag=dc79041f;vsf=bXlfczU/KzdRLnhqb2xwantmXnN7f3BlRA--;vst=bXlfczY8IBcFV3t9bHR5cnJ4X215YXJV>
Via: SIP/2.0/UDP 192.168.100.200;branch=z9hG4bK10d9.6654b4ffba5da6fea3cd3f80b89690c4.0
Via: SIP/2.0/UDP 192.168.100.172:58116;received=192.168.100.172;branch=z9hG4bK-d87543-1e0d1449a250ef06-1--d87543-;rport=58116
Max-Forwards: 69
Contact: <sip:1001@192.168.100.172:58116>
To: "bob"<sip:bob@192.168.100.200>
From: "alice" <sip:alice@192.168.100.200>;tag=dc79041f
Call-ID: YjlhMzAyZGJlMWFhMjRkOTYyNzY1YzY5ZWFiOTg1MzE.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO
Content-Type: application/sdp
User-Agent: eyeBeam release 1011d stamp 40820
Content-Length: 292

请注意rr头里面的vsf和vst参数,就是经过加密处理后的原始主被叫

这是另外一段kamailio路由,把原始主被叫保存到对话变量

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
enable_sctp=nolisten=udp:192.168.100.200:5060# mpath="/usr/local/lib/kamailio/modules/"loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "textopsx.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"loadmodule "dialog.so"
loadmodule "uac.so"modparam("sanity", "autodrop", 0)modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)modparam("rr", "enable_full_lr", 0)
modparam("rr", "append_fromtag", 1) /*vip*/
modparam("tm", "auto_inv_100", 0)modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
modparam("registrar", "max_expires", 3600)
modparam("registrar", "gruu_enabled", 0)
modparam("registrar", "use_path", 1)
modparam("registrar", "path_mode", 0)modparam("usrloc", "timer_interval", 60)
modparam("usrloc", "timer_procs", 1)
modparam("usrloc", "use_domain", 0)
modparam("usrloc", "db_mode", 0)modparam("dialog", "db_mode", 0)modparam("uac", "restore_mode", "auto")
modparam("uac", "restore_dlg", 1)request_route {xinfo("$rm|$fU!$tU|$ci from $si:$sp\n");route(REQINIT);route(NATDETECT);if (is_method("CANCEL")) {if (t_check_trans()) {route(RELAY);}exit;}if (!is_method("ACK")) {if(t_precheck_trans()) {t_check_trans();exit;}t_check_trans();}route(WITHINDLG);route(AUTH);remove_hf("Route");if (is_method("INVITE|SUBSCRIBE")) {record_route();}route(REGISTRAR);if (is_method("INVITE")) {dlg_manage();}route(LOCATION);return;
}route[RELAY] {if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");}if (is_method("INVITE|SUBSCRIBE|UPDATE")) {if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");}if (is_method("INVITE")) {if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");}if (!t_relay()) {sl_reply_error();}exit;
}route[REQINIT] {set_reply_no_connect();force_rport();if (!mf_process_maxfwd_header("10")) {sl_send_reply("483", "Too Many Hops");exit;}if(is_method("OPTIONS")) {sl_send_reply("200", "OK");exit;}if(is_method("SUBSCRIBE")) {sl_send_reply("200", "OK");exit;}if(!sanity_check("17895", "7")) {xlog("Malformed SIP request from $si:$sp\n");exit;}
}route[WITHINDLG] {if (!has_totag()) return;if (loose_route()) {if (is_method("BYE")) {;} else if ( is_method("ACK") ) {route(NATMANAGE);} else if ( is_method("NOTIFY") ) {record_route();}route(RELAY);exit;}if ( is_method("ACK") ) {if ( t_check_trans() ) {route(RELAY);exit;} else {exit;}}sl_send_reply("404", "Not here");exit;
}route[REGISTRAR] {if (!is_method("REGISTER")) return;if (!save("location")) {sl_reply_error();}exit;
}route[LOCATION] {if (!lookup("location")) {$var(rc) = $rc;t_newtran();switch ($var(rc)) {case -1:case -3:send_reply("404", "Not Found");exit;case -2:send_reply("405", "Method Not Allowed");exit;}}uac_replace_from('"alice"', "sip:" + "alice" + "@" + $fd);uac_replace_to('"bob"', "sip:" + "bob" + "@" + $td);route(RELAY);exit;
}route[AUTH] {return;
}route[NATDETECT] {return;
}route[NATMANAGE] {return;
}branch_route[MANAGE_BRANCH] {xinfo("new branch [$T_branch_idx] to $ru\n");route(NATMANAGE);return;
}reply_route {if(!sanity_check("17604", "6")) {xlog("Malformed SIP response from $si:$sp\n");drop;}return;
}onreply_route[MANAGE_REPLY] {xinfo("incoming reply\n");return;
}failure_route[MANAGE_FAILURE] {route(NATMANAGE);if (t_is_canceled()) exit;return;
}

现在1001呼叫1002,接着执行`kamcmd dlg.list`,输出如下:

{
    h_entry: 3555
    h_id: 11955
    ref: 2
    call-id: MGQ2NTc4MGM0YzQ4MjI4MWJiMTI2NzViZjBhZmNiYjU.
    from_uri: sip:1001@192.168.100.200
    to_uri: sip:1002@192.168.100.200
    state: 4
    start_ts: 1698647274
    init_ts: 1698647272
    end_ts: 0
    duration: 15
    timeout: 1698690474
    lifetime: 43200
    dflags: 643
    sflags: 0
    iflags: 0
    caller: {
        tag: f56df00b
        contact: sip:1001@192.168.100.172:58116
        cseq: 1
        route_set: 
        socket: udp:192.168.100.200:5060
    }
    callee: {
        tag: 1f0d4519
        contact: sip:1002@192.168.100.172:11806
        cseq: 0
        route_set: 
        socket: udp:192.168.100.200:5060
    }
    profiles: {
    }
    variables: {
        {
            _uac_tdpnew: "bob"
        }
        {
            _uac_tdp: "1002"
        }
        {
            _uac_tonew: sip:bob@192.168.100.200
        }
        {
            _uac_to: sip:1002@192.168.100.200
        }
        {
            _uac_fdpnew: "alice"
        }
        {
            _uac_fdp: 
        }
        {
            _uac_funew: sip:alice@192.168.100.200
        }
        {
            _uac_fu: sip:1001@192.168.100.200
        }
    }
}

这篇关于Kamailio uac_replace和uac_restore的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/309148

相关文章

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

Android rk3399 UAC(USB Audio)开发笔记

一、UAC有1.0和2.0,因Windows对2.0支持不好,我使用的是UAC1.0驱动 内核配置:CONFIG_USB_CONFIGFS_F_UAC1          ---这个宏配置无需物理codec,使用虚拟 alsa codec  驱动路径:"kernel\drivers\usb\gadget\function\f_uac1.c" 内核配置:CONFIG_USB_CONFIGFS_

Android canvas save restore saveLayer的异同点

一、基础操作 drawText、drawRect、drawColor等 对于这些基础操作,相信每一个安卓开发者都能说上个一二点出来,这些就不多做介绍,api 工程师必备技能之一。 在进阶之前,先回答这个问题:    问:canvas既然大家都理解为画布,那如果先在画布上绘制了某些内容,然后再canvas.rotate旋转了画布,为什么这些已经绘制在画布上的内容不会跟随着旋转?    答:由此可

base_dir.replace(‘\‘,‘/‘)报错SyntaxError: unterminated string literal

base_dir.replace(‘’,‘/’)报错 报错解释: 这个报错信息表明你在尝试使用Python中的replace方法来替换字符串中的字符时出现了问题。具体来说,base_dir.replace(‘’,‘/’)这行代码中,你试图将base_dir字符串中的反斜杠\替换为斜杠/,但是你的代码中反斜杠前的反斜杠是一个转义字符,它本应用来转义后面的字符。 问题可能是你在一个字符串中使

CodeForces 404C Restore Graph

题意: n个点的图  最大度为k  已知从某个点到每个点的距离dis[i]  求  这幅图的边 思路: 告诉了距离  很容易想到dis是从距离为0的那个点开始bfs求出来的 那么复原这幅图的办法就是重新构造这棵bfs形成的树就好了 每层利用点数计算一下是不是违反了最大度k的限制 这里注意  只有dis=0的那个点可以连出k条边  其余的只有k-1条(因为它们还和父亲连着一条边)

Replace All ?‘s to Avoid Consecutive Repeating Characters

Given a string s containing only lower case English letters and the '?' character, convert all the '?' characters into lower case letters such that the final string does not contain any consecutive re

Vue(十三) 路由、路由嵌套、query、param传参、propos、replace属性。编程式路由导航,特有的生命周期函数,路由守卫

文章目录 路由1. 基本使用2. 多级(嵌套)路由3. 路由query传参4. 命名路由5. 路由param传参6. propos属性7. replace属性8. 编程式路由导航9. 缓存路由组件10. actived,deactived生命周期函数11. 路由守卫1、全局路由2、独享路由3、组件内路由守卫 12. 路由器工作的两种模式 路由 路由就是一组key-value的

【Go】strings.Replace 与 bytes.Replace 调优

原文链接:https://blog.thinkeridea.com/201902/go/replcae_you_hua.html 标准库中函数大多数情况下更通用,性能并非最好的,还是不能过于迷信标准库,最近又有了新发现,strings.Replace 这个函数自身的效率已经很好了,但是在特定情况下效率并不是最好的,分享一下我如何优化的吧。 我的服务中有部分代码使用 strings.Replac

Pandas-数据操作-字符串型(二):常用方法【lower、upper、len、startswith、endswith、strip、lstrip、replace、split、rsplit】

一、字符串常用方法:lower,upper,len,startswith,endswith import numpy as npimport pandas as pds = pd.Series(['A', 'b', 'bbhello', '123', np.nan])print("s = \n", s)print('-' * 200)print("lower小写: s.str.lower

Pandas-高级处理(三):缺失值处理【isnull:判断是否有缺失数据NaN】【fillna:实现缺失值的填充】【dropna:实现缺失值的删除】【replace:实现数据的替换】

缺失值处理 应用isnull判断是否有缺失数据NaN应用fillna实现缺失值的填充应用dropna实现缺失值的删除应用replace实现数据的替换 1 如何处理nan 获取缺失值的标记方式(NaN或者其他标记方式) 如果缺失值的标记方式是NaN 判断数据中是否包含NaN: pd.isnull(df),pd.notnull(df) 存在缺失值nan: 1、删除存在缺失值的:dr