Home

Awesome

webrtc-server Build Status

An Erlang/OTP application that provides all the server side components to make video calls using WebRTC.

Usage

Add webrtc_server as a dependency, for example using rebar3:

{deps, [
        {cowboy, "2.0.0"},
        {webrtc_server, {git, "https://github.com/lambdaclass/webrtc-server", {ref, "56bce3"}}}
       ]}

webrtc_server provides a single Cowboy WebSocket handler webrtc_ws_handler that acts as the Signaling Server to pass data between peers. Add the handler to your cowboy 2.0 application:

Dispatch = cowboy_router:compile([{'_', [{"/websocket/:room", webrtc_ws_handler, []}]}]),
{ok, _} = cowboy:start_tls(my_http_listener,
                           [{port, config(port)},
                            {certfile, config(certfile)},
                            {keyfile, config(certkey)}],
                           #{env => #{dispatch => Dispatch}}).

Note the handler expects a :room parameter to group connecting clients into different rooms.

In addition to the Signaling server, webrtc_server starts a STUN/TURN server on port 3478 using processone/stun, which can be used as ICE servers by the WebRTC peers. A browser client can use it like:

var pc = new RTCPeerConnection({
  iceServers: [{
    urls: "stun:example.com:3478"
  },{
    urls: "turn:example.com:3478",
    username: "username",
    credential: "password"
  }]
});

The examples/simple directory contains a full Cowboy application using webrtc_server and a browser client that establishes a WebRTC connection using the Signaling and ICE servers.

Configuration

authentication

An authentication function needs to be provided to the app environment to authenticate both the websocket connections to the signaling server and the TURN connections.

Example:

{auth_fun, {module, function}}

This function will ba called like module:function(Username), and should return the expected password for the given Username. The password will be compared to the one sent by the client. Authentication will be considered failed if the result value is not a binary or the function throws an error.

The implementation of the function will depend on how the webrtc application is expected to be deployed. It could just return a fixed password from configuration, encode the username using a secret shared between the webtrtc and application servers, lookup the password on a common datastore, etc.

callbacks

webrtc_server allows to define callback functions that will be triggered when users enter or leave a room. This can be useful to track conversation state (such as when a call starts or ends), without needing extra work from the clients.

{join_callback, {module, function}}
{leave_callback, {module, function}}

Both callbacks receive the same arguments:

server configuration

Signaling API reference

The signaling API is used by web socket clients to exchange the necessary information to establish a WebRTC peer connection. See the examples for context on how this API is used.

Authentication

After connection, an authentication JSON message should be sent:

{
    "event": "authenticate",
    "data": {
        "username": "john",
        "password": "s3cr3t!"
    }
}

The server will assign a peer_id to the client and reply:

{
    "event": "authenticated",
    "data": {
        "peer_id": "bxCBrwyL3Ar7Nw=="
    }
}

The rest of the peers in the room will receive a joined event:

{
    "event": "joined",
    "data": {
        "username": "john",
        "peer_id": "bxCBrwyL3Ar7Nw=="
    }
}

Similarly, when a client leaves the room, the rest of the peers will receive a left event:

{
    "event": "left",
    "data": {
        "username": "john",
        "peer_id": "bxCBrwyL3Ar7Nw=="
    }
}

Signaling messages

After authentication, all messages sent by the client should be signaling messages addressed to a specific peer in the room, including a to field. The event and data are opaque to the server (they can be ice candidates, session descriptions, or whatever clients need to exchange). For example:

{
    "event": "candidate",
    "to": "458/53WAkeu+tQ==",
    "data": {
        ...
    }
}

The addressed peer will receive this payload:

{
    "event": "candidate",
    "from": "bxCBrwyL3Ar7Nw==",
    "data": {
        ...
    }
}

Ping

To send a keepalive message to prevent idle connections to be droped by the server, send a plain text frame of value ping. The server will respond with pong.

Server API

The webrtc_server module provides a few functions to interact with connected peers from the server:

Troubleshooting

openssl error during compilation

_build/default/lib/fast_tls/c_src/fast_tls.c:21:10: fatal error: 'openssl/err.h' file not found

On debian it's solved by installing libssl-dev:

sudo apt-get install libssl-dev

On macOS it's solved by exporting the following openssl flags:

export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CFLAGS="-I/usr/local/opt/openssl/include/"
export CPPFLAGS="-I/usr/local/opt/openssl/include/"

Firewall setup for STUN/TURN

iptables -A INPUT -p tcp --dport 3478 -j ACCEPT
iptables -A INPUT -p udp --dport 3478 -j ACCEPT
iptables -A INPUT -p tcp --dport 5349 -j ACCEPT
iptables -A INPUT -p udp --dport 5349 -j ACCEPT
iptables -A INPUT -p udp --dport 49152:65535 -j ACCEPT