WebRTC peer to peer setup works perfectly with both audio and video locally and remotely. The ICE connection state transitions as expected and finally lands in the "connected" state.
Now if I don't add any audio or video streams to the peer, the session descriptions and ice candidates are exchanged and applied successfully, but the ice connection state never changes to anything. Not to checking, connected, disconnect, failed, or closed. No exceptions are thrown either.
If I add just an audio stream, again everything is exchanged and applied successfully, and the ice connection state this time transitions to "checking" but nothing after that.
Any insight as to why this is?
If you look at the SDP generated you'll see it has no m= sections. Those are necessary in order to have a=candidate lines and without those you can not establish a connection (and it would be surprising if you got candidates). There is some discussion around this issue here.
For the second question the answer is "it depends". This discusses how to use chrome's webrtc-internal for analysing the issue.
Related
From
Link: www.w3.org/TR/webrtc/#dom-rtcbundlepolicy
Content: 4.2.5 RTCBundlePolicy Enum
"If the remote endpoint is bundle-aware, all media tracks and data channels are bundled onto the same transport."
When is an endpoint bundle-aware and when not? And what does bundle-aware means?
To establish a p2p connection, WebRTC will allocate and do STUN network checks on up to 3 ports (multiplied by ways they can be reached) on either end, and as they're discovered (which takes time), ask JS to trickle-exchange info on each of these "ICE candidates" across a signaling channel, once for video, once for audio, and once for data (if you have it).
WebRTC does this mostly to support connecting to non-browser legacy devices, because all modern browsers support BUNDLE, which is when all but one candidate end up being thrown away, and all media gets bundled over that single port.
WebRTC even has a "max-compat" mode that goes even further, allocating a port for each piece of media, just in case the other endpoint is really old.
WebRTC doesn't know the other endpoint is a browser until it receives an "answer" from it, but if you know, you can specify "max-bundle" and save a couple of milliseconds.
My understanding:
In WebRTC, SDP is used to relay ice candidates to remote peers after they are gathered by the local peer. The connectivity checks thereafter are performed using STUN binding requests. I can log the SDP received/sent using Javascript but these are merely ICE candidates.
Question:
How do I log or view the ICE connectivity check (STUN, RFC 5389) messages in Chrome? I understand that I can install Wireshark or some such tool to log all network traffic but I think there must be a better direct way to do this.
One way is to visit chrome://webrtc-internals and click "Download the PeerConnection updates and stats data" Button.
There isn't a way you can get the STUN packets directly, but you can somewhat monitor what is going on via the getStats API!
RTCIceCandidatePairStats you have requestsReceived and requestsSent so you can figure out some stuff from that.
I don't think we will ever get an API to actually get the packets though.
I have an app which creates two instances of RTCPeerConnection (within the same JS context) which attempt to connect to each other. While I'm developing, I reload the page often, maybe several times per minute. About 10% of the time, WebRTC will fail to progress to the 'iceConnectionState == "connected"' stage. This failure occurs even when I pass no STUN/TURN servers to createPeer().
I primarily use Chrome (OSX, currently version 81.0.4044.138). I have never been able to reproduce this on Firefox.
I have captured nearly-identical dumps of the success and failure cases using chrome://webrtc-internals.
I have spent many hours on this and haven't found any clue as to why this might be failing. Is it just some kind of temporary local network outage? Is there anything I can do within the code to have a 100% local connection rate?
I have seen similar flakiness because of mDNS candidates. Try disabling #enable-webrtc-hide-local-ips-with-mdns in chrome://flags and see if that helps!
After that I would grab a tcpdump and confirm you see ICE traffic flowing each way.
I have started to look into WebRTC a bit and I am using it to build a simple peer to peer chat application using the data channel. I have the following questions:
Do I need to establish a RTCPeerConnection to each peer I want to talk to? So if there are three peers they each need 2 RTCPeerConnections (unless I use one of the peers as a sort of ad-hoc server).
If peer A sends out a candidate and sdp when creating a offer to peer B. Can peer B connect to peer A using that info and send its answer (with candidate and its sdp) over the RTCPeerConnection, i.e. using the RTCPeerConnection (before it's been completely established) as a signaling channel? I would assume that when the offer is created by peer A it starts to listen for connections on some port.
My understanding of WebRTC is a bit limited so if I've missunderstood some concept of WebRTC in my questions above please point them out!
Yes, as a direct P2P protocol everybody must be directly connected to everybody else if they want to communicate; unless you create some kind of mesh network in which one peer forwards messages to other peers.
No, the SDP offer and answer and ICE candidates all need to be exchanged through a signalling server; the connection cannot be established until both peers have actually agreed on a specific session configuration and ICE route to use, so you cannot send the SDP answer over a connection which isn't complete yet.
Especially for a simple text-only chat, going through a server is often easier than using P2P; the processing and bandwidth requirements are so minimal that the complications of P2P connections are probably not worth it. And you need a signalling server anyway. P2P only becomes really interesting once you start sending large files or audio/video streams.
In principle it is possible to establish a WebRTC connection without a signalling server, but that requires an out of band exchange of session tokens between the peers. I.e. the user would have to copy a token from the application, somehow send it to another user and the other user would have to paste it.
Additionally those tokens cannot be reused, so this procedure would have to be repeated every time peers want to establish a connection.
So while theoretically possible webrtc is not distributed in practical terms.
There is some noise about specifying support for incoming connections and reusable peer contacts, but the progress on that is unclear.
I'm converting an application over from GameKit to Multipeer Connectivity and can't seem to find a method that would allow the browser device to disconnect another peer from the session . With GKSession, we could disconnect a single peer from the session using disconnectPeerFromAllPeers:, but I can't find anything like that in MPC. Of course, MPC does have the disconnect: method, but that takes the local peer out of the session..not what I want.
The closest I've found is:cancelConnectPeer: but that seems more focused on canceling a connecting attempt...not post connection.
Anyone know how to do this of if it is even possible with MPC?
Thanks!
A peer can leave a session by calling [MCSession disconnect].
If you want the browser to disconnect another peer, you could make the browser send a message to that peer, and make the peer disconnect from the session upon receiving that message.
I am working on MPC too, but find annoying by API too. Therefore I move the logics, such as disconnecting a specific peer, up to app logic level, from physical connection level. E.g. Session/connection is always on, and just do soft-disconnection by not sending any message to specific peer.
Bluetooth does not perform stably as we all experienced in GKSession. With MPC, we most time used Wifi, therefore connection stability and cost does not matter so much.