Skip to main content

One of the base features of WebRTC is an ability to transfer data between peers secure and on high speed. Data exchange is realized via Data Channel (also called RTCDataChannel) API.

Data channel is basically a one direction stream which is used to share data in peer-to-peer connection. For example during video call data is sent via 2 channels: one for outgoing video stream and other for audio. Optionally we can create additional data channels (up to 65535 per connection), for instance to send file to other peers.

How does it work?

After establishing peer-to-peer connection, application creates at least one data channel to share video, audio or pure data. By default data channel uses SRTP (Secure Real-time Transport Protocol), which doesn’t require packet retransmission, so stream continues as fast as connection permits; in the other side when we need to share reliable data like an image or a file, data channel can transport information through SCTP (Stream Control Transmission Protocol) which has control over packet retransmission and ordering. Both protocol works over UDP.

Is that secure?

Security is one of the most important topics in WebRTC, no matter which transport protocol we use, both implement DTLS (Datagram Transport Layer Security) to encrypt data, which is similar to SSL/HTTPS but for UDP instead of TCP.

How can I use data channels without diving into WebRTC specification?

Abstraction of data channels is already implemented in VideoLinkPlatform API, so you can only use simple API functions to transfer data directly between peers.

tl;dr

RTC data channel provides the way to share data in peer-to-peer connection. All data is sent over UDP (which makes communication fast) and depending on kind of data we need to share, channel will transport everything over SRTP or SCTP. First one doesn’t require packet retransmission when a packet is lost, which is useful when we need to share a video or audio stream (so realtime is more important than reliability), when the other protocol (SCTP) guarantees data delivery by requesting packet retransmission (when needed) and keeps ordering, so is useful when all packets must be received in the same order they were sent (for example file transmission).

Data channels are supported by almost all modern browsers and VideoLinkPlatform API provides a simple way to use them as well as seamless fallback for old ones.

Let’s make simple javascript web app that will provide peer-to-peer file sharing via WebRTC

First let’s make sure to have VideoLinkPlatform JS SDK included into your page

1
<script src="//cdn.videolinkplatform.com/vl_api.js"></script>

Then you need to initialize connector object with own API key and desired connection type (which determines what kind of data we’re going to work with). All available parameters can be found in documentation.

Connector object establishes connection to VideolinkPlatform Signaling Cloud and provides API for managing rooms.

1
2
3
4
new VideolinkPlatformConnector({
  apiKey: '<your API key>',
  connectionType: 'chat-only'
}, function success(connector){...}, function failure(error){...})

Constructor takes success callback as second argument, that will receive initialized connector when it’s ready. As soon as we get connector object we can create a room:

1
2
3
connector.createRoom({name: 'file-share'}, function(room){
  vlpRoom = room; //we can use object vlpRoom to access room API
  ...

All peers should join room with the same name (in our case “file-share”) to be able to exchange data.

Files are shared via FileSharingService which is also used to work with file sharing events and can be retrieved from room object:

1
var fileSharingService = vlpRoom.getFileSharingService();

There are plenty number of events in the file sharing process (as you can see here), but for this example we just need to handle onFileRequest and onDownloadCompleted.

1
2
3
4
5
6
7
8
 fileSharingService.onFileRequest(function(fileTransferId, name) {
    if (confirm('Would you like to download file: ' + name)) {
      fileSharingService.acceptFileSharingRequest(fileTransferId);
    }
  });
  fileSharingService.onDownloadCompleted(function(fileId, name, fileData, type, mime) {
    addDownloadedFile(fileId, name, fileData, type, mime);
  });

Now, when we have room and file sharing events configured, we just need to pass selected file to fileSharingService.startFileSharing(file) to start sharing:

1
2
3
4
5
6
function sendP2PFile (file) {
  if (!!vlpRoom){
    var fileSharingService = vlpRoom.getFileSharingService();
    fileSharingService.startFileSharing(file);
  }
}

And that’s it, we have our file sharing js app.

Here’s full source code with some comments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
$(function() {
    //We will save File Sharing Service to this variable as soon as room will be created
    var fileSharingService;

    /**
     * This method is called by Drag'n'drop interface when user droped file into container
     * and receives selected files as argument.
     * (it can also be called when file is selected in <input type="file">)
     */
    function sendP2PFile(file) {
        if ( !! fileSharingService) {
            fileSharingService.startFileSharing(file);
        } else {
            alert('File Sharing Service is not ready yet');
        }
    }

    /**
     * Called by onDownloadCompleted event, to show info about downloaded file
     */
    function addDownloadedFile(fileId, name, fileData, type, mime) {
        $('#transmited-files').append('<a target="_blank" href="' + fileData +
            '" class="file-thumbnail col-sm-3"><i class="glyphicon glyphicon-file"></i> Open ' +
            name + '</a>');
    }

    /**
     * Initialize connection to VideolinkPlatform Signaling Cloud and
     * establish text/data connection (so no video and audio stream will be sent)
     */
    var vlpConnector = new VideolinkPlatformConnector({
        apiKey: '58109df59af3c725f8ed0f2a0c65e341',
        connectionType: 'chat-only'
    }, function(connector) {
        /**
         * Create room with name "file-share". If room already exists we will just join it,
         * otherwise it will be created first.
         */
        var roomName = 'file-share';
        connector.createRoom({
            name: roomName
        }, function(room) {
            /**
             * Room is ready, so we can retrieve File Sharing Service and prepare to file transfer
             */
            fileSharingService = room.getFileSharingService();

            /**
             * This event is fired when remote peer initiates file transfer
             */
            fileSharingService.onFileRequest(function(fileTransferId, name) {
                if (confirm('Would you like to download file: ' + name)) {
                    fileSharingService.acceptFileSharingRequest(fileTransferId);
                }
            });

            /**
             * This event is fired when download is completed and we can show file info
             */
            fileSharingService.onDownloadCompleted(function(fileId, name, fileData, type, mime) {
                addDownloadedFile(fileId, name, fileData, type, mime);
            });

        })
    }, function(error) {
        console.log(error);
    })
})

Now if we add some basic layout with ability to drag'n'drop files into web page, we’ll get pretty cool file sharing service: http://rawgit.com/VideolinkPlatform/vlp-samples/master/file-sharing/index.html.

So as you can see, apart of video and audio abilities, WebRTC also provides rich data transfer functionality, which simplifies life of developer, as supports security and different types of transfers out of the box.

Hope you enjoyed reading. Questions and suggestions in comments are appreciated.

Full source code (together with layout, styles and drag'n'drop) is available on GitHub.

Comments