# Communication

## A Web RTC Tutorial

With WebRTC, adding a peer-to-peer video chat to a site is as easy as child's play and the best part of it is that there is no need for your users to download plugins to use the service.

There are two pieces needed to set up peer-to-peer video chat using WebRTC: an HTML5 compliant browser, and the proper code on your server. This blog will walk you through the steps to get a simple service up and running.

WebRTC is part of the HTML5 standard and is still under development. But by downloading an augmented WebKit library from Ericsson Labs, you can try it out today. At present, only Ubuntu 11.04 is supported for the browser, but there are no such restrictions on the server. For simplicity, we'll assume that the server will run on the same machine as at least one of the clients.

## Installing the Browser

To install the browser, follow the steps here. You can choose to use Epiphany or a simple demo browser (GtkLauncher) for your tests, but for this tutorial we'll use GtkLauncher. To make sure it was installed correctly, fire up a terminal window and go to the WebRTC demo page at Ericsson Labs using the following command:

/usr/lib/webkitgtk-1.0-0/libexec/GtkLauncher https://webrtc.labs.ericsson.net



If you see a page with a Captcha, you're all set to go, but if you see a warning that your browser lacks support for PeerConnection video conferencing you need to track down the problem. See the install page for hints.

Note that the following steps are only required if you want to host the signaling server yourself. If you don't, just use the one on Ericsson Labs.

## Setting up the Server

With the browser part cleared, we'll now turn to the server setup. First, there are a number of prerequisites that need to be fulfilled. You'll need Apache2, php5, and some supporting modules. Use apt-get to install them by:

sudo apt-get install apache2 libapache2-mod-php5 php5-dev php-pear



Then, install libevent:

sudo apt-get install libevent-dev



Finally, you have to add the PHP module for libevent using PECL, but first you have to change some of the PECL settings. You can show the PECL setting using the command:

pecl config-show



If you're behind a proxy, the first thing to add is

pear config-set http_proxy http://myproxy.my.org:8080/



where you substitute your proxy and port number. Two things to note is that the command is pear, not pecl, and that the trailing slash is mandatory.

Next, libevent is considered beta, so you need to make pecl aware of that using:

pecl config-set preferred_state beta



before the install step:

sudo pecl install libevent



During the installation, you will be presented with a question. Just hit 'enter' to accept the default (autodetect).

If the installer reports that it couldn't update your php.ini file, you'll have to do so manually. Open the file using the command:

sudo pico /etc/php5/apache2/php.ini



locate the section "Dynamic Extensions", and add the line:

extension=libevent.so



Now save the file.

If your server is accessible from the outside world, you might want to add a Captcha to provide some protection from evil. The following steps will set you up with the necessary support. Note that if you skip this part, you'll need to comment out a section in the code provided for this tutorial, see below.

sudo apt-get install php5-gd libfreetype6 flite



### Final Step

During the connection phase, the server will create FIFOs and we need a suitable place to do so. We also have to make sure that the server has permission to create the FIFOs.

sudo mkdir /var/run/starchat

sudo chown :www-data /var/run/starchat

sudo chmod g+w /var/run/starchat



Unfortunately, there is a known bug in the server code that prevents us from cleaning up the FIFOs automatically, so for now we need to use a cron job to delete stale FIFOs periodically. Use the command:

crontab -e



to start an editor seesion, and add the following line to the crontab file

0 12 * * 0 find /var/run/starchat -mtime +1 -exec rm -f {} \;



and save the file. Now all FIFOs older than 24 hours will be removed on a regular basis.

All that is left to do before continuing with the fun part, is to restart the webserver.

sudo /etc/init.d/apache2 restart



## The Videochat Server Code

The complete code for this tutorial can be downloaded from Ericsson Labs. Next comes a quickstart guide, followed by a longer section detailing the different parts of the implementation.

### Quickstart Guide

To install it to the server, cd into the directory where the zip file was downloaded and issue the command:

sudo unzip videochat-example.zip -d /var/www/



NB: If you didn't install Captcha support during the server setup part, you must comment out the captcha code in create.html and change the hidden property of the content div to false, like so:

<!--
<div id="cap">
<form>
<p><a href="audio-captcha.php">Cannot see the image? Click for audible version</a></p>
<label>Enter the contents of image</label>
<input type="text" name="user_code" id="user_code" />
<input type="button" onclick="verify();" value="Verify Code"/>
</form>
</div>
-->
<div id="content" hidden="false">

To test your setup, start a browser

/usr/lib/webkitgtk-1.0-0/libexec/GtkLauncher http://localhost/videochat-example &



enter the captcha, and you'll be presented with a invitation link. Copy the link and start a second browser with the link as the argument

/usr/lib/webkitgtk-1.0-0/libexec/GtkLauncher <invitation link> &



When you click accept in the second browser, you should get a media selection dialog and once you click OK your video chat session should start.

### Code Walktrough

The code conceptually is split in two parts, signaling and the peer-to-peer videochat. Let's start by looking at the signaling. The sequence of events are shown below.

• Caller
• creates a FIFO on the server for listening.
• adds the FIFO as an event source.
• generates an invitation URL.
• Caller passes the invitation URL to the callee.
• Callee
• parses the invitation URL to obtain the remote (caller) FIFO
• creates a FIFO on the server for listening
• sends a signaling message with it's local FIFO to the caller
• creates a peer connection
• Caller
• receives the remote FIFO from the callee
• creates a peer connection

Now the signaling channels and the peer-to-peer connection have been set up and both caller and callee can begin the chat session.

Let's take a closer look at the code used in step above steps. (Note that the code below only reflects the parts relevant to this discussion).

#### Step 1

The process starts out when the caller load create.hml which contains a text field for the invitation URL and an (initially hidden) iframe with the chat code. The window.onload method is set up to call createFIFO (in signaling.js) with an anonymous function to create an invitation URL from the FIFO name passed as a parameter.

-- create.html --

<script>
Signaling.createFIFO(function(fifoid) {
var url_base = location.href.substring(0,location.href.lastIndexOf('/'));
var url = url_base + "/accept.html?id=" + fifoid;
document.getElementById('invitationUrl').value = url;
});
}
</script>

<body>
<iframe id="chat" name="chat" src="chat.html" hidden="true"></iframe>
</body>

The createFIFO method send an XHR for a new named FIFO to the server. When the server responds, the FIFO name is retrieved and stored. Next, an event source is set up that will call onSigMsg() whenever the peer writes something to the FIFO.

-- signaling.js --

createFIFO: function(on_fifo_created) {
var createClient = new XMLHttpRequest();
createClient.open("GET", "create.php", true);
createClient.send(null);

Signaling.fifoId = this.responseText;
Signaling.eventSrc = new EventSource("recv.php?id=" + Signaling.fifoId);

on_fifo_created(Signaling.fifoId);
};
},

The PHP code to create the named FIFO is simple enough,

-- create.php --

$fifoid=uniqid("id", true); posix_mkfifo("/var/run/starchat/$fifoid", 0600) or die("cannot open FIFO");
echo "$fifoid"; but the code for the event source might need some explanation. Here we are using libevent to listen to the FIFO and echo incoming messages to trigger an event on incoming messages. Ideally, this code should really have the EV_PERSIST flag merged in, but PHP (or Apache, or something else) seems to buffer things a bit too much, and the browser ends up getting nothing. This solution is inefficient, but it works. -- recv.php -- function print_line($fd, $events,$args) {
echo fgets($fd); }$fd = fopen("/var/run/starchat/".$_GET["id"], "r");$base = event_base_new();
$event = event_new(); event_set($event, $fd, EV_WRITE, "print_line"); event_base_set($event, $base); event_add($event);

#### Step 4

The fourth and final step occurs when the caller receives the signaling message with the FIFO ID of the callee. This time around the message arrives in an event triggered by the callee writing to the caller FIFO, so the message has to be handled in onSigMsg(). Since this is first message to arrive, it can be intercepted and the callee FIFO ID is retrieved and stored before the caller peer connection is created.

The internal state is then changed so that subsequent messages are passed to the peer connection for processing.

-- signaling.js --
onSigMsg : function (event) {
var msg = JSON.parse(event.data).msgBody;

switch (Signaling.fifo_state) {
case Signaling.FIFO_STATE_CREATED:
// The inviter just received its first message.
Signaling.remoteFifoId = msg;
Signaling.fifo_state = Signaling.FIFO_STATE_ACCEPTED;

Signaling.Peer = new webkitPeerConnection(Signaling.TURN_CONFIG, Signaling.sendSigMsg);
break;

case Signaling.FIFO_STATE_ACCEPTED:
Signaling.Peer.processSignalingMessage(msg);
break;
}
},

### The Chat Application

The chat application resides in chat.html and the techniques used are explained in detail at Ericsson Labs.

Have fun!

Great web developpement !
Thanks for sharing !

First of all I would like to congratule for this API. I have deployed the server, but when I start the client I just enter the catcha and I can't get the invitation id. It's the same in your website.

I can get a session going between two clients. However, when I try to invite a third client into the videoconference there is a timeout and a message about not being able to connect. Can I expect to get 3 or more in the conference with the current code? Also should there be echo cancellation on the audio?

This example code only supports 2-way communication, however there is nothing preventing you from modifying the code to also support 3-way. Our implementation supports multiple PeerConnection objetcs.

I think The method sendSigMsg() triggers an XHR for writing its argument to the remote FIFO using post.php

Hi there
thanks a lot for all these explenations about webrtc-connections. I tried to replicate the example above on my own webserver, but i was not able to.
i read a lot about webrtc and how this should work. am i right, that there is no need for server-application but the libevent-app? that, if i follow the instructions above, i should be able to make a basic call?

i always get a "NOMATCH"-error, is this a known problem?