OpenSIPS3.4.3
启用topology_hiding模块的主要考虑是,某些sip协议栈对record-route支持的不好
启用mid_registrar模块,向FreeSWITCH注册,修改contact为OpenSIPS的地址,但不修改过期时间。不用path模块的主要考虑是,某些sipserver对path支持的不好
测试环境:
- OpenSIPS ip地址:172.20.10.6
- FreeSWITCH地址:172.20.10.7
路由逻辑:
- REGISTER方法,调用mid_registrar_save,再送到FreeSWITCH(172.20.10.7:5060)
- INVITE方法,如果ip来源是FreeSWITCH,调用mid_registrar_lookup,再调用topology_hiding。否则,设置目的地是FreeSWITCH(172.20.10.7:5060),再调用topology_hiding
- 为了简单,暂不处理NAT
完整的路由脚本为:
#debug_mode=yes
log_level=3
xlog_level=3
stderror_enabled=no
syslog_enabled=yes
syslog_facility=LOG_LOCAL0
udp_workers=4
/* uncomment the next line to enable the auto temporary blacklisting of
not available destinations (default disabled) */
#disable_dns_blacklist=no
/* uncomment the next line to enable IPv6 lookup after IPv4 dns
lookup failures (default disabled) */
#dns_try_ipv6=yes
socket=udp:172.20.10.6:5060 # CUSTOMIZE ME
socket=tcp:172.20.10.6:5060 # CUSTOMIZE ME
####### Modules Section ########
#set module path
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
#### SIGNALING module
loadmodule "signaling.so"
#### StateLess module
loadmodule "sl.so"
#### Transaction Module
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "onreply_avp_mode", 1)
#### Record Route Module
loadmodule "rr.so"
modparam("rr", "append_fromtag", 0)
#### MAX ForWarD module
loadmodule "maxfwd.so"
#### SIP MSG OPerationS module
loadmodule "sipmsgops.so"
#### FIFO Management Interface
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "working_mode_preset", "single-instance-no-db")
#### REGISTRAR module
loadmodule "registrar.so"
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
#### TEXTOPS module
loadmodule "textops.so"
#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "reinvite_ping_interval", 300)
modparam("dialog", "options_ping_interval", 60)
#### TOPOLOGY_HIDING module
loadmodule "topology_hiding.so"
#### PATH module
loadmodule "path.so"
#### MID_REGISTRAR module
loadmodule "mid_registrar.so"
#### CACHEDB_LOCAL module
loadmodule "cachedb_local.so"
modparam("cachedb_local", "cachedb_url", "local://")
loadmodule "proto_udp.so"
loadmodule "proto_tcp.so"
####### Routing Logic ########
# main request routing logic
route{
xlog("$ci|$rm|$fU|$tU|$rp from $si:$sp\n");
if (!mf_process_maxfwd_header(10)) {
send_reply(483, "Too Many Hops");
exit;
}
if (has_totag()) {
if (topology_hiding_match()) {
xlog("*** Callee side callid is $TH_callee_callid\n");
route(relay);
exit;
}
# handle hop-by-hop ACK (no routing required)
if (is_method("ACK") && t_check_trans()) {
t_relay();
exit;
}
# sequential request within a dialog should
# take the path determined by record-routing
if (!loose_route()) {
# we do record-routing for all our traffic, so we should not
# receive any sequential requests without Route hdr.
send_reply(404, "Not here");
exit;
}
# validate the sequential request against dialog
if ($DLG_status != NULL && !validate_dialog()) {
xlog("$ci|In-Dialog $rm from $si (callid=$ci) is not valid according to dialog\n");
## exit;
}
# route it out to whatever destination was set by loose_route()
# in $du (destination URI).
route(relay);
exit;
}
# CANCEL processing
if (is_method("CANCEL")) {
if (t_check_trans())
t_relay();
exit;
}
# absorb retransmissions, but do not create transaction
t_check_trans();
if (is_method("OPTIONS|NOTIFY")) {
send_reply(200, "OK");
exit;
}
# record routing
#if (!is_method("REGISTER|MESSAGE"))
# record_route();
if (is_method("PUBLISH|SUBSCRIBE")) {
send_reply(200, "OK");
exit;
}
if (is_method("REGISTER")) {
route(register);
exit;
}
if (is_method("INVITE")) {
route(invite);
exit;
}
exit;
}
route[register] {
if (!is_method("REGISTER")) {
return;
}
$var(rc) = mid_registrar_save("location");
xlog("mid_registrar_save() = $var(rc)\n");
switch ($var(rc)) {
case 1:
xlog("L_INFO", "forwarding REGISTER to main registrar...\n");
$ru = "sip:172.20.10.7:5060"; # CUSTOMIZE ME, dst to FreeSWITCH
if (!t_relay()) {
send_reply(500, "Server Internal Error 1");
}
break;
case 2:
xlog("L_INFO", "REGISTER has been absorbed!\n");
break;
default:
xlog("L_ERR", "mid-registrar error!\n");
send_reply(500, "Server Internal Error 2");
}
exit;
}
route[invite] {
if (!is_method("INVITE") || has_totag()) {
return;
}
create_dialog();
if ($si == "172.20.10.7") { # CUSTOMIZE ME, src from FreeSWITCH
if (!mid_registrar_lookup("location")) {
t_reply(404, "Not Found");
exit;
}
topology_hiding("U"); # Propagate the Username in the Contact header URI
route(relay);
exit;
} else {
$du = "sip:172.20.10.7:5060"; # CUSTOMIZE ME, dst to FreeSWITCH
topology_hiding("U"); # Propagate the Username in the Contact header URI
route(relay);
exit;
}
}
route[relay] {
if (is_method("INVITE")) {
t_on_branch("per_branch_ops");
t_on_reply("handle_nat");
t_on_failure("missed_call");
}
if (!t_relay()) {
send_reply(500, "Internal Error");
}
exit;
}
branch_route[per_branch_ops] {
xlog("new branch at $ru\n");
}
onreply_route[handle_nat] {
xlog("incoming reply, status = $rs\n");
# xlog("****$mb\n");
if (($rs =~ "18[30]") && has_body("application/sdp")) {
# save sdp
# xlog("****$rb\n");
$var(key) = $ci + "+body";
cache_store("local", $var(key), $rb, 120); # 120 秒超时
$var(key) = $ci + "+length";
cache_store("local", $var(key), $hdr(Content-Length), 120); # 120 秒超时
} else if (($rs == "200") && !has_body("application/sdp")) {
# restore sdp
$var(key) = $ci + "+body";
cache_fetch("local", $var(key), $var(sdp));
cache_remove("local", $var(key));
xlog("****$var(sdp)\n");
$var(key) = $ci + "+length";
cache_fetch("local", $var(key), $var(length));
cache_remove("local", $var(key));
xlog("****$var(length)\n");
if (($var(sdp) != NULL) && ($var(length) != NULL)) {
insert_hf("Content-Type: application/sdp\r\n", "Call-ID");
insert_hf("Content-Length: $var(length)\r\n", "Call-ID");
add_body_part($var(sdp), "application/sdp");
}
}
}
failure_route[missed_call] {
if (t_was_cancelled()) {
exit;
}
# uncomment the following lines if you want to block client
# redirect based on 3xx replies.
##if (t_check_status("3[0-9][0-9]")) {
##t_reply(404,"Not found");
## exit;
##}
}
OpenSIPS的拓扑隐藏模块设计的很好,容易使用,本人很喜欢
如果哪天能把OpenSIPS的优点和Kamailio优点都能集中到一起,那就太好了
走过路过的朋友们,请多提宝贵意见