Xirsys TURN Server Quick Start Guide

Introduction

The number one problem our customers have when getting started with WebRTC is how to deal with situations in which peer-to-peer connections fail because of NATs and firewalls.

WebRTC promises peer-to-peer communication. And it works. At least much of the time. But sometimes it does not and cannot because NATs and firewalls prevent two peers from communicating directly with one another.

In that case, what you need is a fallback solution – a server or servers that can relay communications between clients. This solution is called a TURN server.

Xirsys provides TURN (and STUN) servers to meet your needs. When you use our TURN servers, you’ll get the benefits of the Xirsys global network. We take the headache out of TURN – providing worldwide, scalable connectivity solutions for your WebRTC apps.

Best of all, we do all the heavy lifting. All you have to do is make a single request to our RESTful API, parse the JSON response, and pass that to your RTCPeerConnection object when you construct it.

It really is that easy.

First, let’s clarify some who this Quick Start Guide is for. This guide is for you if you have an existing WebRTC application that works with a STUN server (such as the public Google STUN server), but fails in cases where the peers are behind NATs that cannot be traversed by way of STUN.

Point being, we are assuming that you already have a WebRTC app that works except for when it fails due to connectivity issues.

(If that’s not you…if you need more guidance getting started with WebRTC, please check out our introductory WebRTC programming guide.)

Making An ICE Call

Okay. Now let’s start looking at the technical stuff.

The good news is, once you’ve got your app built – once you’ve mucked through the nastiness of signaling and all the handshaking that needs to take place in a general sense – this last little bit in order to ensure connectivity for all peers is super simple.

All you have to do is make a call to the Xirsys RESTful API to get the ICE data that you can pass to the RTCPeerConnection constructor. Just handle that RESTful API call asynchronously (using something like a jQuery $.post() or fetch() in JavaScript), and this is a piece of cake.

So let’s quickly look at the relevant Xirsys API call you need to make. It is to the _turn resource. Make a PUT request to that end point, including the channel in the URL and your username/password using basic access authentication.

Let’s look at a couple of examples.

First, a basic cURL example:

   curl -s -H "Content-type: application/json" -XPUT "https://ident:secret@global.xirsys.net/_turn/your-channel"
In this example (and those that follow), ident and secret are values you can get from your Xirsys dashboard. You can find them under the Services section of your Xirsys dashboard. There, once you create a channel, you’ll find them listed as ident and secret. And your-channel is a channel that you create either in your dashboard or programmatically using the Xirsys RESTful API end point _ns.

Next, let’s look at the same example written in Node.js.

var https = require("https");
var options = {
     host: "global.xirsys.net",
     path: "/_turn/your-channel",
     method: "PUT",
     headers: {
       "Authorization": "Basic " + new Buffer("ident:secret").toString("base64")
     }
};
var httpreq = https.request(options, function(httpres) {
     var str = "";
     httpres.on("data", function(data){ str += data; });
     httpres.on("error", function(e){ console.log("error: ",e); });
     httpres.on("end", function(){
       console.log("response: ", str);
     });
});
httpreq.end();
And finally, here’s the same example written in PHP:

<?php
$curl = curl_init();
curl_setopt_array($curl, array(
     CURLOPT_RETURNTRANSFER => 1,
     CURLOPT_URL => 'https://global.xirsys.net/_turn/your-channel',
     CURLOPT_USERPWD => "ident:secret",
     CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
     CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);
?>
Okay, so hopefully you see how easy it is to get the ICE string from the Xirsys RESTful API.

One important note, however. You will need a valid certificate in order to make this request. If you have a problem with this failing, make sure you have a valid certificate to meet the HTTPS requirements.

To make this really easy, you can actually find this code with the correct values already filled out for you under the Services section of your Xirsys dashboard. Select a channel (or create one first if you have not yet). Then scroll down and you’ll find the Quick Connect Example section with the code.

Obviously, you are not restricted to these languages. You can achieve the same results using any programming language that supports making PUT calls over HTTPS.

Please do keep in mind, however, that you should only make the call to _turn from the server…never from the client/peer. If you make the call from the client/peer, you risk exposing your credentials to those who could then make use of your Xirsys channel, using your bandwidth.

Construct An RTCPeerConnection

The response from the _turn call will be a JSON string with two values: v and s. The s value should be "ok". The v value will be a JSON string that will parse to an object containing an array of TURN and STUN server candidates.

Once you’ve retrieved the response from _turn, all you need to do is return the string to the client/peer, parse the string into an object, and use that object to construct an RTCPeerConnection object.

Presumably, you’ll be using jQuery or fetch() to retrieve the _turn response from the server-side. Then you’ll simply parse it using JSON.parse() (or the json() method of the fetch() response) and pass the value of v to a new RTCPeerConnection object.

Let’s look at a very simple example that demonstrates how this can be done. This example uses PHP, but it could easily use any other language to achieve the same result.

First, let’s look at the simple PHP code that we’ll use for this example. This code will go in a file called getice.php. And it looks identical to the PHP code we looked at a moment ago. It simply makes the call to _turn and outputs the response.

<?php
$curl = curl_init();
curl_setopt_array($curl, array(
     CURLOPT_RETURNTRANSFER => 1,
     CURLOPT_URL => 'https://global.xirsys.net/_turn/your-channel',
     CURLOPT_USERPWD => "ident:secret",
     CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
     CURLOPT_CUSTOMREQUEST => 'PUT'
));
$resp = curl_exec($curl);
curl_close($curl);
echo($resp);
?>
Just insert your channel, ident, and secret values, and save this file. In this example we’ll assume it is running on localhost at the htdocs root.

Next, here’s a simple HTML file with some JavaScript that demonstrates how to make the asynchronous call for the ICE candidates, parse the response, and pass it to a new RTCPeerConnection object.

<html>
   <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
      <script type="text/javascript">
            // This function handles the response from the asynchronous call to getice.php
            function onIceSuccess(data){
                // Parse the JSON string. Then grab the value of v, which is the candidates
                iceObj = JSON.parse(data).v;
                // Pass the ICE candidates object to the constructor.
                var pc = new RTCPeerConnection(iceObj);
            }
            $(document).ready(function(){
                 // Call post() to get the ICE candidates.
                 $.post("http://localhost/getice.php", null, onIceSuccess);
            });
      </script>
   </head>
   <body></body>
</html>

Conclusion

Obviously, this is a very simple example only to illustrate how to make the call to get ICE candidates asynchronously and pass that result back to the client/peer. Our expectation is that you have enough experience and knowledge of WebRTC at this point to be able to run with what we’ve just showed you.

Again, if you need more support getting started with WebRTC programming, Xirsys also has a more comprehensive introductory WebRTC programming guide that breaks everything down, step by step, with examples.

With that guide, you should find that any questions you have are answered.