当前位置: 首页 > 工具软件 > SIP.js > 使用案例 >

配置Nginx wss连接FreeSwitch的ws地址,使用sip.js进行测试(成功版)

阎辰钊
2023-12-01

具体请先看nginx的webrtc配置WebRTC - FreeSWITCH - Confluence

map $http_upgrade $connection_upgrade {
     default upgrade;
     ''      close;
}
 
server {
     listen 443;
     server_name  wss.somedomain.com.ua;
 
     ssl on;
     ssl_certificate      /etc/nginx/cert.pem;
     ssl_certificate_key  /etc/nginx/private.key;
 
     location / {
         proxy_pass http://127.0.0.1:5066;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection $connection_upgrade;
         proxy_read_timeout 86400s;
    }
 
     access_log /var/log/nginx/wss_access;
     error_log /var/log/nginx/wss_error debug; }

配置好后,就可以使用前端连接sip.js配置了

具体源码如下:sipjs-demo.7z-Web开发文档类资源-CSDN下载

这个是在csdn下载的sip.js测试代码,具体地址提供忘记了,所以用了我上传的资源

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>sipjstest</title>
    <link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div>
    <input id="number" value="1000" type="text"/>
    <button id="startCall">Start Call</button>
    <button id="endCall">End Call</button>
    <button id="transfer">transfer</button>
    <button id="hold">hold</button>
    <button id="unhold">unhold</button>
    <button id="mute">mute</button>
    <button id="unmute">unmute</button>
</div>
<br>
<div>
    <input id="msg" value="你好" type="text"/>
    <button id="sendMessage">Send Message</button>

    <audio id="ringtone" loop src="./sounds/ringtone.wav"></audio>            <!--//来电提示音-->
    <audio id="ringbacktone" loop src="./sounds/ringbacktone.wav"></audio>    <!--//电话呼叫后声音-->
    <audio id="dtmfTone" src="./sounds/dtmf.wav"></audio>

    <video id="remoteVideo" autoplay="autoplay"></video>
    <video id="localVideo" autoplay="autoplay" muted="muted"></video>
    <!-- DTMF -->
    <div id="dtmf-buttons">
        <button onclick="sendDtmf('1');">1</button>
        <button onclick="sendDtmf('2');">2</button>
        <button onclick="sendDtmf('3');">3</button>
        <button onclick="sendDtmf('4');">4</button>
        <button onclick="sendDtmf('5');">5</button>
        <button onclick="sendDtmf('6');">6</button>
        <button onclick="sendDtmf('7');">7</button>
        <button onclick="sendDtmf('8');">8</button>
        <button onclick="sendDtmf('9');">9</button>
        <button onclick="sendDtmf('0');">0</button>
        <button onclick="sendDtmf('#');">#</button>
        <button onclick="sendDtmf('*');">*</button>
    </div>
</div>

<script src="./js/sip-0.15.6.js"></script>
<script>

    var extCode = "1004"; //分机号
    var extPass = "123456"; //分机密码
    var config = {
        //uri: "sip:" +extCode + '@testfs.com.cn',
        uri: "sip:" +extCode + '@192.168.61.140:11889',
        //uri: "sip:" +extCode + '@192.168.61.73.com',
        authorizationUser: extCode,
        password: extPass,
        displayName: extCode,
        log: {
            builtinEnabled: true,
            level: 3 // log日志级别
        },
        transportOptions: {
            //wsServers: ['wss://你的域名:11443'], // wss 目前chrome 必须使用https才可以调起媒体 服务使用https 连接fs则相应需要使用wss  本地测试可以配套自签证书使用(如果没有真实的证书)
            wsServers: ['wss://zhaoxin.tech'],
            traceSip: true  //开启sip日志,用于排查问题
        },
        allowLegacyNotifications: true,
        hackWssInTransport: false, // 设置为true 则注册时 transport=wss; false:transport=ws;
        /**
         * sip.js生成的随机contact字符串 设置后会以此为后缀 可以搭配 cusContactName使用,根据自身业务进行使用
         *  设置前: sofia/internal/sip:asdasdfawg@df7jal23ls0d.invalid;
         *  设置后: sofia/internal/sip:asdasdfawg@192.168.0.253;
         *
         */
        userAgentString: "sipJsDemo",
        //hackIpInContact: "192.168.61.140",
        /*
        registerOptions: {
            expires: 300,
            registrar: 'sip:iscc.yonyou.com',
        },
        */
        /**
         * 此处是笔者自定义的参数,因为注册到fs时,sip.js会随机生成contact字符串,如:sofia/internal/sip:admin10@df7jal23ls0d.invalid;
         *  笔者自己添加了一个参数,对sip.js的源码进行了修改 ,修改后效果  sofia/internal/sip:1012@192.168.0.253 不需要的可以不理会此参数
         */
        cusContactName: extCode,
        // rel100: SIP.C.supported.UNSUPPORTED,
        // dtmfType: SIP.C.dtmfType.RTP,
    };
    //var ua = new SIP.UA(config);
    var ua = new SIP.UA(config);

    var sessionall;
    var startCall = document.getElementById('startCall');
    var endCall = document.getElementById('endCall');
    var transfer = document.getElementById('transfer');
    var hold = document.getElementById('hold');
    var unhold = document.getElementById('unhold');
    var sendMessage = document.getElementById('sendMessage');
    var mute = document.getElementById('mute');
    var unmute = document.getElementById('unmute');

    var Ring={
        /**
         * 振铃
         */
        startRingTone: function () {
            document.getElementById("ringtone").play();
            /*
            let play = document.getElementById("ringtone").play();
            play.then(()=>{

            }).catch((err)=>{

            });
            */

        },
        /**
         * 停止振铃
         */
        stopRingTone: function () {
            document.getElementById("ringtone").pause();
        },

        startRingbackTone: function () {
            document.getElementById("ringbacktone").play();
            /*
            let play = document.getElementById("ringbacktone").play();
            play.then(()=>{

            }).catch((err)=>{


            });
            */
        },
        stopRingbackTone: function () {
            document.getElementById("ringbacktone").pause();
        }


    };

    /**
     *  绑定方法
     * @param obj 要绑定事件的元素
     * @param ev 绑定的事件
     * @param fn  绑定事件的函数
     */
    function bindEvent(obj, ev, fn) {
        if (obj.attachEvent) {
            obj.attachEvent("on" + ev, fn);
        }
        else {
            obj.addEventListener(ev, fn, false);
        }
    }

    /**
     *  发送DTMF
     * @param num 按键
     */
    function sendDtmf(num) {
        sessionall.dtmf(num);
    }

    /**
     * 拨打电话
     */
    bindEvent(startCall, 'click', function () {


        var number = document.getElementById("number").value;
        //创建一个新的出站(用户代理客户端)会话
        sessionall = ua.invite(number, {
            sessionDescriptionHandlerOptions: {
                constraints: {
                    audio: true,
                    video: false
                },
                alwaysAcquireMediaFirst: true // 此参数是sip.js官方修复在firefox遇到的bug所设置
            }
        });

        //开始嘟嘟嘟
        Ring.startRingbackTone();


        var remoteVideo = document.getElementById('remoteVideo');
        var localVideo = document.getElementById('localVideo');


        //每次收到成功的最终(200-299)响应时都会触发。
        sessionall.on("accepted", function (response, cause) {
            console.log(response);
            Ring.stopRingbackTone();
            var pc = this.sessionDescriptionHandler.peerConnection;
            var remoteStream;

            if (pc.getReceivers) {
                remoteStream = new window.MediaStream();
                pc.getReceivers().forEach(function (receiver) {
                    var track = receiver.track;
                    if (track) {
                        remoteStream.addTrack(track);
                    }
                });
            } else {
                remoteStream = pc.getRemoteStreams()[0];
            }
            remoteVideo.srcObject = remoteStream;


            var localStream_1;
            if (pc.getSenders) {
                localStream_1 = new window.MediaStream();
                pc.getSenders().forEach(function (sender) {
                    var track = sender.track;
                    if (track && track.kind === "video") {
                        localStream_1.addTrack(track);
                    }
                });
            }
            else {
                localStream_1 = pc.getLocalStreams()[0];
            }
            localVideo.srcObject = localStream_1;
        });

        sessionall.on('progress', function (response, cause) {
            console.log(response);
            Ring.stopRingbackTone();
            console.warn('开始振铃!。。');
            console.warn(response.statusCode);

            if (response.statusCode === 183) {
                sessionall.createDialog(response, 'UAC');
                sessionall.hasAnswer = true;
                sessionall.status = 11;
                sessionall.sessionDescriptionHandler.setDescription(response.body)
                    .catch(function (exception) {
                        sessionall.logger.warn(exception);
                        sessionall.failed(response, C.causes.BAD_MEDIA_DESCRIPTION);
                        sessionall.acceptAndTerminate({status_code: 488, reason_phrase: 'Bad Media Description'});
                    });

            }});



        //每次收到成功的最终(200-299)响应时都会触发。
        sessionall.on("accepted", function (response, cause) {
            console.log(response);
            Ring.stopRingbackTone();
            var pc = this.sessionDescriptionHandler.peerConnection;
            var remoteStream;

            if (pc.getReceivers) {
                remoteStream = new window.MediaStream();
                pc.getReceivers().forEach(function (receiver) {
                    var track = receiver.track;
                    if (track) {
                        remoteStream.addTrack(track);
                    }
                });
            } else {
                remoteStream = pc.getRemoteStreams()[0];
            }
            remoteVideo.srcObject = remoteStream;


            var localStream_1;
            if (pc.getSenders) {
                localStream_1 = new window.MediaStream();
                pc.getSenders().forEach(function (sender) {
                    var track = sender.track;
                    if (track && track.kind === "video") {
                        localStream_1.addTrack(track);
                    }
                });
            }
            else {
                localStream_1 = pc.getLocalStreams()[0];
            }
            localVideo.srcObject = localStream_1;
        })

        //挂机时会触发
        sessionall.on("bye", function (response, cause) {
            Ring.stopRingbackTone();
            console.log(response);
        })

        //请求失败时触发,无论是由于最终响应失败,还是由于超时,传输或其他错误。
        sessionall.on("failed", function (response, cause) {
            Ring.stopRingbackTone();
            console.log(response);
        })

        /**
         *
         */
        sessionall.on("terminated", function (message, cause) {
            Ring.stopRingbackTone();
        })

        /**
         * 对方拒绝
         */
        sessionall.on('rejected', function (response, cause) {
            Ring.stopRingbackTone();
        })
    })


    //挂断事件
    bindEvent(endCall, 'click', function () {
        if (!sessionall) {
            return;
        } else if (sessionall.startTime) { // Connected
            sessionall.bye();
        } else if (sessionall.reject) { // Incoming
            sessionall.reject();
        } else if (sessionall.cancel) { // Outbound
            sessionall.cancel();
        }
    })



    //电话转移盲转
    bindEvent(transfer, 'click', function () {
        if (!sessionall) {
            return;
        }
        var number = document.getElementById("number").value;
        sessionall.refer(number, {
            receiveResponse: function (msg, ss) {
                console.info(msg);
                console.info(ss);
            }
        });
    })


    //电话保持
    bindEvent(hold, 'click', function () {
        if (!sessionall) {
            return;
        }
        sessionall.hold();
    })


    //恢复电话保持
    bindEvent(unhold, 'click', function () {
        if (!sessionall) {
            return;
        }
        sessionall.unhold();
    })

    //发送消息
    bindEvent(sendMessage, 'click', function () {
        // Sends a new message
        var number = document.getElementById("number").value;
        var message = document.getElementById("msg").value;
        ua.message(number, message);
        // When receiving a message, prints it out
        ua.on('message', function (message) {
            console.log(message.body);
        });
    })

    // 静音
    bindEvent(mute, 'click', function () {
        if (!sessionall) {
            console.warn("No session to toggle mute");
            return;
        }

        var pc = sessionall.sessionDescriptionHandler.peerConnection;
        if (pc.getSenders) {
            pc.getSenders().forEach(function (sender) {
                if (sender.track) {
                    sender.track.enabled = false;
                }
            });
        } else {
            pc.getLocalStreams().forEach(function (stream) {
                stream.getAudioTracks().forEach(function (track) {
                    track.enabled = false;
                });
                stream.getVideoTracks().forEach(function (track) {
                    track.enabled = false;
                });
            });
        }
    })

    // 解除静音
    bindEvent(unmute, 'click', function () {
        if (!sessionall) {
            console.warn("No session to toggle mute");
            return;
        }

        var pc = sessionall.sessionDescriptionHandler.peerConnection;
        if (pc.getSenders) {
            pc.getSenders().forEach(function (sender) {
                if (sender.track) {
                    sender.track.enabled = true;
                }
            });
        } else {
            pc.getLocalStreams().forEach(function (stream) {
                stream.getAudioTracks().forEach(function (track) {
                    track.enabled = true;
                });
                stream.getVideoTracks().forEach(function (track) {
                    track.enabled = true;
                });
            });
        }
    })


    // 接受入站(用户代理服务器)会话
    ua.on('invite', function (session) {
        // 开始振铃
        Ring.startRingTone();
        var url = session.remoteIdentity.uri.toString() + "来电了,是否接听";

        var remoteVideo = document.getElementById('remoteVideo');
        var localVideo = document.getElementById('localVideo');


        session.on("terminated", function (message, cause) {
            Ring.stopRingTone();
            console.info(message);

        })

        /**
         *
         */
        session.on('accepted', function (response, cause) {
            console.info(response);
            console.info(session);
            Ring.stopRingTone();
            // If there is a video track, it will attach the video and audio to the same element
            var pc = this.sessionDescriptionHandler.peerConnection;
            console.info(this.sessionDescriptionHandler);
            var remoteStream;

            if (pc.getReceivers) {
                remoteStream = new window.MediaStream();
                pc.getReceivers().forEach(function (receiver) {
                    var track = receiver.track;
                    if (track) {
                        remoteStream.addTrack(track);
                    }
                });
            } else {
                remoteStream = pc.getRemoteStreams()[0];
            }
            remoteVideo.srcObject = remoteStream;


            var localStream_1;
            if (pc.getSenders) {
                localStream_1 = new window.MediaStream();
                pc.getSenders().forEach(function (sender) {
                    var track = sender.track;
                    if (track && track.kind === "video") {
                        localStream_1.addTrack(track);
                    }
                });
            }
            else {
                localStream_1 = pc.getLocalStreams()[0];
            }
            localVideo.srcObject = localStream_1;
            localVideo.volume = 0;


        })

        session.on('bye', function (resp, cause) {
            Ring.stopRingTone();
        });

        var isaccept = confirm(url);
        if (isaccept) {
            //接受来电
            session.accept({
                sessionDescriptionHandlerOptions: {
                    constraints: {
                        audio: true,
                        video: false
                    }
                }
            });
            sessionall = session;
        }
        else {
            //拒绝来电
            session.reject();
        }

    });

</script>

</body>
</html>

修改sip-0.15.6.js

 //var via = "SIP/2.0/" + scheme;

改成
  var via = "SIP/2.0/WS";

OutgoingRequestMessage.prototype.setViaHeader = function (branch, scheme) {
        if (scheme === void 0) { scheme = "WSS"; }
        // FIXME: Hack
        if (this.options.hackViaTcp) {
            scheme = "TCP";
        }
        //var via = "SIP/2.0/" + scheme;
        var via = "SIP/2.0/WS";
        via += " " + this.options.viaHost + ";branch=" + branch;
        if (this.options.forceRport) {
            via += ";rport";
        }
        this.setHeader("via", via);
        this.branch = branch;
    };

 类似资料: