WebRTC connection does not establish after successful signaling - javascript

I am using the simple-peer js library to create peer to peer connections in the browser. I have setup proper signaling through socket.io and most of the time everything works fine; hand-shake is successful and p2p connection is established.
But sometimes despite proper hand-shake, p2p connection does not initiate, no error is thrown. This happens consistently on a VPN but sometimes it can happen without VPN. I am using the default google STUN server for now and there is no TURN server provided.
Any enlightenment as to what could be the cause will be appreciated.

Problem is that sometimes one of the peers "sits" behind the doubled NAT or symmetric NAT, VPN is a good example. You use only STUN server, STUN could not solve internal<->external IP of the client behind the doubled NAT. You need to set up TURN server for that. You can test with free TURN, however, this is only to test the problem, not as a permanent solution. For permanent solution better to use your own TURN server.

Related

Can Chrome or Firefox open a network port and serve connections using javascript?

For a mostly offline browser game I'm researching the possibility to run a WebRTC signalling server from a browser.
I can imagine that security-wise it's a big no-no to open a port and serve connections from a browser (or service worker), but I cannot* find any information on this.
Q. Can Chrome, Firefox (or perhaps any other major browser) open a network port and serve connections using javascript? Or is this fundamentally disallowed by browser design?
*) For sake of completeness, I did find one option (maybe), but it's overly complex, and therefore isn't very appealing. There is a javascript package called filerjs, which allows for a posix-like filesytem in the browser, I think using indexedb, that would allow for a nodejs installation in the browser. I did not further investigate it, so no idea if it actually works, and if a connection could be served this way.
I don't think that you can run a signaling server in the browser. But you say "mostly offline", does that mean that the peers are connected to the internet, but playing from the same LAN? Or are they completely offline? Here are a few ideas:
Signaling server on the web
Even if the signaling server is running on the web, chances are that WebRTC will connect directly through the LAN (to be tested, and it may depend on how the browser selects the ICE candidates).
Manual signaling
Now, the signaling server is only there to exchange SDP messages. So you could theoretically copy-paste the offer and answer (or copy it manually, or scan it with a QR code). It may not be practical, but for instance you could try hardcoding the SDP offer/answer. The two players would need to exchange information somehow, though:
The ICE candidates (those are IPs) that you would need to create the SDP message
The SDP type (one has to be the offer, the other has to be the answer)
I never tried it, but maybe your UI could tell the player "Please share the following IPs to the other player, and enter their IPs below. Also select if you are the offerer or the answerer". But you see that it seems a bit convoluted...
Signaling server in the LAN
If the peers are completely offline and the manual signaling is too convoluted, my next idea would be to run the signaling server in the LAN, and have the peers connect to it. You could even make it such that your game first tries to contact your signaling server on the Internet, and if it fails (because it is offline), it could fallback and try to contact the one in the LAN (maybe it would need to ask the user for the IP of the signaling server, then).

WebRTC fails to connect P2P even though peers can send UDP packets to each other

I was under the impression that WebRTC goes to great lengths to achieve P2P connectivity despite NATs. [1][2] That's why I was surprised to learn that WebRTC fails to connect peers in some situations where a P2P connection is easy to achieve. I would like to understand why this happens, and if there is anything I can do to improve the situation.
Why do I claim that P2P is easy to achieve in some of these situations? I claim this because I have set up an experiment with 2 devices on different networks:
Device F is connected to the internet behind Full-cone NAT
Device S is connected to the internet behind Symmetric NAT
I can easily achieve a P2P connection between these devices in the following manner:
Device F binds a connection to a random (unpredictable) port and sends a UDP packet through that port to anywhere on the internet. Because F is behind Full-cone NAT, this packet has "hole-punched" the port open, allowing any external addresses to now send packets through that port. In my case the port that I opened locally appears to be the same as the external port. (If the external port was different from the local port, we could use something like STUN to figure out the external port.)
Device S binds a connection to a random (unpredictable) port and sends a UDP packet through that port to the external IP and port of Device F. This packet can be delivered, because the port was hole-punched open in step 1. After this packet, Device S has hole-punched through its own port, allowing packets from Device F to be sent back through it. Device F will know where to send the packets, because the packet that S sent contains the external IP and port. Because Device S has Symmetric NAT, the hole-punching didn't open the port for all traffic, only for traffic from Device F (the external IP and port of Device F).
I used Python to verify that I am able to open a P2P connection between these devices and send messages in both directions, as described above. I don't understand why WebRTC is unable to achieve a P2P connection like this.
Why do I claim that WebRTC fails to connect in some of these situations where a connection should be easy? I claim this because I tried to achieve a WebRTC P2P connection with 3 different code examples. All of the examples worked when devices were in the same local network, but didn't work when the devices were in different networks (the setup described above). None of the libraries I tried provided any useful debugging information to figure out what went wrong, and chrome://webrtc-internals didn't provide any useful information either. I also tried in Firefox to verify that this issue is not implementation-specific.
To be specific, I tried the following code examples:
simple-peer, a WebRTC library. I tried the first example code in the README.
PeerJS, another WebRTC library. I tried the demo page they have set up.
A code snippet from a Stackoverflow answer. [3]
In all 3 experiments I also tried to switch which device initiates the connection and which device receives it.
Since this issue isn't specific to WebRTC implementation, and it isn't specific to any particular WebRTC JavaScript library, I'm beginning to suspect that the spec for WebRTC is broken in some fundamental way, preventing WebRTC from achieving P2P connections in situations where they would be easy to achieve. Am I missing something here?
[1] https://webrtc.org/getting-started/turn-server states: "For most WebRTC applications to function a server is required for relaying the traffic between peers, since a direct socket is often not possible between the clients". This gives the impression that WebRTC should be able to achieve a P2P connection in a scenario where it is easy to achieve.
[2] https://webrtcforthecurious.com/docs/03-connecting/ states: "WebRTC will gather all the information it can and will go to great lengths to achieve bi-directional communication between two WebRTC Agents." This also gives the impression that WebRTC should be able to achieve a P2P connection in a scenario where it is easy to achieve.
[3] WebRTC datachannel with manual signaling, example please?

How can I use webrtc without any server of my own?

Is there a way to use webrtc without any server or cost and without downloading anything? I'm trying to make a peer to peer network without a server of any kind (I can't set up my own). Every tutorial that I've found needs some kind of server, or downloading node.js, or using some service that you pay for with a subscription. Is there a way to do this?
WebRTC is actually a Peer to Peer RTC Protocol which happens between browser.
But you got it in wrong way. For establishing the direct link between two systems WebRTC requires,
The topology between itself, and the peer it wants to communicate with
Establish connectivity on the best path through a given topology
Have a fallback mechanism if all else fails.
WebRTC standards require the use of  three IEFT NAT traversal standards to address these issues:
Interactive Connectivity Establishment (ICE) –  RFC 5245
Session Traversal Utilities for NAT (STUN) – RFC 5389
Traversal Using Relay NAT (TURN) – RFC 5766
So, the final answer is it's not possible with WebRTC.

Webrtc Getting blocked by Firewall (iceConnection:Failed)

I have simple web app,
Client1 logs in and socket connections is made to signal.php
Client2 logs in and socket connections is made to signal.php again
Client2 sends offer to client1 via signal.php
client1 sends answe to client2
ice candidiates are exchanged
So this works fine when the remote system's windows firewall is Off but when the firewall is On the ice connection fails after ice candidates are gathered.
I am using xirsys Turn/Stun servers. I have tried to find a way to find a way to make sure my app runs even if firewall is On. I have seen other webrtc example which do no get blocked by firewall. What am I missing here ?????
UPDATE
Did some more testing with following results
Does not matter if Firewall is On or Off on the client making connection. If the Firwall is On who is getting the Offer the connections fails
Example: Consider client 1 is making the offer and client 2 is receiving the offer. If client 2 has firwall On, the connection fails. If firewall is Off the connection is etablished. Does not matter if client 1 has its firewall On or Off. If client 1 and 2 or on same computer, the connections is always sucessful.
You need to compare the types of TURN servers used by your app which does not work with the ones that work. chrome://webrtc-internals shows the servers.
do you use TURN/TCP and TURN/TLS?
on which ports do the the TURN servers run?
for the working service, what kind of connection is used (see here for how to determine this)
And there are cases where the connection will fail. Your UX needs to deal with those too.

Is WebRTC without any server not even a signaling server possible?

I'm trying to setup an a cordova plugin for iOS which implements the webrtc functions without using any server and it will only be used on a local network. I know there is this plugin, which looks promising but i have some problems with it.
My plan is not to use a TRUN, STUN or any kind of signaling server.
Maybe you think right now: "Ok this is not possible. No signaling equals no connection." But let me explain first. As pointed out here and
here it's possible to avoid using a TRUN, STUN or ICE server. I think this is a good way to start my project but there is still an open question. How shall the devices find each other if there isn't any kind signaling (in the example they use a Node.js server)? Right now i'm playing with the idea of an QR-Code which contains all the necessary information.
At the end it should look like this (black arrwos are more important):
The idea is that everyone who comes into a room has to scan a QR-Code on the RP and then the device knows the IP, port, etc. of the RP and a WebRTC connection with a DataChannel will be established.
I've been looking for an answer for days now, but due to the fact (or at least one of the reasons) that WebRTC is not even supported on iOS nativly there aren't many WebRTC examples out there which work on iOS and no one for a local network.
So my question is: Am I on the right way or is this not even possible? (I found no example for this anywhere, but if I put all the posts I read together, I think it should be possible.)
First of all, TURN and STUN are not signaling server. Signaling server is the term normally associated with the backend server that let's you relay the messages between two peers before the connection is established. The signaling server is thus used to establish the connection. Once the connection is established, there is no role of the signaling server in the communication, unless you intend to make any changes to the connection parameters.
TURN and STUN servers, on the other hand, are used during the connection establishment process. It helps the two peers find a direct path to each other. So when the connection is established, the peers can talk directly with each other and they don't require the signaling server to relay the messages anymore.
Now coming to your question, short answer is, no, your plan is incomplete.
Here are some changes that you'd need in order to make it work:
QR Code is not adequate to convey all required information. According to this answer, they can store roughly 4kb of maximum data. Thus it is not sufficient to pass all candidates.
Not to mention that WebRTC requires both devices to share the candidates. So, you'd need a display and QR code scanner on the Raspberry PI.
You might want to explore alternatives such as Wifi to allow for two-way data sharing between the device and Raspberry Pi. Once setup, the Wifi connection will act as the Signaling server.
Though I am not well versed in iOS or Raspberry Pi. So I would recommend that you ask a separate question about the choice of communication channel if you are unsure about what to choose. Keep in mind that you need Raspberry Pi to be able to communicate with the device for a short period of time in order to allow WebRTC connection to be established.
Coming to STUN and TURN servers, you may be able to get away without using them. I have seen a few cases when my app is able to establish connection to peers within the local network without STUN and TURN servers.
However, I would strongly recommend that you use at least a STUN server. They are often available for free of charge. Google and Firefox also provide their own STUN servers that you can use in any of your WebRTC apps. You can search on internet to get their details.
TURN servers are required only when the two peers are behind NAT's. In such cases STUN servers are sometimes incapable of finding a direct route between them, and you need the TURN server to relay the audio/video/message stream.
Your plan to establish the WebRTC channel between Raspberry Pi and the phones (the black arrows) seem fine to me. It would help you establish further connections between two phones whenever required.
However, if you eventually decide to implement something like Wifi on your Raspberry Pi, the WebRTC connection may be redundant. After all, you could use Wifi to pass the data back and forth, and don't really need an additional layer of WebRTC channel to do that.
Since you run your app on a local network you don't need STUN and TURN servers. But still you need a signaling server. Signaling can't be done with QR-codes, read more about WebRTC and you will understand why.
But a signaling server can be very simple. Since you have that raspberry pi in your local network, you can use this as your signaling server. Just install node, express and socket.io on it. You need only one simple javascript file, mine is only 23 lines of code. Stop wasting your time with QR-codes and you will have your signaling server up and running in no time. You can look at Google Codelab for an example. Hopes this helps you !!

Categories

Resources