EricssonResearch / openwebrtc

A cross-platform WebRTC client framework based on GStreamer
http://www.openwebrtc.org
BSD 2-Clause "Simplified" License
1.8k stars 537 forks source link

Generated ICE candidates are not accepted by Chrome #211

Open szimek opened 9 years ago

szimek commented 9 years ago

I'm trying out data channels in OpenWebRTC and Chrome complains about ICE candidates sent by Safari. Safari sends e.g. something like this:

"candidate:2 1 TCP 1019216383 fe80::4a0:1bff:fe63:21f7 9 typ host tcptype active"

and when Chrome tries to add such candidate:

connection.addIceCandidate(new RTCIceCandidate({
  sdpMLineIndex: 0,
  candidate: candidate
}));

I'm getting an error: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': The ICE candidate could not be added.

For comparison, Chrome (41.0.2272.74 beta (64-bit) on OS X) sends candidates looking like this:

candidate: candidate:316526476 1 udp 2122260223 192.168.0.20 52796 typ host generation 0 candidate: candidate:3838686808 1 udp 1686052607 31.179.7.215 52796 typ srflx raddr 192.168.0.20 rport 52796 generation 0 candidate:1549677436 1 tcp 1518280447 192.168.0.20 0 typ host tcptype active generation 0

superdump commented 9 years ago

Does Chrome support IPv6 candidates?

szimek commented 9 years ago

I have no idea, but it's possible that that's what causing this issue. Is it possible to somehow disable IPv6? I'll create a new issue for the Firefox error.

EDIT: It seems that the Firefox issue (missing ice-ufrag) has already been reported some time ago: #62

stefanalund commented 9 years ago

According to release notes for Chrome 42, IPv6 is now turned on by default. Which version are you testing with?

szimek commented 9 years ago

I was testing it using the latest beta version (41.0.2272.74 beta (64-bit)), but I've just tried it in the latest canary (43.0.2323.0 canary (64-bit)) and I'm getting the same error there.

quicklyfrozen commented 9 years ago

Note that the ICE-TCP RFC calls for a port number of 9 for an active TCP candidate (I guess 9 indicates not specified). Chrome, however, doesn't follow the RFC and uses port number 0 instead (you can see this from the number after the IP in these candidates). Perhaps when Chrome is accepting candidates it rejects candidates with port 9 (i.e. it's looking for 0 or >1024).

stefanalund commented 9 years ago

Have you filed a bug report on Chrome?

szimek commented 9 years ago

@stefanalund It looks like it's been already reported some time ago: https://code.google.com/p/webrtc/issues/detail?id=3849

stefhak commented 9 years ago

@szimek Do you still have issues with this? The candidates look to have identical structure between openwebrtc and Chrome (I've tested 42 and 43) now, and I see no issues when applying them.

szimek commented 9 years ago

@stefhak I'll try later today. I've just tried rebuilding openwebrtc for osx platform with ./build-all.sh -Cbr osx (previously I built it for osx and ios), but it complains about iPhone SDK missing:

...
Marking sources installed in gettext-0.18.2.1
Already on 'master'
[master 20dc6c1] tag file identifying the build script that installed the sources
 1 file changed, 1 insertion(+)
 create mode 100644 .sources_installed_tag_file.txt
Switched to branch 'arm-apple-darwin10'
Setting up toolchain for ios.
ERROR: No SDK detected, looking in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform

even though it worked before and I seem to have something there:

$ ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
iPhoneOS.sdk    iPhoneOS8.2.sdk

so I need some more time to figure out what's wrong.

Could you try if https://staging.sharedrop.io works for you if you try to send a file to Chrome or Firefox?

stefhak commented 9 years ago

@superdump can you comment on the build problems? (though it seems the "old" build process is used, and that one stopped working for me a while ago. I got Cerbero building to work though, just followed the instructions (I just build for osx FYI). I tried staging.sharedrop, but it seems to me that owr produces an invalid sdp if you only have a data channel (there is no DTLS fingerprint, and no ICE credentials as far as I can see). I'll ask around.

stefhak commented 9 years ago

There seems to be something strange going on in your application. The sdp that makes it (from owr) to Chrome in your app has no DTLS fingerprints and no ICE credentials so it can't be applied (look on the console of Chrome). I think that the problem with the ICE candidates is just a result of this (you can't add ICE candidates before a valid sdp has been set in the PeerConnection).

However, with demo.openwebrtc.io I get a datachannel-only chat to work, and the sdp produced by owr looks like: v=0 o=- 1427189005346015000 1 IN IP4 127.0.0.1 s=- t=0 0 m=application 49800 DTLS/SCTP 5000 c=IN IP4 150.132.143.12 a=sendrecv a=ice-ufrag:Jyuj a=ice-pwd:OEC/dVRJCTow6X8diJPD6B a=candidate:1 1 UDP 2013266431 fe80::24cd:4fff:fe7f:8024 57280 typ host a=candidate:2 1 TCP 1019216383 fe80::24cd:4fff:fe7f:8024 9 typ host tcptype active a=candidate:3 1 TCP 1015022079 fe80::24cd:4fff:fe7f:8024 60169 typ host tcptype passive a=candidate:4 1 UDP 2013266431 150.132.143.12 49800 typ host a=candidate:5 1 TCP 1019216383 150.132.143.12 9 typ host tcptype active a=candidate:6 1 TCP 1015022079 150.132.143.12 60170 typ host tcptype passive a=candidate:7 1 UDP 2013266431 fe80::22c9:d0ff:fed4:e175 49801 typ host a=candidate:8 1 TCP 1019216383 fe80::22c9:d0ff:fed4:e175 9 typ host tcptype active a=candidate:9 1 TCP 1015022079 fe80::22c9:d0ff:fed4:e175 60171 typ host tcptype passive a=fingerprint:sha-256 78:5F:C8:98:F1:F6:EA:D1:F3:A6:7A:64:86:BA:D6:FA:B5:A2:37:45:59:A0:5E:24:98:AD:E1:3D:EF:6C:92:AD a=setup:actpass a=sctpmap:5000 webrtc-datachannel 1024

I.e. contains DTLS fingerprints and ICE credentials as it should. Does your code do anything special with the sdp's?

szimek commented 9 years ago

@stefhak I'm using peer.js lib (modified to work with Firebase as a signaling server) - https://github.com/cowbell/sharedrop/blob/master/vendor/peer.js. I don't think it does anything strange with SDPs, but if demo.openwebrtc.io works fine, then it must be doing something differently :) Or my app is calling it in some strange way.

superdump commented 9 years ago

@szimek we're fully focused on moving to cerbero as our build system for the future. I suspect the build problem you encountered is because we have not updated the build scripts to add iOS 8.2 SDK support. That exists in cerbero and we're busy fixing all the issues there. We will soon also be making a release and publishing downloadable binaries to help people get going.

stefhak commented 9 years ago

@szimek I could not directly find any issue with peer.js (but I have to admit I'm not good at understanding and reviewing other's code). Could you try using demo.openwebrtc.io (chat only) and see if that works? And if so add console logs of the sdps to see if they look ok. If they do we could continue digging into what peer.js does.

Or if you could update your app to log sdp:s to the console I could have a look.

szimek commented 9 years ago

@stefhak Unfortunately, it seems I've got an outdated version of openwebrtc, because in Safari I can't check "chat" checkbox (video and audio work just fine) and I can't build the new version, because of the issue with iPhone SDK

stefhak commented 9 years ago

@szimek I think I found the issue. If in peer.js you replace line 1196 ("sdp: offer,") and line 1236 ("sdp: answer,") with "sdp: pc.localDescription," (same at both places) things might just work. If you change your JS app, I can test tomorrow (just let me know) given that you have build issues.

szimek commented 9 years ago

@stefhak Thanks! I've just pushed a new version to https://staging.sharedrop.io with the changes you suggested.

stefhak commented 9 years ago

@szimek It does not work, I probably made some error. I can't see the code (and peer.js at github does not seem to be updated). Details: works fine Chrome - Chrome, but with FF and Safari there are errors that seem related to the SDPs generated. Is there any way I could see the relevant snippets of the used peer.js?

szimek commented 9 years ago

@stefhak I've just pushed the fix to github as well: https://github.com/cowbell/sharedrop/compare/openwebrtc

stefhak commented 9 years ago

@szimek I missed that we need to stringify. "sdp: pc.localDescription," should be "sdp: JSON.stringify(pc.localDescription)," hope that helps!

szimek commented 9 years ago

@stefhak Thank you so much for looking into this. I've tried doing JSON.stringify(pc.localDescription), but then I probably need to call JSON.parse when receiving such message, because I'm getting errors like: Argument 1 of mozRTCSessionDescription.constructor can't be converted to a dictionary.

I can't really remember why, but when I was sending the original offer/answer, I needed this code: https://github.com/cowbell/sharedrop/blob/openwebrtc/vendor/peer.js#L1228-L1230 to make it work in Firefox.

I'll try to fix it, so that it works between Chrome and Firefox later today and let you know when it's ready.

stefhak commented 9 years ago

@szimek you're right - you need to parse on the receiving side! Let me know when it works between FF and Chrome, and I'll test with owr.

dborovik commented 9 years ago

Candidates should also have field "id":"audio" or "id":"video"...

szimek commented 9 years ago

@stefhak I've just pushed a new version to staging. I've tried it with Chrome <=> Firefox and it works.

dborovik commented 9 years ago

Any idea when it will be avail in bowser release?

stefhak commented 9 years ago

I'll test tomorrow!

25 Mar 2015 kl. 21:22 skrev Szymon Nowak notifications@github.com:

@stefhak I've just pushed a new version to staging. I've tried it with Chrome <=> Firefox and it works.

— Reply to this email directly or view it on GitHub.

stefhak commented 9 years ago

I've tested, and we're making some progress at least. owr - Chrome and owr - FF now negotiates correctly, and data channel is established. But, when sending from owr -> FF or Chrome, there is a syntax error reported in the console of the receiving side in both cases that happens when the user clicks "save" in the dialog. Message on FF: "SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data vendor-60dedd58351276b6d98ee1ad84eadb86.js:10:17639" and on Chrome: "Uncaught SyntaxError: Unexpected token o staging.sharedrop.it/:1" For the other direction nothing strange is shown in the console, but owr seem to crash with the following log: "/GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: random-key = false /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: key = 88b571493627a5c282f9e1e8b174e3bcc257598bd3886ad7306f7122230f /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: rtcp-auth = GST_SRTP_AUTH_HMAC_SHA1_80 /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: rtp-auth = GST_SRTP_AUTH_HMAC_SHA1_80 /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: rtcp-cipher = GST_SRTP_CIPHER_AES_128_ICM /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstDtlsSrtpEnc:dtls_srtp_rtp_encoder_1/GstSrtpEnc:srtp-encoder: rtp-cipher = GST_SRTP_CIPHER_AES_128_ICM

\ (:21762): CRITICAL **: Received message before datachannel was established. /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstAppSrc:datasrc_1.GstPad:src: caps = "application/data\,\ ordered\=(boolean)true\,\ ppid\=(uint)51\,\ partially-reliability\=(string)none\,\ reliability-parameter\=(uint)0" /GstPipeline:transport-agent-4/GstBin:transport_bin_4/GstBin:send-output-bin-1/GstSctpEnc:sctpenc_4.GstSctpEncPad:sink_1: caps = "application/data\,\ ordered\=(boolean)true\,\ ppid\=(uint)51\,\ partially-reliability\=(string)none\,\ reliability-parameter\=(uint)0"" @superdump can anyone look into what happens?

szimek commented 9 years ago

@stefhak I've just enabled JS source maps on staging, so at least Chrome should report the syntax error with a link to a non-minified file. It's also possible to run ShareDrop locally, but you need to set up a free FIrebase account for that to work.

stefhak commented 9 years ago

@szimek could you give some instructions on how to run locally (I can create a firebase account)? I won't promise anything, but I'll try to look into it.

szimek commented 9 years ago

@stefhak Sure - https://github.com/cowbell/sharedrop#how-to-set-it-up-for-local-development If something doesn't work, let me know.

stefhak commented 9 years ago

@szimek I'll hopefully have a go at this soon. @superdump assigned to you for the owr parts as agreed.

stefhak commented 9 years ago

@szimek setting up my own local copy seems to require some work. I'd like to do some limited tests as start instead if that's ok with you. It seems everything goes well until the user at the receiving end clicks "Save" in the dialog. I'd like to emulate what you got, so could you describe a bit? I assume you use "file" and FileReader to get hold of the file to transmit. How do you read the file ("readFileAsBinaryString"?) Is what you send over the data channel a Blob/ArrayBuffer or something else? How do you transmit the file name? As a separate data transmission of a string on the data channel? What happens when the user clicks "Save"?

szimek commented 9 years ago

@stefhak

  1. I use Blob#slice with FileReader#readAsArrayBuffer. This is the function responsible for reading and sending a single block of data.
  2. If I remember correctly, I send ArrayBuffer. See this line which calls connection.send that is defined in peer.js library here. There's a lame type check which may be causing some problems. The same check is present again on the receiving side.
  3. Yup. The code for sending file meta data is here and for receiving is here.
  4. To store incoming blocks of data on the receiving side I'm using FileSystem API , which is available only in Chrome (and even there probably not for very long) with IndexedDB based polyfill idb.filesystem.js for other browsers. When user clicks "Save" this function is called. It creates an <a> element, gets the URL to the image (either from FileSystem API or using URL.createObjectURL), sets it as href attribute and simulates a click.

Most of this code was written over a year ago, so even though it works in Chrome and Firefox, it's possible that it doesn't follow new versions of WebRTC standard accurately.

Again, thanks for looking into this!

EDIT: I've just noticed that when sending file meta data, I'm calling JSON.stringify on this data twice - once in WebRTC#sendFileInfo and then in DataConnection#send. I have no idea why it works :/

EDIT2: I've just pushed a new branch that removes this double JSON.stringify/parse calls. I've tested it between Chrome and Firefox and it seems to still work.

stefhak commented 9 years ago

@szimek You can thank me if I ever solve anything - so far I've only consumed your time :) Regarding EDIT2: is this also pushed to the site (https://staging.sharedrop.io)? I assume it is.

szimek commented 9 years ago

@stefhak Now it is :)

stefhak commented 9 years ago

I've determined that owr data channel can't handle ArrayBuffers, and filed an Issue on that (https://github.com/EricssonResearch/openwebrtc/issues/287). This may not be the only issue, but we need to fix that before doing any meaningful furhter testing.

If the file is read as "DataURL" or "BinaryString" it works, but not if read as ArrayBuffer.