一,环境准备
1,系统:centos 6.7
2,下载freeswitch及安装前环境准备
git clonehttps://freeswitch.org/stash/scm/fs/freeswitch.git
# Add the RPM repository
rpm -ivh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
### OR a European repository
rpm -ivh http://mirror.cedia.org.ec/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
# Install necessary components
yum install git gcc-c++ autoconf automake libtool wget python ncurses-devel zlib-devel libjpeg-devel openssl-devel e2fsprogs-devel sqlite-devel libcurl-devel pcre-devel speex-devel ldns-devel libedit-devel
ps:执行时间比较久,建议使用screen来多个过程一起来执行
将clone下来的文件放在/usr/src目录下,进入目录执行以下命令
ps:注意官方推荐在centos6.7版本下使用v1.4,所以需要切换到v1.4分支下执行配置安装
./bootstrap.sh -j
因为我是用javascript做开发的,所以需要打开mod_v8模块,下面会在pstn电话呼入和呼出中使用到v8模块,由于个人比较喜欢写js,所以在做电话呼出路由选择和呼入分机转接的时候就用js来写了。详见下文
vi modules.conf
找到 languages/mod_v8 取消注释
./configure -C
make && make install
........等待安装完成
安装sounds
make cd-sounds-install
make cd-moh-install
创建freeswitch管理账号及软链接
cd /usr/local
useradd --system --home-dir /usr/local/freeswitch -G daemon freeswitch
passwd -l freeswitch
chown -R freeswitch:daemon /usr/local/freeswitch/
chmod -R 770 /usr/local/freeswitch/
chmod -R 750 /usr/local/freeswitch/bin/*
mkdir /var/run/freeswitch
chown -R freeswitch:daemon /var/run/freeswitch
ln -s /usr/local/freeswitch/bin/freeswitch /usr/bin/ # needed by /etc/init.d/freeswitch
--------------------安装完成-------------------
控制台执行freeswitch命令启动freeswitch
--------------------wss配置------------------
1,编辑sip_profiles/internal.xml
打开 name="ws-binding" value=":5066"注释
打开 name="wss-binding" value=":7443" 注释
2.编辑 vars.xml 找到下面的设置并更改
data="internal_ssl_enable=true"
data="external_ssl_enable=true"
创建wss.pem
wget http://files.freeswitch.org/downloads/ssl.ca-0.1.tar.gz
tar zxfv ssl.ca-0.1.tar.gz
cd ssl.ca-0.1/
perl -i -pe 's/md5/sha256/g' *.sh
perl -i -pe 's/1024/4096/g' *.sh
./new-root-ca.sh
./new-server-cert.sh self.bkw.org
./sign-server-cert.sh self.bkw.org
cat self.bkw.org.crt self.bkw.org.key > /usr/local/freeswitch/certs/wss.pem
ps:如果需要走wss协议,需要在入口机器上配置ssl【必须是认证过的证书才能有效,否则会出现握手失败的错误】
----------------------配置pstn呼出-----------------
网关配置在目录:/usr/local/freeswitch/conf/sip_profiles/external
增加一个pstn网关,创建一个xml 如:gw_pstn.xml 编辑
复制一个网关
sed -e "s/81046865/81046873/" gw_pstn.xml > gw_pstn1.xml
批量生成网关
for i in `seq 810474 810402`;do sed -e "s/81046865/$i/" gw_pstn.xml > gw_$i.xml;done
sed -e "s/8004/5009/“ gw_pstn.xml > gw_pstn_5009.xml
for i in `seq 5030 5050`;do sed -e "s/8004/$i/" gw_pstn.xml > gw_pstn_$i.xml;done
sofia profile external restart
创建一个出局规则,就是说客户端拨打什么样的号码走哪个网关出去
注:上面的配置是说,当sip客户端拨打outXXXXX号码的时候,freeswitch会转到810463网关将电话打出去
----------------------------使用mysql数据库进行客户端账号注册--------------------------
组建:unixODBC
unixODBC是一个可以让你在Unix/Linux系统下使用ODBC来连接数据库的组件,就像java中的mysql-connector-java-5.1.6-bin.jar一样,负责连接数据库的
安装:
yum install unixODBC-devel.x86_64
yum install mysql-connector-odbc.x86_64
安装后修改两个文件:/etc/odbc.ini,/etc/odbcinst.ini
/etc/odbc.ini 配置要连接的数据库信息
[freeswitch]
Driver = /usr/lib64/libmyodbc5.so
SERVER = ip
PORT = 3306
DATABASE = database
USER = user
PASSWORD = password
/etc/odbcinst.ini 修改mysq的部分,将驱动包指向正确,这要根据你本身的包安装路径配置
[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib64/libmyodbc5.so
Setup = /usr/lib64/libodbcmyS.so
Driver64 = /usr/lib64/libmyodbc5.so
Setup64 = /usr/lib64/libodbcmyS.so
FileUsage = 1
检查是否安装成功,控制台输入命令 isql -v freeswitch
修改从lua脚本注册用户 /usr/local/freeswitch/conf/autoload_configs/lua.conf.xml
增加以下配置
这两句是说用lua脚本来接管用户的注册,脚本的默认路径是 freeswitch/script/
local req_domain = params:getHeader("domain")
local req_key = params:getHeader("key")
local req_user = params:getHeader("user")
local req_password = params:getHeader("pass")
freeswitch.consoleLog("NOTICE", "收到客户端注册请求,请求账号:"..req_user.."\n");
if req_password ~= nil then
freeswitch.consoleLog("NOTICE", "收到客户端注册请求,请求密码:"..req_password.."\n");
end
freeswitch.consoleLog("NOTICE", "开始连接数据库查找用户信息\r\n");
local dbh = freeswitch.Dbh("freeswitch", "user", "pwd");
assert(dbh:connected());
dbh:query("select * from sysUsr where usrCode=" .. req_user, function(row)
freeswitch.consoleLog("NOTICE", string.format("%s\n", row.usrCode))
req_password = string.format("%s", row.usrCode)
end);
dbh:release();
if req_password ~= nil then
freeswitch.consoleLog("NOTICE", "info:用户注册信息匹配完成:" .. req_domain .. "--" .. req_key .. "--" .. req_user .. "--" .. req_password .. "\n");
else
freeswitch.consoleLog("error", "用户信息验证失败\r\n");
end
if req_domain ~= nil and req_key ~= nil and req_user ~= nil and req_password ~= nil then
XML_STRING =
[[
]];
freeswitch.consoleLog("NOTICE", "用户注册完成\n\n");
else
XML_STRING =
[[
]]
freeswitch.consoleLog("ERROR", "用户注册失败\n\n");
end
ps:在配置后启动出现了一个483 Failure! ODBC NOT AVAILABLE! 错误,这是因为在v1.4版本中没有默认加上odbc功能模块,需要进入/usr/src/freeswitch目录 执行以下命令
./configure --enable-core-odbc-support
make&&make install
重启,fs_cli进入fs控制台,注册一个数据库中的用户
查看到以上信息,说明lua接管用户注册成功
如果需要去掉默认的用户注册,只需要修改 /usr/local/freeswitch/conf/directory/default.xml文件,删掉以下配置即可
至此,用户使用我们自己的数据库中的用户来进行注册,并且能通过一个pstn网关拨打电话出去了,但是由于网络电话供应商给我们透露了一个消息是一个gatway同一时间只能有一路通话,这样很明显是不行的,我们需要将业务员和想对应的gatway绑定起来,为了能够使业务员在拨打电话的时候可以动态的切换网关【比如说一个业务员在拨打电话的时候使用网关1,但是发现网关1正在被另一个业务员占用,就自动切换到另一个网关来播出电话】我是使用js来实现的,详细的步骤如下
----------------------------js处理电话呼出------------------------
刚才我们说了在呼出电话的时候配置了一个呼出规则,配置文件在 /usr/local/freeswitch/conf/dialplan/default/call_out.xml
注: 要使用js脚本,需要在 /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml 中将
将 application="bridge" 注释掉,将 application="javascript" 打开,使用call_out.js来处理电话的呼出。注$1是参数 call_out.js 如下:
use("ODBC");
function callOut() {
var gatway = queryGatway(session.caller_id_number);
if (gatway != null) {
playFile(session, "/usr/local/freeswitch/sounds/pengshu/zhuanjie.wav");
var outsession = new Session("sofia/gateway/" + gatway + "/" + argv[0]);
if (!outsession.ready()) {
outsession = pollGatWay(argv[0]);
}
if (outsession != null&&outsession.ready()) {
bridge(session, outsession, logAndStopBridge);
session.hangup();
outsession.hangup();
} else {
session.hangup();
outsession.hangup();
}
} else {
playFile(session, "/usr/local/freeswitch/sounds/pengshu/gatway-error.wav");
console_log("获取网关失败");
session.hangup();
}
}
function logAndStopBridge() {
session.hangup();
session.close();
return false;
}
function playFile(session, file, callBack, callBackArgs) {
session.streamFile(file, callBack, callBackArgs);
}
function queryGatway(account) {
console_log("开始查询" + account + "网关");
var db = new ODBC("freeswitch_system", "account", "pwd");
db.connect();
var sql = "select * from sip_gatway where account=" + account;
db.exec(sql);
var gatway = null;
while (db.nextRow()) {
var row = db.getData();
console_log("查询到数据:" + row['account'] + "-->" + row['gatway'])
gatway = row['gatway'];
}
return gatway;
}
function pollGatWay(phone) {
var pollSession = null;
var db = new ODBC("freeswitch_system", "account", "pwd");
db.connect();
console_log("========开始轮询手机========");
var sql = "select * from sip_gatway";
db.exec(sql);
while (db.nextRow()) {
var row = db.getData();
pollSession = new Session("sofia/gateway/" + row["gatway"] + "/" + phone);
if (pollSession.ready()) {
return pollSession;
}
}
return null;
}
callOut();
-------------------------js处理电话呼入----------------------
我们想电话呼入的时候可以自动的选择来电客户属于哪个业务员,如果业务员坐席没有接听,自动转接到其他业务员坐席,所有业务员都不在坐席的话轮询转接到业务员的手机上,直至有接听未知,若全部都没有接听,则挂断电话
首先,创建呼入规则 /usr/local/freeswitch/conf/dialplan/public/call_in.xml
创建 call_in.js 【默认目录在freeswitch/scripts】
use("ODBC");
function answerCallIn() {
session.answer();
playFile("zhuanjie.wav");
while (session.ready()) {
console_log("=============开始同振==============");
var num = queryPhone();
var firstCallStr = "[leg_timeout=30,origination_caller_id_name='" + session.caller_id_name + "',origination_caller_id_number='" + session.caller_id_number + "']user/" + num + "|";
var callStr = firstCallStr + mosaicCallNum(session, num);
//同振
//callStr.replace(/|/g, ",");
bridge(session, new Session(callStr), logAndStopBridge);
}
}
function logAndStopBridge() {
session.hangup();
mySession.hangup();
return false;
}
function queryPhone() {
var result = fetchUrl("http://19.02.4.3/getdata");
if (result.success) {
console_log("获取http请求数据成功");
}
console_log("号码查询成功");
return "[leg_timeout=30,origination_caller_id_name='" + session.caller_id_name + "',origination_caller_id_number='" + session.caller_id_number + "']user/13524544334" + "|";
}
function playFile(fileName, callBack, callBackArgs) {
session.streamFile("/usr/local/freeswitch/sounds/pengshu/" + fileName, callBack, callBackArgs);
}
function mosaicCallNum(session, num) {
var db = new ODBC("freeswitch_system", "root", "ps@mysql");
var accountStr = "";
var phoneStr = "";
db.connect();
var sql = "select * from sip_gatway";
db.exec(sql);
while (db.nextRow()) {
var row = db.getData();
if (row["account"] != num && row["account"] && row["phone"]) {
accountStr += "[leg_timeout=30,origination_caller_id_name='" + session.caller_id_name + "',origination_caller_id_number='" + session.caller_id_number + "']user/" + row["account"] + "|"
phoneStr += "[leg_timeout=30]sofia/gateway/" + row["gatway"] + "/" + row["phone"] + "|"
}
}
var callStr = accountStr + phoneStr;
return callStr.substring(0, callStr.length - 1);
}
answerCallIn();