简体   繁体   中英

Firefox WebRTC signaling DOMException Failed to parse SDP

I am using WebRTC data channels for networking in an HTML5 game. Though WebRTC can be used P2P the topology for this project is centralized client-server. The server is a Node.js process that acts as a WebRTC peer. The clients are browsers that make a 1-1 connection with the server.

I am using the simple-peer library to handle WebRTC on both client and server. On the Node.js server I using the wrtc module as the peer connection instance. For the signaling handshake, I am using signalhub on both client and server.

The following is some fake code that demonstrates how the handshake is setup

//client
var peer = new SimplePeer({initiator: true});
peer.on('signal', (signalPayload) => signalHub.broadcast('client_signal', signalPayload));
signalHub.subscribe('server_signal', function(signalPayload){ peer.signal(signalPayload) });

//server
signalHub.subscribe('client_signal', (signalPayload) => {
    peer = new Simplepeer({});
    peer.signal(signalPayload);

    peer.on('signal', (signalPayload) => signalHub.broadcast('server_signal', signalPayload));
})

The current setup Consistently works as expected in Chrome...

Firefox fails to establish a connection. Simple-peer's error handler throws an error peer.on('error', (err) => {})

DOMException: "Failed to parse SDP: SDP Parse Error on line 6: No webrtc-datachannel token in m= media line, parse failed.

The specific signal payload that triggers this error looks like:

v=0
o=- 1575807233894551963 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS
m=application 0 UDP/DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=mid:0
a=sctpmap:5000 webrtc-datachannel 1024

This is the payload that the server sends to the client it is an 'answer' payload.

The following is a complete comparison of Chrome vs Firefox offer and answer payloads

  • Chrome Offer to Node.js
{
type: "offer",
sdp:
"v=0
o=- 5121147169778109884 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE data
a=msid-semantic: WMS
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=ice-ufrag:CmIA
a=ice-pwd:jHCWR4JJquU/r8KXtP0cQ9YN
a=ice-options:trickle
a=fingerprint:sha-256 0C:AC:DB:40:8E:AD:58:D8:09:3B:66:94:63:1B:00:D0:09:BD:F3:72:BF:29:66:53:94:9B:67:22:A9:27:A0:35
a=setup:actpass
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024
"
}
  • Firefox Offer to Node.js
{
 type: "offer",
sdp:
"v=0
o=mozilla...THIS_IS_SDPARTA-64.0.2 6450781105440687594 0 IN IP4 0.0.0.0
s=-
t=0 0
a=sendrecv
a=fingerprint:sha-256 54:5D:CF:E6:B6:B5:9B:60:C3:AB:F3:EC:5A:62:18:5E:13:F2:1A:23:86:03:BA:9D:D0:EA:67:7B:1C:5C:0A:2A\r\na=group:BUNDLE 0\r\na=ice-options:trickle
a=msid-semantic:WMS *
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=sendrecv
a=ice-pwd:c2217ee835bac1bdc0a765ebf1b5de2c
a=ice-ufrag:b0ceda3e
a=mid:0
a=setup:actpass
a=sctp-port:5000
a=max-message-size:1073741823"
}
  • Node.js Answer in response to Chrome Offer
"v=0
o=- 4547471447226747141 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE data
a=msid-semantic: WMS
m=application 62951 DTLS/SCTP 5000
c=IN IP4 192.168.1.159
b=AS:30
a=candidate:105744546 1 udp 2122260223 192.168.1.159 62951 typ host generation 0 network-id 1 network-cost 50
a=ice-ufrag:taPA
a=ice-pwd:Q/W3D4wgrRqMrfVT51yO3i5T
a=fingerprint:sha-256 2A:3C:A3:64:92:7D:32:F5:AB:5F:69:1F:C1:76:82:4C:97:A3:FE:CA:70:C5:E3:FA:FC:C0:11:FC:E3:DB:D5:1C
a=setup:active
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024"
  • Node.js answer in response to Firefox offer
"v=0
o=- 1575807233894551963 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS
m=application 0 UDP/DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=mid:0
a=sctpmap:5000 webrtc-datachannel 1024"

We can see that the Firefox answer payload looks odd. It is missing the fingerprint and other a= fields. Additionally, it does include the m= field which is odd that it would then throw the DOMException claiming it can't be parsed.

Non-browser end-point doesn't support v21 SCTP offer, giving malformed answer

It looks like the webrtc code on your server (the remote end-point in your setup) doesn't support the newer m=application format Firefox's offer uses, and produces an incorrect answer in that case, which Firefox chokes on, as Firefox expects an answer in the new format to its new-format offer:

  • Firefox Offer:
 m=application 9 UDP/DTLS/SCTP webrtc-datachannel a=sctp-port:5000 

Firefox (63+) here is using a newer version 21+ of the SCTP SDP draft , from 2017.

Chrome uses the older version 05 of the SCTP SDP draft , from 2013:

  • Chrome Offer:
 m=application 9 DTLS/SCTP 5000 a=sctpmap:5000 webrtc-datachannel 1024 

Unfortunately, this is a breaking change. The old parser expects to find a number ( 5000 ) in the m-line, where the new parser expects webrtc-datachannel . Read more about it here .

When Firefox is the answerer, it'll respond to both (old answer to old offer, new answer to new), great! But when Firefox is the offerer—which is the case here—it sends out a new offer and expects a new answer in return (Chrome, BTW, knows how to answer new offers, even though it does not yet emit them itself).

Workarounds

Ideally, you'll want to update your server to emit the right answer. In lieu of that, it should work if you make Firefox the answerer.

If that's not an option, it might work to munge the SDP between the two formats: You'd need to alter Firefox's offer to the old format before the server sees it, and its answer back to the new format before setting it with setRemoteDescription in Firefox.

Based on the comment below the question I think it is now clear that the wrtc Node module does not understand the new SCTP SDP format used by newer versions of Firefox. The wrtc module needs to be fixed then and updated.

I see you opened https://github.com/node-webrtc/node-webrtc/issues/483 already. I think that is way to get this fixed/working.

The only way to get such an answer from Chrome is if you use its proprietary rtp datachannel like this:

var pc = new RTCPeerConnection(null, {optional: [{RtpDataChannels: true}]});
pc.setRemoteDescription({type: 'offer', sdp: 'v=0\no=mozilla...THIS_IS_SDPARTA-64.0.2 6450781105440687594 0 IN IP4 0.0.0.0\ns=-\nt=0 0\na=sendrecv\na=fingerprint:sha-256 54:5D:CF:E6:B6:B5:9B:60:C3:AB:F3:EC:5A:62:18:5E:13:F2:1A:23:86:03:BA:9D:D0:EA:67:7B:1C:5C:0A:2A\r\na=group:BUNDLE 0\r\na=ice-options:trickle\na=msid-semantic:WMS *\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\nc=IN IP4 0.0.0.0\na=sendrecv\na=ice-pwd:c2217ee835bac1bdc0a765ebf1b5de2c\na=ice-ufrag:b0ceda3e\na=mid:0\na=setup:actpass\na=sctp-port:5000\na=max-message-size:1073741823\n'})

followed by createAnswer.

Don't do this. The rtp data channel is inferior to standard data channel in all aspects. Don't use it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM