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 !!
Related
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).
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?
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.
I'm trying to create a webrtc data channel between client to server.
(the data is different between each client so i need a unique connection between each client to my server)
After some research i concluded that i need to use a turn server and when a client connects to the turn server on the server side i need to act as the other peer and create the data channel, at least that what i think.
I don't need any signalling only pure webrtc connection.
i tried to use this turn server https://github.com/coturn/coturn
but i will deeply appreciate any working example for server to client data channel without any signalling just pure webrtc.
Thanks A lot!:)
You need a signalling server to interchange SDP between the browser and whatever the browser talks to in order to set up the call.
This signalling server can be the same as your media server - but it doesn't have to be.
If your media server is on the open Internet, you don't need a TURN server. If it's behind another NAT, you'll need one.
You've got it all wrong...
To get WebRTC started, you'll need a signaling server. To be able to connect one browser to another, you first need the two browsers to exchange SDP blobs between them. And for that, you need some signaling server to coordinate this process (also known as offer-answer).
Once you get these messages going via a signaling server, you might end up needing a TURN server (and most likely will need a STUN server - which you get for free from most TURN server implementations). The TURN server will relay your data channel's traffic if the browsers will be unable to communicate directly peer-to-peer.
There are quite a few signaling servers out there for you to use. Here's one to try out: https://github.com/feross/simple-peer
I totally understand what you want to achieve here, in fact we had the same requirement in our project too.
Please have a look at the answer I have at: WebRTC Data Channel server to clients UDP communication. Is it currently possible?
I wanna run the stream from client side then join from server to client
. How can I stream the video through a server to another Viewers? Is this possible?
I would like to try and point you in the right direction.
First, lets understand a little more about how WebRTC works.
In WebRTC you have a websocket that is called the bridge, the bridge's role is to help broker a connection between two or more peers.
Generaly speaking, the bridge uses STUN/TURN servers along with SDP Protocol to help establish the connections between peers.
STUN servers are used to establish p2p udp conenctions by punch holes through NAT.
If the STUN fails to punch a whole (ie there is a firewall), a TURN server is used as a hub & spoke (ie relays data though the TURN server).
The full WebRTC stack includes video/audio streaming with vp8/vp9/h264 codecs & data is packaged using RTP.
Lucky for you there is a node-js library that implments almost the entire stack.
https://github.com/js-platform/node-webrtc
The library essentially provides you a WebRTC data channel.
There is no support for "Media Streams" and thus I assume you need to build the encoding/decoding and RTP packaging yourself.
However, there is a discussion here on how to stream audio/video with the data channel:
https://github.com/js-platform/node-webrtc/issues/156
Now, your specific question, how to stream from a "server"?
Well WebRTC is generally p2p, however you could setup a "Server Peer" and designate it as having a source channel only (ie there is no input channel).
This peer then becomes the "server" and all the other peers can view its contents when they connect.
Hope that helps.
Cheers!