JsSIP和FreeSWITCH整合

Stella981
• 阅读 1753

写在前面:FreeSWITCH作为服务器,通过SIP协议,Web端使用jssip+webrtc和其他软电话进行通信

一、先配置FreeSWITCH(用的版本1.6.20)的配置:

1 、修改vars.xml文件,找到下面字段,并设置

<X-PRE-PROCESS cmd="set" data="internal_ssl_enable=true"/>
<X-PRE-PROCESS cmd="set" data="external_auth_calls=true"/>
<X-PRE-PROCESS cmd="set" data="external_ssl_enable=true"/>

2、修改 autoload_configs/acl.conf.xml文件,增加acl选项

    <list name="wan" default="allow">
        <node type="allow" cidr="10.10.21.0/22"/>
        <node type="allow" cidr="10.250.250.0/24"/>
    </list>

在配置文件 sip_profiles/internal.xml 增加如下配置

<param name="apply-candidate-acl" value="wan"/>

默认情况下建立连接失败,提示下面错误,并呼叫失败

a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [WARNING] switch_core_media.c:3451 NO candidate ACL defined, Defaulting to wan.auto
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] switch_core_media.c:3481 Save audio Candidate cid: 1 proto: udp type: host addr: 10.10.21.32:52786
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] switch_core_media.c:3523 Searching for rtp candidate.
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] switch_core_media.c:3523 Searching for rtcp candidate.
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] switch_core_media.c:3567 sofia/internal/82s6ps5e@80ug9oo63ltj.invalid no suitable candidates found.
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] switch_core_media.c:4767
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [NOTICE] sofia.c:8240 Hangup sofia/internal/82s6ps5e@80ug9oo63ltj.invalid [CS_CONSUME_MEDIA] [INCOMPATIBLE_DESTINATION]
5fe89e1d-bb0c-473b-8877-d3648acd4076 2018-08-09 20:28:15.217384 [DEBUG] switch_core_codec.c:248 sofia/internal/1009@192.168.20.78 Restore previous codec PCMA:8.
a21d347d-5622-451b-a1db-d241ca823e4d 2018-08-09 20:28:15.217384 [DEBUG] sofia.c:1453 Channel is already hungup.

在配置文件 sip_profiles/internal.xml 增加如下配置,解决这个问题

<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>

二、编写Web客户端

样式如下: JsSIP和FreeSWITCH整合 不是专业前端,没有做布局

启动之后,就和正常的SIP软终端一致了,通过FreSWITCH拨打其他软终端,测试正常。

源代码:基于JsSIP的客户端,参考网上,并自己修改并调试通过

<!DOCTYPE html>
<html>
<head>
    <title>JsSIP 对接 FreeSWITCH</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="Author" content="wangweichao"/>
    <meta name="description" content="JsSIP based example web application."/>
    <script src="js/jssip-3.0.13.min.js" type="text/javascript"></script>
    <style type="text/css">
    </style>
</head>


<body>
<div id="login-page"
     style="width: 424px; height: 260px; background-color: #f2f4f4; border: 1px solid grey; padding-top: 4px">
    <table border="0" frame="void" width="418px">
        <tr>
            <td class="td_label" width="160px" align="right"><label for="sip_uri">SIP URI:</label></td>
            <td width="258px"><input style="width:250px" id="sip_uri" type="text" value="sip:1009@192.168.20.78"/></td>
        </tr>
        <tr>
            <td class="td_label" align="right"><label for="sip_password">SIP Password:</label></td>
            <td><input style="width:250px" id="sip_password" type="password" value="654321"/></td>
        </tr>
        <tr>
            <td class="td_label" align="right"><label for="ws_uri">WSS URI:</label></td>
            <td><input style="width:250px" id="ws_uri" class="last unset" type="text" value="ws://192.168.20.78:5066"/>
            </td>
        </tr>
        <tr>
            <td class="td_label" align="right"><label class="input_label" for="sip_phone_number">SIP Phone Info:</label>
            </td>
            <td><input style="width:250px" id="sip_phone_number" type="text" value="1007"></td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <button onclick="testStart()"> 初始化</button>
            </td>
        </tr>

        <tr>
            <td colspan="5" align="center">
                <button onclick="reg()"> 注册</button>
            </td>
        </tr>

        <tr>
            <td colspan="5" align="center">
                <button onclick="unReg()"> 注销</button>
            </td>
        </tr>

        <tr>
            <td colspan="2" align="center">
                <button onclick="testCall()"> 呼叫</button>
            </td>
        </tr>

        <tr>
            <td colspan="5" align="center">
                <button onclick="hangup()"> 挂断</button>
            </td>
        </tr>
    </table>
</div>

<video id="videoView" width="420px" height="320px" autoplay></video>

</body>
<script type="text/javascript">
    var outgoingSession = null;
    var incomingSession = null;
    var currentSession = null;
    var videoView = document.getElementById('videoView');

    var constraints = {
        audio: true,
        video: false,
        mandatory: {
            maxWidth: 640,
            maxHeight: 360
        }
    };
    URL = window.URL || window.webkitURL;

    var localStream = null;
    var userAgent = null;


    function testStart() {

        var sip_uri_ = document.getElementById("sip_uri").value.toString();
        var sip_password_ = document.getElementById("sip_password").value.toString();
        var ws_uri_ = document.getElementById("ws_uri").value.toString();

        console.info("get input info: sip_uri = ", sip_uri_, " sip_password = ", sip_password_, " ws_uri = ", ws_uri_);

        var socket = new JsSIP.WebSocketInterface(ws_uri_);
        var configuration = {
            sockets: [socket],
            outbound_proxy_set: ws_uri_,
            uri: sip_uri_,
            password: sip_password_,
            register: true,
            session_timers: false
        };

        userAgent = new JsSIP.UA(configuration);

        //注册成功
        userAgent.on('registered', function (data) {
            console.info("registered: ", data.response.status_code, ",", data.response.reason_phrase);
        });

        //注册失败
        userAgent.on('registrationFailed', function (data) {
            console.log("registrationFailed, ", data);
            //console.warn("registrationFailed, ", data.response.status_code, ",", data.response.reason_phrase, " cause - ", data.cause);
        });

        //注册超时
        userAgent.on('registrationExpiring', function () {
            console.warn("registrationExpiring");
        });

        userAgent.on('newRTCSession', function (data) {
            console.info('onNewRTCSession: ', data);

            //通话呼入
            if (data.originator == 'remote') {
                console.info("incomingSession, answer the call----------------------");
                incomingSession = data.session;
                data.session.answer({
                    'mediaConstraints': {
                        'audio': true,
                        'video': false,
                        mandatory: {maxWidth: 640, maxHeight: 360}
                    }, 'mediaStream': localStream
                });
            } else {
                console.info("outgoingSession");
                outgoingSession = data.session;
                outgoingSession.on('connecting', function (data) {
                    console.info('onConnecting - ', data.request);
                    currentSession = outgoingSession;
                    outgoingSession = null;
                });
            }
            data.session.on('accepted', function (data) {
                console.info('onAccepted - ', data);
                if (data.originator == 'remote' && currentSession == null) {
                    currentSession = incomingSession;
                    incomingSession = null;
                    console.info("setCurrentSession - ", currentSession);
                }
            });
            data.session.on('confirmed', function (data) {
                console.info('onConfirmed - ', data);
                if (data.originator == 'remote' && currentSession == null) {
                    currentSession = incomingSession;
                    incomingSession = null;
                    console.info("setCurrentSession - ", currentSession);
                }
            });
            data.session.on('sdp', function (data) {
                console.info('onSDP, type - ', data.type, ' sdp - ', data.sdp);
            });

            data.session.on('progress', function (data) {
                console.info('onProgress - ', data.originator);
                if (data.originator == 'remote') {
                    console.info('onProgress, response - ', data.response);
                }
            });
            data.session.on('peerconnection', function (data) {
                console.info('onPeerconnection - ', data.peerconnection);
                data.peerconnection.onaddstream = function (ev) {
                    console.info('onaddstream from remote ----------- ', ev);
                    videoView.src = URL.createObjectURL(ev.stream);
                };
            });
        });

        userAgent.on('newMessage', function (data) {
            if (data.originator == 'local') {
                console.info('onNewMessage , OutgoingRequest - ', data.request);
            } else {
                console.info('onNewMessage , IncomingRequest - ', data.request);
            }
        });

        console.info("call register");

        userAgent.start();
    }

    // Register callbacks to desired call events
    var eventHandlers = {
        'progress': function (e) {
            console.log('call is in progress');
        },
        'failed': function (e) {
            console.log('call failed: ', e);
        },
        'ended': function (e) {
            console.log('call ended : ', e);
        },
        'confirmed': function (e) {
            console.log('call confirmed');
        }
    };

    function testCall() {
        var sip_phone_number_ = document.getElementById("sip_phone_number").value.toString();

        var options = {
            'eventHandlers': eventHandlers,
            'mediaConstraints': {
                'audio': true, 'video': false,
                mandatory: {maxWidth: 640, maxHeight: 360}
            },
            'mediaStream': localStream
        };

        outgoingSession = userAgent.call(sip_phone_number_, options);
    }
    function reg() {
        console.log('register----------->');
        userAgent.register();
    }

    function unReg() {
        console.log('unregister----------->');
        userAgent.unregister(true);
    }

    function hangup() {
        console.log('hangup----------->');
        userAgent.terminateSessions();
    }

</script>
</html>
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这