1.问题回放

  使用如下代码获取局域网IP报错

  (代码来源:https://github.com/diafygi/webrtc-ips 日期:2019-02-16)

 1 //get the IP addresses associated with an account
 2 function getIPs(callback){
 3     var ip_dups = {};
 4
 5     //compatibility for firefox and chrome
 6     var RTCPeerConnection = window.RTCPeerConnection
 7         || window.mozRTCPeerConnection
 8         || window.webkitRTCPeerConnection;
 9     var useWebKit = !!window.webkitRTCPeerConnection;
10
11     //bypass naive webrtc blocking using an iframe
12     if(!RTCPeerConnection){
13         //NOTE: you need to have an iframe in the page right above the script tag
14         //
15         //<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
16         //<script>...getIPs called in here...
17         //
18         var win = iframe.contentWindow;
19         RTCPeerConnection = win.RTCPeerConnection
20             || win.mozRTCPeerConnection
21             || win.webkitRTCPeerConnection;
22         useWebKit = !!win.webkitRTCPeerConnection;
23     }
24
25     //minimal requirements for data connection
26     var mediaConstraints = {
27         optional: [{RtpDataChannels: true}]
28     };
29
30     var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
31
32     //construct a new RTCPeerConnection
33     var pc = new RTCPeerConnection(servers, mediaConstraints);
34
35     function handleCandidate(candidate){
36         //match just the IP address
37         var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
38         var ip_addr = ip_regex.exec(candidate)[1];
39
40         //remove duplicates
41         if(ip_dups[ip_addr] === undefined)
42             callback(ip_addr);
43
44         ip_dups[ip_addr] = true;
45     }
46
47     //listen for candidate events
48     pc.onicecandidate = function(ice){
49
50         //skip non-candidate events
51         if(ice.candidate)
52             handleCandidate(ice.candidate.candidate);
53     };
54
55     //create a bogus data channel
56     pc.createDataChannel("");
57
58     //create an offer sdp
59     pc.createOffer(function(result){
60
61         //trigger the stun server request
62         pc.setLocalDescription(result, function(){}, function(){});
63
64     }, function(){});
65
66     //wait for a while to let everything done
67     setTimeout(function(){
68         //read candidate info from local description
69         var lines = pc.localDescription.sdp.split('\n');
70
71         lines.forEach(function(line){
72             if(line.indexOf('a=candidate:') === 0)
73                 handleCandidate(line);
74         });
75     }, 1000);
76 }
77
78 //Test: Print the IP addresses into the console
79 getIPs(function(ip){console.log(ip);});

2.分析

  代码在此处报错:pc.setLocalDescription(result, function(){}, function(){})

  即此API报错:RTCPeerConnection.setLocalDescription()

  源代码在Firefox和Chrome71正常执行,Chrome升级到72稳定版后代码报错,浏览器debug调试发现Chrome71和Chrome72的offer(代码中是result)的SDP格式/内容发生了变化,因此可以判断是新版本Chrome的WebRTC相关API发生了变化,于是在https://www.chromestatus.com/features找到了解释:

 1.问题回放-LMLPHP

  文中提供了此链接:https://docs.google.com/document/d/1-ZfikoUtoJa9k-GZG1daN0BU3IjIanQ_JSscHxQesvU/edit,划重点:

    WebRTC规范仍然在演进,Chrome上目前SDP格式有两种:规范定义的SDP格式(Unified Plan)和Chrome自己定义的SDP格式(Plan B),火狐支持前者,如果不指定SDP格式Chrome72默认使用Unified Plan,这和Chrome71的行为不同,那么如何指定SDP格式呢?

3.解决

  将源代码此行

    var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};

  更改为   

    var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}], sdpSemantics:'plan-b'};

4.其他

  如果Public IP无法解析,请更换stun服务器:

    var servers = {iceServers: [{urls: "stun:stun.l.google.com:19302"}], sdpSemantics:'plan-b'}; 
04-18 03:15