Freeswitch环境搭建及pstn网络呼出电话备忘

一,环境准备

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 编辑

 

<include>  
  <gateway name="81046873">
  <param name="realm" value="192.168.1.11:5060"/>
  <param name="username" value="8798092"/>
  <param name="password" value="***pwd"/>
  <param name="register" value="true"/>
  </gateway>
</include>

复制一个网关

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

创建一个出局规则,就是说客户端拨打什么样的号码走哪个网关出去

 

 

<include>
  <extension name="call out">
    <condition field="destination_number" expression="^out(\d+)$">
      <action application="bridge" data="sofia/gateway/810463/$1"/>
      <!--<action application="javascript" data="call_out.js $1"/>-->
    </condition>
  </extension>
</include>

注:上面的配置是说,当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

增加以下配置

 

<param name="xml-handler-script" value="gen_dir_user_xml.lua" /> 
<param name="xml-handler-bindings" value="directory" />

这两句是说用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 =
    [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <document type="freeswitch/xml">
      <section name="directory">
        <domain name="]] .. req_domain .. [[">
          <params>
        <param name="dial-string"
        value="{presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(${dialed_user}@${dialed_domain})}"/>
          </params>
          <groups>
        <group name="default">
          <users>
            <user id="]] .. req_user .. [[">
<params>
            <param name="password" value="]] .. req_password .. [["/>
            <param name="vm-password" value="]] .. req_password .. [["/>
              </params>
              <variables>     
<variable name="toll_allow" value="domestic,international,local"/>
            <variable name="accountcode" value="]] .. req_user .. [["/>
            <variable name="user_context" value="default"/>
            <variable name="directory-visible" value="true"/>
            <variable name="directory-exten-visible" value="true"/>
            <variable name="limit_max" value="15"/>
            <variable name="effective_caller_id_name" value="Extension ]] .. req_user .. [["/>
            <variable name="effective_caller_id_number" value="]] .. req_user .. [["/>
            <variable name="outbound_caller_id_name" value="${outbound_caller_name}"/>
            <variable name="outbound_caller_id_number" value="${outbound_caller_id}"/>
            <variable name="callgroup" value="techsupport"/>
              </variables>
            </user>
          </users>
        </group>
</groups>
        </domain>
      </section>
    </document>]];
    freeswitch.consoleLog("NOTICE", "用户注册完成\n\n");
else
    XML_STRING =
    [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <document type="freeswitch/xml">
      <section name="directory">
      </section>
    </document>]]
    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文件,删掉以下配置即可

 

<group name="default">
        <users>
          <X-PRE-PROCESS cmd="include" data="default/*.xml"/>
        </users>
</group>

至此,用户使用我们自己的数据库中的用户来进行注册,并且能通过一个pstn网关拨打电话出去了,但是由于网络电话供应商给我们透露了一个消息是一个gatway同一时间只能有一路通话,这样很明显是不行的,我们需要将业务员和想对应的gatway绑定起来,为了能够使业务员在拨打电话的时候可以动态的切换网关【比如说一个业务员在拨打电话的时候使用网关1,但是发现网关1正在被另一个业务员占用,就自动切换到另一个网关来播出电话】我是使用js来实现的,详细的步骤如下

 

----------------------------js处理电话呼出------------------------

刚才我们说了在呼出电话的时候配置了一个呼出规则,配置文件在  /usr/local/freeswitch/conf/dialplan/default/call_out.xml

 

<pre name="code" class="html"><include>
  <extension name="call out">
    <condition field="destination_number" expression="^out(\d+)$">
      <span style="font-family: Arial, Helvetica, sans-serif;"><!--</span><span style="font-family: Arial, Helvetica, sans-serif;"><action application="bridge" data="sofia/gateway/810463/$1"/></span><span style="font-family: Arial, Helvetica, sans-serif;">--></span>
      <action application="javascript" data="call_out.js $1"/>
    </condition>
  </extension>
</include>

 

 

 

注: 要使用js脚本,需要在 /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml 中将<loadmodule="mod_v8"/>打开 

将 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

 

<include>
  <extension name="public_did">
    <!--<condition field="destination_number" expression="^(81046092)$">-->
    <condition field="destination_number"  expression="^(\d+)$">
      <!--<action application="transfer" data="10002 XML default"/>-->
      <action application="record_session" data="$${base_dir}/recordings/archive/callIn/callIn_${strftime(%Y-%m-%d-%H-%M-%S)}_${caller_id_number}_$1.wav"/>
      <action application="javascript" data="call_in.js"/>
    </condition>
  </extension>
</include>


创建 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();

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值