设为首页 收藏本站
开启辅助访问 切换到宽版
注册会员 找回密码

VoIP88

toasterisk 发表于 2011-6-13 22:13 | 显示全部楼层 |阅读模式
注:以下文章如需转载,请注明所属作者,转载地址,谢谢!
实现呼叫盲转(Implementing Blind Call Forwarding
首先,让我们来实现呼叫盲转服务。在INVITE请求的处理过程中,我们将从数据库中的用户优先表中加载名称为callfwdAVP。如果callfwd被设置给了指定的用户,那么我们在对该请求进行前转前将它“推进”(push)到R-URI中。
if(avp_db_load("$ruri/username","s:callfwd")){
#Check the existence of the callfwd attribute on the
#usr_preferences table. If found, assign the vaue to the AVP
# and push the value to the ruri of the SIP header.
avp_pushto("$ruri","s:callfwd");
route(1);
exit;
};
为了能让这个特性得以工作,重要点在于在数据库中插入正确的入口点。AVPs使用的表叫做usr_preferences



你可以在SerMyAdmin的帮助下来对用户的喜好进行修改;只需要浏览菜单中“user preferences”即可。在那个选单中你可以查看所有的用户喜好,编辑它们,还可以创建新的。



如果你工作在多域环境中,请将模块AVPOPS的多域参数功能打开,并用域名来填充数据库。
在上面的记录中,我们告诉系统将任何呼给1001的呼叫都呼给URIsip:1004@yourdomain
Lab——实现呼叫盲转(Lab——Implementing Blind Call Forwarding
步骤1:让我们使用在第六章里第一次见到的SerMyAdmin接口来插入AVP对。
你的浏览器中访问SerWEB的管理接口为:
http://<your-ip-server-address>:8080/serMyAdmin
步骤2:使用一个具有“全局管理员”角色的用户登录接口。
步骤3:点击用户喜好(User preferences)标签。在这个菜单中,点击“New Preference”按钮,为你想要前转通话的用户来创建AVP;在这个例子中,[url=mailto:%E5%BA%94%E8%AF%A5%E6%98%AF1000@sermyadmin.org]应该是1000@sermyadmin.org[/url]。它的属性比较取名为callfwd,值是你要前转通话的URI[url=mailto:%E8%BF%99%E9%87%8C%E5%BA%94%E8%AF%A5%E8%AE%BE%E7%BD%AE%E6%88%901004@sermyadmin.org]这里应该设置成1004@sermyadmin.org[/url]



步骤4:编辑openser.cfg以包含上面做的那些说明解释。文件应该以下面的代码结束。在openser.cfg文件中包含下面的代码行。或是简单地从http://www.sermayadmin.org/openser拷贝openser.callfwd1openser.cfg
在模块加载部分:
loadmodule "avpops.so"
loadmodule "xlog.so"
在模块参数部分:
modparam("avpops", "avp_url", "mysql://openserpenserrw@localhost/openser")
modparam("avpops", "avp_table", "usr_preferences")
route[3]部分:
route[3] {
#
# -- INVITE request handler --
#
if (is_from_local()){
# From an internal domain -> check the credentials and the FROM
if(!allow_trusted()){
if (!proxy_authorize("","subscriber")) {
proxy_challenge("","1");
exit;
} else if (!check_from()) {
sl_send_reply("403", "Forbidden, use From=ID");
exit;
};
} else {
log("Request bypassed the auth. using allow_trusted");
};
if(avp_db_load("$ru/username","$avp(s:callfwd)")) {
avp_pushto("$ru", "$avp(s:callfwd)");
xlog("forwarded to: $avp(s:callfwd)");
route(1);
exit;
}
consume_credentials();
步骤5:注册分机10011004。使用1001打给1000,这时候这通通话就应该按照usr_preferences表中说明被前转到1004
在忙线或无人接听的时候实现呼叫前转(Implementing Call Forward on Busy or Unanswered



这是这一章的第二部分。现在我们将介绍两个新的重要概念。第一个是failure_route,第二个则是append_branch,其被用来派生通话(fork the call)。我们将处理下面的出错情况:
l
408 – Timeout
l
486 – Busy Here
l
487 – Request Cancelled
为了实现在忙线和无人接听的情况下的通话前转,我们将使用出错路由(failure route)的概念。
下面的逻辑中,在发送INVITE到标准处理过程前,我们将调用函数t_on_failure(“1”)。这允许我们在failure_route[1]中处理SIP出错消息(返回的消息高于299的,也叫做负应答negative replies
当在这种情况下收到一通通话时,我们将其前转到一个语音邮箱系统。Asterisk能够充当一个相当好的语音邮箱系统。让我们来看看如何整合asterisk来记录语音邮箱消息。我们将在URI使用bbusy)前缀来告诉asterisk服务器播放busy消息,使用uunanswered)来播放无应答消息。Asterisk将分别使用应用voicemail(b${EXTEN})voicemail(u${EXTEN})来处理忙线和无人接听的语音邮箱请求。
下面是一个完整的脚本,修改部分使用高亮显示。
#
#
# $Id: openser.cfg 1676 2007-02-21 13:16:34Z bogdan_iancu $
#
# simple quick-start config script
# Please refer to the Core CookBook at http://www.openser.org/dokuwiki/doku.php
# for a explanation of possible statements, functions and parameters.
#
# ----------- global configuration parameters ------------------------
debug=3 # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)
children=4
port=5060
# ------------------ module loading ----------------------------------
#set module path
mpath="//lib/openser/modules/"
# Uncomment this if you want to use SQL database
#loadmodule "mysql.so"
loadmodule "mysql.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "uri.so"
loadmodule "uri_db.so"
loadmodule "domain.so"
loadmodule "permissions.so"
loadmodule "group.so"
loadmodule "mi_fifo.so"
loadmodule "lcr.so"
loadmodule "avpops.so"
loadmodule "xlog.so"
# Uncomment this if you want digest authentication
# mysql.so must be loaded !
loadmodule "auth.so"
loadmodule "auth_db.so"
# ----------------- setting module-specific parameters ---------------
modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")
modparam("usrloc", "db_mode", 2)
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("rr", "enable_full_lr", 1)
modparam("auth_db|permissions|uri_db|usrloc","db_url","mysql://openserpenserrw@localhost/openser")
modparam("permissions", "db_mode", 1)
modparam("permissions", "trusted_table", "trusted")
modparam("avpops", "avp_url", "mysql://openserpenserrw@localhost/openser")
modparam("avpops", "avp_table", "usr_preferences")
# ------------------------- request routing logic -------------------
# main routing logic
route{
#
# -- 1 -- Request Validation
#
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
};
if (msg:len >= 2048 ) {
sl_send_reply("513", "Message too big");
exit;
};
#
# -- 2 -- Routing Preprocessing
#
## Record-route all except Register
if (!method=="REGISTER") record_route();
##Loose_route packets
if (has_totag()) {
#sequential request withing a dialog should
# take the path determined by record-routing
if (loose_route()) {
#Check authentication of re-invites
if(method=="INVITE" && (!allow_trusted())) {
if (!proxy_authorize("","subscriber")) {
proxy_challenge("","1");
exit;
} else if (!check_from()) {
sl_send_reply("403", "Forbidden, use From=ID");
exit;
};
};
route(1);
} else {
sl_send_reply("404","Not here");
}
exit;
}
#CANCEL processing
if (is_method("CANCEL")) {
if (t_check_trans()) t_relay();
exit;
};
t_check_trans();

#
# -- 3 -- Determine Request Target
#
if (method=="REGISTER") {
route(2);
} else {
route(3);
};
}

route[1] {
#
# -- 4 -- Forward request to target
#
## Forward statefully
t_on_failure("1");
if (!t_relay()) {
sl_reply_error();
};
exit;
}
route[2] {
## Register request handler
if (is_uri_host_local()) {
if (!www_authorize("", "subscriber")) {
www_challenge("", "1");
exit;
};
if (!check_to()) {
sl_send_reply("401", "Unauthorized");
exit;
};
save("location");
exit;
} else if {
sl_send_reply("401", "Unauthorized");
};
}
route[3] {
## Non-Register request handler
if (is_from_local()){
# From an internal domain -> check the credentials and FROM
if(!allow_trusted()){
if (!proxy_authorize("","subscriber")) {
proxy_challenge("","1");
exit;
} else if (!check_from()) {
sl_send_reply("403", "Forbidden, use From=ID");
exit;
};
} else {
log("Request bypassed the auth.using allow_trusted");
};
if(avp_db_load("$ru/username","$avp(s:callfwd)")) {
avp_pushto("$ru", "$avp(s:callfwd)");
route(1);
exit;
}
consume_credentials();
#Verify aliases, if found replace R-URI.
lookup("aliases");
if (is_uri_host_local()) {
# -- Inbound to Inbound
route(10);
} else {
# -- Inbound to outbound
route(11);
};
} else {
#From an external domain ->do not check credentials
#Verify aliases, if found replace R-URI.
lookup("aliases");
if (is_uri_host_local()) {
#-- Outbound to inbound
route(12);
} else {
# -- Outbound to outbound
route(13);
};
};
}
route[4] {
# routing to the public network
if (!load_gws()) {
sl_send_reply("503", "Unable to load gateways");
exit;
}
if(!next_gw()){
sl_send_reply("503", "Unable to find a gateway");
exit;
}
route(5);
exit;
}
route[5] {
#
# -- 4 -- T_relay for gateways
#
## Forward statefully, if failure load other gateways
t_on_failure("2");
if (!t_relay()) {
sl_reply_error();
};
exit;
}
route[10] {
#from an internal domain -> inbound
#Native SIP destinations are handled using the location table
#Gateway destinations are handled by regular expressions
append_hf("-hint: inbound->inbound \r\n");
if (uri=~"^sip:[2-9][0-9]{6}@") {
if (is_user_in("credentials","local")) {
prefix("+1");
route(4);
exit;
} else {
sl_send_reply("403", "No permissions for local calls");
exit;
};
};
if (uri=~"^sip:1[2-9][0-9]{9}@") {
if (is_user_in("credentials","ld")) {
strip(1);
prefix("+1");
route(4);
exit;
} else {
sl_send_reply("403", "No permissions for long distance");
exit;
};
};
if (uri=~"^sip:011[0-9]*@") {
if (is_user_in("credentials","int")) {
strip(3);
prefix("+");
route(4);
exit;
} else {
sl_send_reply("403", "No perm. for internat.calls");
};
};
if (!lookup("location")) {
if (does_uri_exist()) {
## User not registered at this time.
## Use the IP Address of your e-mail server
revert_uri();
prefix("u");
rewritehostport("192.168.1.171"); #Use the voicemail IP
route(1);
} else {
sl_send_reply("404", "Not Found");
exit;
}
sl_send_reply("404", "Not Found");
exit;
};
route(1);
}
route[11] {
# from an internal domain -> outbound
# Simply route the call outbound using DNS search
append_hf("-hint: inbound->outbound \r\n");
route(1);
}
route[12] {
# From an external domain -> inbound
# Verify aliases, if found replace R-URI.
lookup("aliases");
if (!lookup("location")) {
sl_send_reply("404", "Not Found");
exit;
};
route(1);
}
route[13] {
#From an external domain outbound
#we are not accepting these calls
append_hf("-hint: outbound->inbound \r\n");
sl_send_reply("403", "Forbidden");
exit;
}
failure_route[1] {
##--
##-- If cancelled, exit.
##--
if (t_check_status("487")) {
exit;
};
##--
##-- If busy send to the e-mail server, prefix the "b"
##-- character to indicate busy.
##--
if (t_check_status("486")) {
revert_uri();
prefix("b");
xlog("L_ERR","Stepped into the 486 ruri=<$ru>");
rewritehostport("192.168.1.171");
append_branch();
route(1);
exit;
};
##--
##-- If timeout (408) or unavailable temporarily (480),
##-- prefix the uri with the "u"character to indicate
##-- unanswered and send to the e-mail
##-- sever
##--
if (t_check_status("408") || t_check_status("480")) {
revert_uri();
prefix("u");
xlog("L_ERR","Stepped into the 480 ruri=<$ru>");
rewritehostport("192.168.1.171");
append_branch();
route(1);
exit;
};
}
failure_route[2] {
if(!next_gw()) {
t_reply("503", "Service not available, no more gateways");
exit;
}
t_on_failure("1");
t_relay();
}


tklor 发表于 2011-9-4 10:16 | 显示全部楼层
我也想了解了解!!!先顶一个













Gunyvst4 发表于 2015-12-26 19:47 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

关闭

站长推荐上一条 /1 下一条

手机版|VoIP88 ( 粤ICP备11095982号   填写您的邮件地址,订阅我们的精彩内容:

GMT+8, 2017-9-24 18:34 , Processed in 0.372204 second(s), 23 queries .

Powered by VoIP88

© 2001-2017 VoIP88

快速回复 返回顶部 返回列表