My very hacky webRTC datachannel implementation stopped working a while back, and I could not figure out why.
The way it behaved was hard to understand. Signaling worked as expected, and I received a STUN on the correct port and responded to that. Both Firefox and Chrome reported the response as fine, and kept sending new STUN heartbeats at the normal rate, but no DTLS handshake was initiated.
Initially i thought something was really broken with my STUN/DTLS multiplexing, but I soon figured out that it behaved as expected.
This meant I was probably sending some wrong parameter during signaling, but what?
This is the SDP of my answer to the given offer from the browser.
v=0 o=- 1234567 2 IN IP4 192.168.1.158 s=- t=0 0 a=group:BUNDLE data a=msid-semantic: WMS m=application 51410 DTLS/SCTP 5000 c=IN IP4 192.168.1.158 a=candidate:1 1 udp 2113937151 192.168.1.158 51410 typ host a=ice-ufrag:4a64ca2b a=ice-pwd:a26b6a15a8b4d35db21692d37906840a a=ice-options:trickle a=fingerprint:sha-256 C9:E2:48:09:47:C8:CC:B3:51:A8:A1:C5:AA:63:51:26:50:1D:FF:76:AE:EF:CB:31:0C:E7:41:21:5A:11:FA:D5 a=setup:actpass a=mid:data a=sctpmap:5000 webrtc-datachannel 1024
SDPs are confusing to me, and figuring out what stuff really means in WebRTC context is a lesson in reading RFCs with a microscope, while always wondering if this is the correct RFC for this concrete problem.
Suddenly it dawned on me that it seemed like both sides were waiting for the other side to initiate the DTLS handshake.
It turned out this was the problem:
Since i responded with actpass in my answer SDP, the browser could not know if it wanted to initiate DTLS or not, and I guess it defaults to passive now. actpass is an illegal response value according to this RFC, and defaulting to passive is probably more correct then active. Setting a=setup:passive fixed the issue, since that tells the browser to be the initiating party.