muaz-khan / WebRTC-Experiment

WebRTC, WebRTC and WebRTC. Everything here is all about WebRTC!!
https://www.webrtc-experiment.com/
MIT License
11.66k stars 3.95k forks source link

No way to know whether to create a room, or join one #38

Open mvayngrib opened 11 years ago

mvayngrib commented 11 years ago

One of the current problems I'm experiencing with RTCMultiConnection-v1.2.js with the socketio-over-nodejs server is the lack of a proper way to establish a session. I'm currently using the hack that waits 5 seconds to see if it gets a session invite, otherwise it creates a new channel, but it's pretty unreliable, especially with a slow connection.

I feel like there should be a way to ask the server - "does this room exist?" - like you do with Firebase. Otherwise the two people who want to chat have to go in one at a time, which is not always practical. And a 5 second wait is quite long...especially when testing over and over :)

imomin commented 11 years ago

I am new to node.js and WebRTC and I started playing with it last night, I have similar thoughts, I was wondering if there is a way to remove dependency of Firebase.

I came up with this idea (not tested) In signaler.js add var rooms = []; and add

//expects query param id eg. http://localhost:8888/isRoomExists?id=blahblah app.get('/isRoomExists', function (req, res) { res.setHeader('Content-Type', 'application/json'); res.send(rooms.indexOf(req.query.id) > -1); }); //expects query param id eg. http://localhost:8888/roomAdd?id=blahblah app.get('/roomAdd', function (req, res) { res.setHeader('Content-Type', 'application/json'); var roomId = req.query.id; if(rooms.indexOf(roomId) == -1){ rooms.push(roomId); res.send(roomId); } else { //may be throw error res.send(roomId); } }); //expects query param id eg. http://localhost:8888/roomRemove?id=blahblah app.get('/roomRemove', function (req, res) { res.setHeader('Content-Type', 'application/json'); var roomId = req.query.id; if(rooms.indexOf(req.query.id) > -1){ rooms.splice(rooms.indexOf(req.query.id),1); } res.send(true); });

muaz-khan commented 11 years ago
function testChannelPresence(channel) {
    var socket = io.connect('/');

    socket.on('presence', function (isChannelPresent) {
            console.log('is channel present', isChannelPresent);
            if (!isChannelPresent) playRoleOfSessionInitiator();
        });

    socket.emit('presence', channel);
}
testChannelPresence('default-channel');
mvayngrib commented 11 years ago

cool, thanks :)

I know I asked for this functionality...but thinking about it now, it would save a trip to the server if you could call 'new-channel' and have the server either a) create a new channel IFF it doesn't already exist, or b) connect to the channel if it already does

kooler commented 11 years ago

Is it possible to make such kind of trick for connections based on Firebase?

muaz-khan commented 11 years ago

Are you meant something like this?

channelToTest = 'default-channel';
new Firebase('https://chat.firebaseIO.com/' + channelToTest).once('value', function (data) {
    var isChannelPresent = data.val() != null;
    if (!isChannelPresent) playRoleOfSessionInitiator();

    console.log('is channel present', isChannelPresent);
});
kooler commented 11 years ago

Yep, exactly, works great. Thanks!

zdfs commented 11 years ago

The Firebase method doesn't seem to work with 1.3. Should it?

muaz-khan commented 11 years ago

@zdfs Are you meant "unable to detect presence of the channel".....or....?

Did you try something like this?

channelToTest = location.hash.substr(1) || 'another-channel';

new Firebase('https://chat.firebaseIO.com/' + channelToTest).once('value', function (data) {
    var isChannelPresent = data.val() != null;

    // if no channel present; open new session
    if (!isChannelPresent) connection.open('a-session-id');

    // else join existing session
    else connection.connect('a-session-id');
});
zdfs commented 11 years ago

Yeah. data.val() always returns null in 1.3. It works correctly in 1.2.

muaz-khan commented 11 years ago

It works; session-id must be same for all three cases:

  1. For session initiator e.g. connection.open('session-id')
  2. For session participants e.g. connection.connect('session-id')
  3. And for detecting presence of the session e.g. new window.Firebase('https://chat.firebaseIO.com/' + sessionid)
var sessionid = 'session-id';
var connection = new RTCMultiConnection();

connection.session = {
    audio: true,
    video: true
};

connection.onstream = function (e) {
    document.body.appendChild(e.mediaElement);
};

new window.Firebase('https://chat.firebaseIO.com/' + sessionid).once('value', function (data) {
    var isRoomPresent = data.val() != null;
    if (!isRoomPresent) connection.open(sessionid);
    else connection.connect(sessionid);

    console.debug('room is present?', isRoomPresent);
});

By default, v1.3 uses chat.firebaseIO.com i.e. chat key. You can override it too:

// overriding for session initiation
connection.firebase = 'signaling';

// presence detection
new window.Firebase('https://signaling.firebaseIO.com/' + sessionid).once(....);

You can see that signaling key is used both for session initiation and presence detection.

zdfs commented 11 years ago

I'll take a look tomorrow. Thanks for your input!

zdfs commented 11 years ago

Turns out that https://rtcweb.firebaseIO.com doesn't behave like https://chat.firebaseIO.com. Once I switched the url, behavior returned to normal.

Will probably switch to my own socket IO implementation at some point, but will need the Firebase service for a bit longer. Thanks for your help!

muaz-khan commented 11 years ago

Do you know, firebase can behave like socket.io over node.js too!

new Firebase('https://YOURINSTANCE.firebaseio.com').on('value', function(snap) { 
     // here is the data transferred from the sender!
    var data = snap.val();

    // will never keep data on firebase servers!
    snap.ref().remove(); 
});

I'm using same technique in RTCMultiConnection-v1.4 and DataChannel-v1.1.

Their set function allow us overwrite existing data; however push seems better because we usually share different kinds of data e.g. ice candidates; session descriptions; presence/notifications etc. (simultaneously)

ghost commented 11 years ago

@muaz-khan Your proposed solution, which is working well with RTCMultiConnection-1.3, fails when using RTCMultiConnection-1.4. How can we then check whether to create or join a room?

muaz-khan commented 11 years ago

RTCMultiConnection-v1.4 working demos coming soon. E.g.

  1. All-in-One test
  2. Video Conferencing & File Sharing & Text Chat
  3. Renegotiation
  4. Auto Session Initiation (i.e. auto join/create rooms)

etc.

Following code works well with v1.4 too; to detect presence of the room; and create/join room accordingly:

new window.Firebase('https://chat.firebaseIO.com/' + sessionid).once('value', function (data) {
    var isRoomPresent = data.val() != null;
    if (!isRoomPresent) connection.open(sessionid);
    else connection.connect(sessionid);

    console.debug('room is present?', isRoomPresent);
});
softi89 commented 10 years ago

can I replace Firebase('https://chat.firebaseIO.com/' + sessionid) with node.js signaling server