Establishing a WebRTC connection without a server, one-way - webrtc

I would like to send messages between two peers using WebRTC without a signaling server. I'm using QR codes to send over the connection descriptions, and I found an example implementing exactly this:
https://github.com/TomasHubelbauer/webrtc-qr-signaling-channel
However, it requires scanning the QR code both ways. I'm wondering if it's possible to only have to scan a QR code from the phone, but still establish a connection?
Conceptually, I'm thinking like this:
ClientA shows QR code, essentially saying "here's how to connect to me."
ClientB scans it, and now knows how to find ClientA.
ClientB sends "here's how to connect to me" to clientA.
They now both know how to find and talk to eachother.
However, this doesn't seem possible when looking through the WebRTC documentation. If this isn't possible to do - then why?

I strongly doubt it is possible.
During the offer/answer exchange, each of the peers generates a self-signed (D)TLS certificate and includes its cryptgraphic hash ("fingerprint") in the SDP. Without the answer's SDP, the offering peer would be unable to authentify the answering one.
You might be able to achieve the same user experience, however, by implementing a signalling server on one of the peers. The QR code would contain the URL of the signalling server together with authentication data, and once connected the two peers could perform a traditional offer/answer SDP, and even trickle ICE candidates.

Related

Is it possible to retrieve the STUN server used once the RTCPeerConnection is connected

Not sure the title makes a lot of sense. To add some context, we are building a WebRTC infrastructure and to so do we have a few STUN servers up and and running.
We sometimes have users complaining of call taking too long to connect therefore we would like to get some analytics on the calls. Because we provide a list of STUN IPs (including some public STUN as backup), we would like to detect the STUN server that successfully initiated the call.
We have collected a bunch of information thanks to RTCPeerConnection.getStats but there is nothing related to the STUN itself. So for my questions:
is there any JS API that allow us to retrieve the STUN used?
is there any tool that I am not aware of that could do the job?
do the SDP contains any information related to STUN?
Hope all of this is clear, thanks for your kind replies
The statistics do contain a server url:
https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatestats-url
However, that is not implemented and since STUN servers are not involved in the actual call that information is unlikely to be useful.
For TURN servers you can get the active candidate pair and the IP of any relay involved from getStats. See https://webrtc.github.io/samples/src/content/peerconnection/constraints/ for a sample that shows how to determine the active candidate pair.

Send offers with WebRTC only

I want to create something similar like chat roulette:
There are two peers. Both peers send an SDP offer to the signaling server asking it to get connected with someone. The signaling server uses the offer of peer A to send it as an answer to peer B and vice versa.
Both peers could setLocalDescription() and setRemoteDescription() without using createAnswer().
Could they now go to the next step and exchange candidates? Or is it necessary that at least one is sending a real answer created with createAnswer()?
No. An offer is not an answer. An answer builds on an offer, it's a refinement, an iteration on it, a negotiation.
The offer-answer exchange is inherently asymmetric, so your peers will be in incompatible states if they've both sent out offers.
Instead, solve discovery (pairing) of A and B first, then do WebRTC from A to B.

How to validate WebRTC connection signals when peers can't trust each other?

I am building a WebRTC app where two users are selected at random and then connect to each other to chat. Both clients keep an open WebSocket connection and I am planning to use this to exchange their offers/answers to signal a connection. The case I am trying to account for is when there is a peer that intentionally sends bad configuration information, and also when the peer might spontaneously disconnect in the middle of the signaling exchange.
My solution to the first case is have the server keep state of the exchange, so when the connection is first established I would expect that user A provide an offer and user B have an answer. Is this appropriate? or should this be implemented exclusively client side?
My solution to the second problem feels to me like a hack. What I am trying to do is notify the user that a match has been made and then the user will set a timeout say 20 seconds, if a connection hasn't been made in that amount of time then it should move on...
Are these appropriate solutions? How do you reliably establish a WebRTC when either peer can't be trusted? Should the signaling server be concerned with the state of the exchange?
Sounds like you're more concerned about call set up errors rather than being able to trust the identity of the remote peer. They are two very different problems.
Assuming it is the call set up errors you are concerned about you shouldn't be trying to avoid them you should be trying to make sure your application can handle them. Network connection issues are something that will always crop up and need to be handled.
Setting a timer for the establishment of a WebRTC call to complete is a logical solution. Displaying a warning to the user that the time limit is approaching also seems like a good idea. SIP is a signalling protocol and it has a defined timeout for the completion of a transaction and if it doesn't complete within that time it will generate an error response. You could use the same approach.

Why does ICE needs both-ways signaling?

To establish WebRTC connections the ICE protocol is used with a signaling server which must send messages in both directions. I wonder why after the initiator sent its offer and candidates to the other participant, the participant needed to send back its answer and candidates using the signaling channel in the other direction. Cannot the participant open the connection to the initiator using candidates from both sides and send back its answer using the open connection?
I started reading ICE RFC and the only relevant part I found is in section 5.2 where the initiator must take the controlling role and nominates candidate pairs. But it does not explain why the other could not initiate connection.
To give some background, I am trying to build a webapp for which I want users to establish WebRTC connections without using a signaling server. I thought of having the app to generate a URL including the offer and candidates and providing this URL to other participants through other medium like instant messaging. The issue I got is that the participant need to send back its answer and candidates using the same medium, which is not practical. In the end I will go for a signalling server but I wonder the technical reason.
Yes, you can do that if caller is behind public IP or Full Cone NAT(in this case, router connection mapping needs not to be timed out).
You can able full fill above conditions rarely.
What's the problem with other NAT types?
For example , PRC(port restricted cone) NAT won't allow you to receive a packet from a IP:Port , if you didn't send any packet to that IP:Port before. So callee will never able to send you a packet.
So if callee sends her candidates list to you . you can send some dummy data(with low TTL) to her IP:Port to fool your PRC NAT (now it allow incoming packets from callee's IP:Port as it sends a packet to that IP:Port before).
To know more about different types of NAT:
https://en.wikipedia.org/wiki/Network_address_translation
http://think-like-a-computer.com/2011/09/16/types-of-nat/

How do you handle newcomers efficiently in WebRTC signaling?

Signaling is not addressed by WebRTC (even if we do have JSEP as a starting point), but from what I understand, it works that way :
client tells the server it's available at X
server holds that information and maps it to an identifier
other client comes and sends an identifier to get connection information from the first client
other client uses it to create it's one connection information and sends it to the server
server sends this to first client
both client can now talk
This is all nice and well, but what happends if a 3rd client arrives ?
You have to redo the whole things. Which suppose the first two clients are STILL connected to the server, waiting for a 3rd client to signal itself, and start the exchanging process again so they can get the 3rd client connection information.
So does it mean you are required to have to sort of permanent link to the server for each client (long polling, websocket, etc) ? If yes, is there a way to do that efficiently ?
Cause I don't see the point of having webRTC if I have to setup nodejs or tornado and make it scales to the number of my users. It doesn't sound very p2pish to me.
Please tell me I missed something.
What about a chat system? Do you really need to keep a permanent link to the server for each client? Of course, because otherwise you have no way of keeping track of a user's status. This "permanent" link can be done different ways: you mentioned WebSocket and long polling, but simple periodic XHR polling works too (although this will affect the UX, depending on the interval).
So view it like a chat system, except that the media stream is P2P for reduced latency. Once a P2P WebRTC connection is established, the server may die and, of course, the P2P connection will be kept between the two clients. What I mean is: both users may always block your server once the P2P connection is established and still be connected together in the wild Internets.
Understand me well: once the P2P connection is established, your server will not be doing any more WebRTC signalling. The connection is only needed to keep track of the statuses.
So it depends on your application. If you want to keep the statuses of users and make them visible to others, then you're in the same situation as a chat system: you need to keep a certain link, somehow, to make sure their statuses are synced. Otherwise, your server exists to connect them together and is not needed afterwards. An example of the latter situation is: a user goes to a webpage, the webpage provides him with a new room URL, the user shares this URL to another peer by another mean, the other peer joins the room, server connects them together (manages WebRTC signalling) and then forgets them. They are now connected until one of them breaks the link. Just like this reference app.
Instead of a central server keeping one connection per client, a mesh network could also be considered, albeit difficult to implement.