Skip to content
Muaz Khan edited this page Aug 6, 2013 · 7 revisions

RTCDataConnection is obsolete. It is strongly recommended to try RTCMultiConnection instead:

https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RTCMultiConnection

=

=

RTCDataConnection is a library sits top of RTCPeerConnection and RTCDataChannel to bring easiest file and data sharing experience. RTCDataConnection auto-handles multi-user data connectivity like file broadcasting or group file sharing.


Demos ---- First of all, try RTCDataConnection Demos!!


RTCDataConnection allows you:

  1. Implement file or data sharing feature in your own site, in maximum 2 minutes!
  2. Share data or file over one-to-one, one-to-many, or many-to-many, in maximum two minutes!

RTCDataConnection makes it very easy to use RTCDataChannel APIs to share whatever you want (on both chrome and firefox):

  1. You can share unlimited files of any size
  2. You can share pre-recorded media buffers
  3. You can share part of screen, or the entire webpage (in realtime!)
  4. You can share text message over one or unlimited peers
  5. You can manage whether you want to share one-to-one, one-to-many or many-to-many

Though, chrome-to-firefox data sharing is not implemented yet. However, you can share data among same browsers.

First Step: Link the library

<script src="https://bit.ly/RTCDataConnection-v1-0"></script>

Second Step: Understand the structure of the library

Here is the entire structure of RTCDataConnection object:

var rtcDataConnection = new RTCDataConnection({
    // onopen is optional
    onopen: function (channel) {},

    // onmessage is optional
    onmessage: function (message) {},

    // onclose is optional
    onclose: function (event) {},

    // onerror is optional
    onerror: function (event) {},

    // openSignalingChannel is mandatory
    openSignalingChannel: function (config) {},

    // direction is optional
    direction: 'one-to-one || one-to-many || many-to-many',

    // onNewConnection is optional
    onNewConnection: function (user) {
        // user.id --- user.session
        // window.tempUser = user; --- storing in memory
    },

    // onFileReceived is optional
    onFileReceived: function (fileName) {},

    // getFileStats is optional / data.items
    getFileStats: function (data) {},

    // onFileSent is optional / file.name
    onFileSent: function (file) {}
});

// initDataConnection is mandatory --- initializing the data connection
// call it once; on the session initiator's side....participants don't need to call it
rtcDataConnection.initDataConnection();

// send is optional ..... are you sure?...!!!
rtcDataConnection.send('------- file/data/text -------');

// connect is optional
rtcDataConnection.connect({
    id: user.id,
    session: user.session
});

Only initDataConnection and openSignalingChannel are mandatory.

openSignalingChannel allows you use your own socket.io implementation.

If you want to chat or share files with your friend; you need to initiate the session. Other users don't need to reinitiate the session.

initDataConnection is just for offerer or session initiator or room owner only:

rtcDataConnection.initDataConnection();                                      

Data channels between you and all your friends will auto-open. If you want to manually open data connections on your friends' side:

onNewConnection: function (user) {
    // user.id
    // user.session
    // store user's ID and user's session ID in an "array", "object" or database
    // window.tempUser = user;
}

// whenever you want to open data channels in your friends side, call this:
rtcDataConnection.connect({
    id: user.id,
    session: user.session
});

You can share files like this:

<input type=file>
document.querySelector('file').onchange = function () {
    var file = this.files[0];
    rtcDataConnection.send(file);
};

You can send text messages or data like this:

document.querySelector('input').onchange = function () {
     rtcDataConnection.send(this.value);
};

// send any kind of data
rtcDataConnection.send({
    number: 4534543,
    string: 'safsafdasfas',
    boolean: true,
    data: {}
});

File Sharing Helpers

  1. onFileReceived
  2. getFileStats
  3. onFileSent

RTCDataConnection object will invoke onFileReceived method as soon as the entire file is successfully received.

onFileStats will be fired during file distribution. It will tell you how many items are remaining.

onFileSent will be fired after sending the entire file.

Manage data connection styles or directions

You can manage whether you want to share as:

  1. one-to-one
  2. one-to-many
  3. many-to-many

Only above three directions are supported in the moment.

Example 1: Simplest Usage of RTCDataConnection / Demo

var rtcDataConnection = new RTCDataConnection({
    onmessage: function (message) {},
    openSignalingChannel: function (config) {}
});
rtcDataConnection.initDataConnection();

Example 2: Manually opening data connection on the participant's side / Demo

var rtcDataConnection = new RTCDataConnection({
    onNewConnection: function (user) {
        /* storing in memory; you can store in database! */
        window.user_info_in_memory = user;
    },
});

[Manually_Open_DataConnection_Button].onclick = function () {
    /* accessing window.user_info_in_memory object from memory or database */
    rtcDataConnection.connect({
        id: window.user_info_in_memory.id,
        session: window.user_info_in_memory.session
    });
}

Explaining RTCDataConnection in details

onopen

RTCDataConnection object will call this method as soon as data connection's onopen event will fire.

onmessage

This method will be called on receiving each new data message or file.

onclose

RTCDataConnection object will call this method as soon as data connection's onclose event will fire.

onerror

RTCDataConnection object will call this method as soon as data connection's onerror event will fire.

openSignalingChannel

This method is aimed to open socket.io connection. Here is an example:

var rtcDataConnection = new RTCDataConnection({
    openSignalingChannel: function (config) {
        var socket = io.connect('http://your-site:8888');
        socket.channel = config.channel || 'WebRTC-Experiment';
        socket.on('message', config.onmessage);

        socket.send = function (data) {
            socket.emit('message', data);
        };

        if (config.onopen) setTimeout(config.onopen, 1);
        return socket;
    }
});

direction

  1. Two people can share data or file
  2. A person can share file or data with many others
  3. A group of people can share data or file direclty and concurrently with each other

So:

  1. one-to-one value can be used to limit the number of connections
  2. one-to-many value is for broadcasting data or file
  3. many-to-many is a real-life usage!

onNewConnection

Each new user's session ID will be passed over this method. Session IDs allows RTCDataConnection object to exchange SDP/ICE between two or more users.

By default, RTCDataConnection tries to auto-open data connections between these two persons.

You can manually open data connections by using onNewConnection and connect methods.

onFileReceived

var rtcDataConnection = new RTCDataConnection({
    onFileReceived: function (fileName) {
        console.debug('File <' + fileName + '> received successfully.');
    }
});

getFileStats

var rtcDataConnection = new RTCDataConnection({
    getFileStats: function (data) {
        console.log(data.items, ' items reamining');
    }
});

It is a progress or stats of the current file sharing.

onFileSent

var rtcDataConnection = new RTCDataConnection({
    onFileSent: function (file) {
        console.debug('File <' + file.name + '> sent successfully.');
    }
});

initDataConnection

If 10 people want to share data or files; only userA should call this method:

rtcDataConnection.initDataConnection();

This method initiates the data connection. The person who calls this method is known as broadcaster or initiator or owner of the data session.

send

// INPUT TYPE=FILE ---- file of any size!
rtcDataConnection.send(File);

// any javascript data type
rtcDataConnection.send({
    data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
});

// maximum 1000 chars of text message [will be fixed soon]
rtcDataConnection.send('string ----- text');

You can send anything directly!

connect

If you want to manually open data connections; call connect method:

rtcDataConnection.connect({
    id: user.id,
    session: user.session
});

See more information here.

How RTCDataConnection Works?

As soon as you'll call rtcDataConnection.initDataConnection(), RTCDataConnection will:

  1. Opens a new socket known as default socket
  2. It calls openSignalingChannel method to open that socket
  3. It creates a unique token for your session
  4. It starts transmitting your ID and your session's ID over that new socket

If one of your friends opens the same page; you don't need to call rtcDataConnection.initDataConnection() in his side.

RTCDataConnection will auto-open data ports between you and your friend.

If you want to manually open data ports between you and your friend; use onNewConnection method as explained above.

When you try to send a file:

  1. If you're using Firefox; RTCDataConnection will send that file directly
  2. If you're using chrome; RTCDataConnection will read your file as Data URL; split it in chunks; and transfer that chunks in a loop.

Chrome Canary will start supporting SCTP streams from tomorrow (March, 22, 2013). However, you need to enable a flag using chrome://flags.

Alongwith SCTP streams; they'll also support Blob as binaryType; so we will be able to share files or blobs direclty!

Realtime Examples using RTCDataConnection

Write group text chatting app using RTCDataConnection

<script src="https://bit.ly/RTCDataConnection-v1-0"></script>

<div id="chat-output"></div>
<input type="text" id="chat-input">

<button id="init-session">Open Chatting Room</button>
var rtcDataConnection = new RTCDataConnection({
    onmessage: function (message) {
        var div = document.createElement('div');
        div.innerHTML = message;
        chatOutput.appendChild(div);
    },
    openSignalingChannel: function (config) {
        var socket = io.connect('http://your-site:8888');
        socket.channel = config.channel || 'WebRTC-RTCDataConnection';
        socket.on('message', config.onmessage);

        socket.send = function (data) {
            socket.emit('message', data);
        };

        if (config.onopen) setTimeout(config.onopen, 1);
        return socket;
    }
});

var chatOutput = document.getElementById('chat-output');

document.getElementById('init-session').onclick = function () {
    rtcDataConnection.initDataConnection();
}

document.getElementById('chat-input').onchange = function () {
    rtcDataConnection.send(this.value);
    this.value = '';
};

Write group file sharing app using RTCDataConnection

<script src="https://bit.ly/RTCDataConnection-v1-0"></script>

<input type="file">
<div id="quick-info"></div>
<button id="init-session">Open File Sharing Room</button>
var rtcDataConnection = new RTCDataConnection({
    openSignalingChannel: function (config) {
        var socket = io.connect('http://your-site:8888');
        socket.channel = config.channel || 'WebRTC-RTCDataConnection';
        socket.on('message', config.onmessage);

        socket.send = function (data) {
            socket.emit('message', data);
        };

        if (config.onopen) setTimeout(config.onopen, 1);
        return socket;
    },
    onFileReceived: function (fileName) {
        document.getElementById('quick-info').innerHTML = fileName + ' received.';
    },
    onFileSent: function (file) {
        document.getElementById('quick-info').innerHTML = file.name + ' sent.';
    },
    getFileStats: function (data) {
        document.getElementById('quick-info').innerHTML = data.items + ' items remaining.';
    }
});

document.getElementById('init-session').onclick = function () {
    rtcDataConnection.initDataConnection();
}

document.querySelector('input[type=file]').onchange = function () {
    rtcDataConnection.send(this.files[0]);
};

Write one-to-one file sharing app using RTCDataConnection

Also manually connect data connections.

<script src="https://bit.ly/RTCDataConnection-v1-0"></script>

<input type="file">
<div id="quick-info"></div>

<button id="init-session">Open File Sharing Room</button>
<button id="manually-connect" disabled>Manually Open Data Connection</button>
var rtcDataConnection = new RTCDataConnection({
    openSignalingChannel: function (config) {
        var socket = io.connect('http://your-site:8888');
        socket.channel = config.channel || 'WebRTC-RTCDataConnection';
        socket.on('message', config.onmessage);

        socket.send = function (data) {
            socket.emit('message', data);
        };

        if (config.onopen) setTimeout(config.onopen, 1);
        return socket;
    },
    onFileReceived: function (fileName) {
        document.getElementById('quick-info').innerHTML = fileName + ' received.';
    },
    onFileSent: function (file) {
        document.getElementById('quick-info').innerHTML = file.name + ' sent.';
    },
    getFileStats: function (data) {
        document.getElementById('quick-info').innerHTML = data.items + ' items remaining.';
    },

    /* onNewConnection is first step to manually open data connection */
    onNewConnection: function (user) {
        document.getElementById('manually-connect').disabled = false;
        document.getElementById('init-session').disabled = true;

        window.tempUser = user; /* storing in memory */
    },
    direction: 'one-to-one'
});

document.getElementById('init-session').onclick = function () {
    rtcDataConnection.initDataConnection();
};

/* rtcDataConnection.connect is second but last step to manually open data connection */
document.getElementById('manually-connect').onclick = function () {
    /* accessing window.window.tempUser from memory */
    rtcDataConnection.connect({
        id: window.tempUser.id,
        session: window.tempUser.session
    });
};

document.querySelector('input[type=file]').onchange = function () {
    rtcDataConnection.send(this.files[0]);
};

Using Firebase as Signaling Channel

In all above examples, socket.io is used for signaling. You can use Firebase for signaling too:

<script src="https://cdn.firebase.com/v0/firebase.js"></script>
var rtcDataConnection = new RTCDataConnection({
    openSignalingChannel: function (config) {
        var channel = config.channel || 'WebRTC-RTCDataConnection';
        var socket = new Firebase('https://chat.firebaseIO.com/' + channel);
        socket.channel = channel;
        socket.on("child_added", function (data) {
            config.onmessage && config.onmessage(data.val());
        });
        socket.send = function (data) {
            this.push(data);
        }
        config.onopen && setTimeout(config.onopen, 1);
        socket.onDisconnect().remove();
        return socket;
    }
});