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.
Related
I'am develop group call like google meet using WebRTC and SFU method for routing.
my project work well, until i open chrome://webrtc-internals to see webrtc connection status. and i compare with google meet.
Google meet
only 1 peer connection is active.
my project.
1 peer connection active for broadcast.
n-1 peer connection active as consumer.
so if total users in a room is 5. then on each client side has 5
peer connections are active too (1 as broadcaster, 4 as
consumers).
so my question is, how i can using only 1 peer connection as consumer? or using 1 peer connection as broadcast and also as consumer? maybe my method wrong? or misunderstood the implementation of SFU.
any suggestions or solutions?
I am still discovering/learning the stack of webrtc and related architectures, so take what I am saying with a grain of salt.
With a SFU architecture you can have multiple strategies to distribute the streams between your clients. In all case, you save bandwidth for the local user by only sending his streams once to the SFU.
As you state, for n users you can open 1 RTCPeerConnection with the SFU for the local user and n-1 RTCPeerConnection for remote users.
You can open only one RTCPeerConnection with the SFU for any number of users in the "room". To achieve this, when a new user enters the SFU session, his streams need to be added to the tracks of the PeerConnection present at the SFU. It will trigger some renegotiation through signaling, and your users will know a new track (stream) has been added. The client (javascript code for example) needs to identify the new tracks to a specific user, for that you can add the information of this user in the signaling payload. From the point of view of a given user, these new tracks (audio+video) will correspond to a new user.
The first approach is simpler but takes more ressources, more ice candidate to gather, stun request, connections to the SFU, etc..
The second one is more efficient but harder to implements. Both on the client and the server.
A link to bloggeek.me, which provides excellent ressources for webrtc, and talks about these two approaches, far better than me.
The post states that Jitsi server, use only one peer connection with the SFU, per user.
Other strategies exist, in livekit server, a SFU implementation in Golang, they use 2 PeerConnection per user. One for publishing the streams of the local user and the second to receive streams from all other users. Here a link to the client protocol of Livekit server
For approach 2 and 3, how SFU servers wire up all these streams correctly between each PeerConnection with a local user, I really don't know. It seems really specific to the project.
You have to check the SFU server API you are using, and see what is possible to do with it. But what you are looking for is definitely possible, given the "right" project for your use case.
For the client side it depends on project your are using too.
If you are in the early stage of your project, you can maybe check livekit server. It is an open source project, Apache 2.0 license, develop in golang, and provides a lot of interesting features out of the box. Auto scaling SFU instances through redis, kubernetes setup, client libraries in JavaScript, Flutter, a server sdk to interact with SFU instances in various langage, etc.. The ecosystem seems really nice and the documentation is good too.
Hope it helps a bit
I would like to create an audio (mic) and video (camera) chat room with 12 people using webRTC. I understand signalling and the need for external services like ICE & STUN to help peers connect with each other.
But I don't want to use a full mesh architecture where everyone connects to everyone else because it is less efficient. I don't want to use expensive TURN relay services. I want the swarm to propagate the streams automatically so that if a direct connection isn't possible, the network routes the stream packets via peers automatically using encapsulation.
I don't want to use star architecture because I don't want a bottleneck peer.
I would like a peer to connect to maybe 2 or 3 other peers (max) and broadcast their media across the network without worrying about the relaying between peers. The routing would obviously need to be controlled by some service but I can't see that it's possible to do the stream encapsulation with RTCPeerConnection. Since WebRTC only allows for a RTCPeerConnection object (1 peer to 1 peer) and a peer would need to distinguish where the incoming stream is coming from and whether it needs to be relayed to another peer.
Is there a technology that extends WebRTC to allow for this more bandwidth efficient architecture?
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'm going to implement Java VoiP server to work with WebRtc. Implementation of browser p2p connection is really straightforward. Server to client connection is slightly more tricky.
After a quick look at RFC I wrote down what should be done to make Java server as browser. Kindly help me to complete list below.
Implement STUN server. Server should be abke to respond binding
request and keep-alive pings.
Implement DTLS protocol along with DTLS handshake. After the DTLS
handshake shared secret will be used as keying material within SRTP
and SRTCP.
Support multiplexing of SRTP and SRTCP stream. SRTP and SRTCP use
same port to adress NAT issue.
Not sure whether should I implement SRTCP. I believe connection will
not be broken, if server does not send SRTCP reports to client.
Decode SRTP stream to RTP.
Questions:
Is there anything else which should be done on server-side ?
How webRtc handles SRTCP reports ? Does it adjust sample rate/bit
rate depends on SRTCP report?
WebRtc claims that following issues will be addressed:
packet loss concealment
echo cancellation
bandwidth adaptivity
dynamic jitter buffering
automatic gain control
noise reduction and suppression
Is is webRtc internals or codec(Opus) internals? Do I need to do anything on server side to handle this issues, for example variable bitrate etc ?
The first step would be to implement Interactive Connectivity Establishement (RFC 5245). Whether you make use of a STUN/TURN server or not is irrelevant, your code needs to issue connectivity checks (which use STUN messages) to the browser and respond to the brower's connectivity checks. ICE is a fairly complex state machine, but it's doable.
You don't have to reinvent the wheel. STUN / TURN servers are external components. Use as they are. WebRTC source code is available which you can use in your application code and call the related methods.
Pls. refer to similar post - Server as WebRTC data channel peer
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.