paullouisageneau / datachannel-wasm

C++ WebRTC Data Channels and WebSockets for WebAssembly in browsers
MIT License
148 stars 25 forks source link

Failed to execute 'createDataChannel' on 'RTCPeerConnection': RTCDataChannel cannot have both max retransmits and max lifetime #35

Closed ghost closed 2 years ago

ghost commented 2 years ago

I basically can't do pc->createDataChannel("label") on either chrome or firefox. I've looked into the javascript and it seems like this exception gets always thrown if both maxRetransmits and maxPacketLifeTime are in the datachannelInit, even if they're both null.

After that I just get a ton of "Module.dynCall is not a function" errors. is there some emscripten flag I am supposed to toggle? I can't find any information about this "dynCall" thing...

ghost commented 2 years ago

This is with chrome 102, firefox 101, emcc 3.1.14, and datachannel-wasm 0.2.0

ghost commented 2 years ago

looks like this only happens in datachannel-wasm 0.2.0, but I will test it properly tomorrow

ghost commented 2 years ago

https://github.com/paullouisageneau/datachannel-wasm/pull/33/commits/51ba4a01520d5fdb3c53e592afe1e1442455e46e

ghost commented 2 years ago

According to this source: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel

SyntaxError DOMException

Thrown if values were specified for both the maxPacketLifeTime and maxRetransmits options. You may specify a non-null value for only one of these.

But it's throwing this error when both values are null... is no one else encountering this behavior with their browser's implementation? I find it pretty weird

paullouisageneau commented 2 years ago

I basically can't do pc->createDataChannel("label") on either chrome or firefox. I've looked into the javascript and it seems like this exception gets always thrown if both maxRetransmits and maxPacketLifeTime are in the datachannelInit, even if they're both null.

This is with chrome 102, firefox 101, emcc 3.1.14, and datachannel-wasm 0.2.0

I can't reproduce, on my side the Data Channel is created as expected.

Since the function prototype changed in https://github.com/paullouisageneau/datachannel-wasm/pull/33, could it be possible your build mixes up different versions of JS and C++ code, which would result in garbage arguments being passed as maxPacketLifeTime and maxRetransmits? Could you please try rebuilding from scratch (i.e. after removing the entire build directory)?

After that I just get a ton of "Module.dynCall is not a function" errors. is there some emscripten flag I am supposed to toggle? I can't find any information about this "dynCall" thing...

Module.dynCall allows to call a C function pointer from JavaScript. The emscripten option EXPORTED_RUNTIME_METHODS=['dynCall'] enabled by default in CMakeLists.txt should expose it.

ghost commented 2 years ago

I do also get this warning when I'm compiling datachannel-wasm what indicates this may not be working: em++: warning: linker setting ignored during compilation: 'EXPORTED_RUNTIME_METHODS' [-Wunused-command-line-argument]

paullouisageneau commented 2 years ago

The warning means that it is a linker option so it has an effect only during linking and is ignored during compilation, while it is specified for both. I should move it to linking options only, but the option should work anyway.

ghost commented 2 years ago

Just running the following javascript gives me the error in both chrome 102 and firefox 101:

pc = new RTCPeerConnection();
pc.createDataChannel("test",{
  ordered: false,
  maxPacketLifeTime: null,
  maxRetransmits: null,
});

Firefox 101: Uncaught TypeError: Both maxPacketLifeTime and maxRetransmits cannot be provided Chromium 102: Uncaught TypeError: Failed to execute 'createDataChannel' on 'RTCPeerConnection': RTCDataChannel cannot have both max retransmits and max lifetime

Removing either maxPacketLifeTime or maxRetransmits works fine:

pc = new RTCPeerConnection();
pc.createDataChannel("test",{
  ordered: false,
  maxPacketLifeTime: null,
});

Like I said earlier, I find this to be pretty strange as https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel claims this should be a syntaxError and shouldn't even occur if one of the options is null. So perhaps it is a problem with (both!) of my browser's implementations?

It works for you right? May I ask what browser and version you are using?

ghost commented 2 years ago

Looking at this mirror of the firefox source code: https://github.com/bolucat/Firefox/blob/af1f896bdb514f1414b13c6edf224a4cc6d7e485/dom/media/PeerConnection.jsm#L1685

It appears that it checks if the parameters maxPacketLifeTime and maxRetransmits are undefined, rather than null.

Looking at chromium's source code: https://chromium.googlesource.com/chromium/src/third_party/+/1b6aa2b5c4d9ef48255799dc6f4b4d16426c0207/blink/renderer/modules/peerconnection/rtc_peer_connection.cc#2665

It appears that it checks if they're greater than or equal to 0. I guess null is defined or cast to 0 within that context? Here is the definition of their RTCDataChannelInit struct:

https://chromium.googlesource.com/chromium/src/third_party/+/1b6aa2b5c4d9ef48255799dc6f4b4d16426c0207/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl

Their use of unsigned short seems to imply this. What do you think?

paullouisageneau commented 2 years ago

Oh, I should have tested that first. My bad, it indeed doesn't work.

Thank you for the browser source code investigation, it looks like both browsers do not behave according to specifications as the W3C interface specification says the same thing as MDN: https://w3c.github.io/webrtc-pc/#dom-peerconnection-createdatachannel

Actually I can reproduce now, it appears I was testing with a submodule set on an incorrect version, sorry. I'm pushing a fix.