8

I am using RTCMultiConnection v3.4.4

I want to run WebRTC on localhost. I have chosen XHR-Signaling because I want the project to be completely offline. I do not want it to depend on the internet, since everything is on localhost (to be later deployed on LAN)

I have included XHRConnection.js and set connection.setCustomSocketHandler(XHRConnection). I also did the override connection.openSignalingChannel...

However, when I open/start the room, my video shows but the buttons that was disabled by disableInputButtons() still remains disabled. The chat is not working.

I did a console.log at override connection.openSignalingChannel... to confirm if it ever got called, but it does not.

Please help on how to implement XHR-Signaling on localhost.

Thanks.

Code:

File: Audio+Video+TextChat+FileSharing.html

<!-- Demo version: 2017.08.10 -->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Audio+Video+TextChat+FileSharing using RTCMultiConnection</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <link rel="shortcut icon" href="./logo.png">
  <link rel="stylesheet" href="./stylesheet.css">
  <script src="./menu.js"></script>
</head>
<body>
  <h1>
    Audio+Video+TextChat+FileSharing using RTCMultiConnection
    <p class="no-mobile">
      Multi-user (many-to-many) video streaming + text chat + file sharing using mesh networking model.
    </p>
  </h1>

  <section class="make-center">
    <input type="text" id="room-id" value="abcdef" autocorrect=off autocapitalize=off size=20>
    <button id="open-room">Open Room</button><button id="join-room">Join Room</button><button id="open-or-join-room">Auto Open Or Join Room</button>

    <br><br>
    <input type="text" id="input-text-chat" placeholder="Enter Text Chat" disabled>
    <button id="share-file" disabled>Share File</button>
    <br><br>
    <button id="btn-leave-room" disabled>Leave/or close the room</button>

    <div id="room-urls" style="text-align: center;display: none;background: #F1EDED;margin: 15px -10px;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;"></div>

    <div id="chat-container">
        <div id="file-container"></div>
        <div class="chat-output"></div>
    </div>
    <div id="videos-container"></div>
  </section>

<script src="./RTCMultiConnection.min.js"></script>
<script src="./adapter.js"></script>
<script src="./XHRConnection.js"></script>

<!-- custom layout for HTML5 audio/video elements -->
<link rel="stylesheet" href="./getHTMLMediaElement.css">
<script src="./getHTMLMediaElement.js"></script>
<script src="./FileBufferReader.js"></script>
<script>
// ......................................................
// .......................UI Code........................
// ......................................................
document.getElementById('open-room').onclick = function() {
    disableInputButtons();
    connection.open( document.getElementById('room-id').value , function() {
        showRoomURL(connection.sessionid);
        xhr
        (
            'start-broadcast.php' , 
            function( responseText ){ console.log( 'Broadcast started [' + document.getElementById('room-id').value + ']' ) }, 
            JSON.stringify( { name: document.getElementById('room-id').value } )
        );
    });
};

document.getElementById('join-room').onclick = function() {
    disableInputButtons();
    connection.join(document.getElementById('room-id').value);
};

document.getElementById('open-or-join-room').onclick = function() {
    disableInputButtons();
    connection.openOrJoin(document.getElementById('room-id').value, function(isRoomExists, roomid) {
        if (!isRoomExists) {
            showRoomURL(roomid);
        }
    });
};

document.getElementById('btn-leave-room').onclick = function() {
    this.disabled = true;

    if (connection.isInitiator) {
        // use this method if you did NOT set "autoCloseEntireSession===true"
        // for more info: https://github.com/muaz-khan/RTCMultiConnection#closeentiresession
        connection.closeEntireSession(function() {
            document.querySelector('h1').innerHTML = 'Entire session has been closed.';
        });
    } else {
        connection.leave();
    }
};

// ......................................................
// ................FileSharing/TextChat Code.............
// ......................................................

document.getElementById('share-file').onclick = function() {
    var fileSelector = new FileSelector();
    fileSelector.selectSingleFile(function(file) {
        connection.send(file);
    });
};

document.getElementById('input-text-chat').onkeyup = function(e) {
    if (e.keyCode != 13) return;

    // removing trailing/leading whitespace
    this.value = this.value.replace(/^\s+|\s+$/g, '');
    if (!this.value.length) return;

    connection.send(this.value);
    appendDIV(this.value);
    this.value = '';
};

var chatContainer = document.querySelector('.chat-output');

function appendDIV(event) {
    var div = document.createElement('div');
    div.innerHTML = event.data || event;
    chatContainer.insertBefore(div, chatContainer.firstChild);
    div.tabIndex = 0;
    div.focus();

    document.getElementById('input-text-chat').focus();
}


// ......................................................
// ..................RTCMultiConnection Code.............
// ......................................................

var connection = new RTCMultiConnection();
connection.setCustomSocketHandler(XHRConnection);
connection.direction = 'one-way';
// by default, socket.io server is assumed to be deployed on your own URL
// connection.socketURL = '/';
connection.trickleIce = false;

// comment-out below line if you do not have your own socket.io server
// connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';

//connection.socketMessageEvent = 'audio-video-file-chat-demo';
connection.enableLogs = true;
connection.enableFileSharing = true; // by default, it is "false".

// this object is used to store "onmessage" callbacks from "openSignalingChannel handler
var onMessageCallbacks = {};

// this object is used to make sure identical messages are not used multiple times
var messagesReceived = {};

// overriding "openSignalingChannel handler
connection.openSignalingChannel = function (config) {

    console.log( 'called: openSignalingChannel' );
    var channel = config.channel || this.channel;
    onMessageCallbacks[channel] = config.onmessage;

    // let RTCMultiConnection know that server connection is opened!
    if (config.onopen) {
        console.log( 'Calling the config.open object' );
        setTimeout(config.onopen, 1);
    }
    else console.log( 'No config.open object' );

    // returning an object to RTCMultiConnection
    // so it can send data using "send" method
    return {
        send: function (data) {
            data = {
                channel: channel,
                message: data,
                sender: connection.userid
            };

            // posting data to server
            // data is also JSON-ified.
            xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
        },
        channel: channel
    };
};

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

connection.sdpConstraints.mandatory = {
    OfferToReceiveAudio: true,
    OfferToReceiveVideo: true
};

connection.videosContainer = document.getElementById('videos-container');
connection.onstream = function(event) {
    var width = parseInt(connection.videosContainer.clientWidth / 2) - 20;
    var mediaElement = getHTMLMediaElement(event.mediaElement, {
        title: event.userid,
        buttons: ['full-screen'],
        width: width,
        showOnMouseEnter: false
    });

    connection.videosContainer.appendChild(mediaElement);

    setTimeout(function() {
        mediaElement.media.play();
    }, 5000);

    mediaElement.id = event.streamid;
};

connection.onstreamended = function(event) {
    var mediaElement = document.getElementById(event.streamid);
    if (mediaElement) {
        mediaElement.parentNode.removeChild(mediaElement);
    }
};

connection.onmessage = appendDIV;
connection.filesContainer = document.getElementById('file-container');

connection.onopen = function() {
    console.log( "com. openend" );
    document.getElementById('share-file').disabled = false;
    document.getElementById('input-text-chat').disabled = false;
    document.getElementById('btn-leave-room').disabled = false;

    document.querySelector('h1').innerHTML = 'You are connected with: ' + connection.getAllParticipants().join(', ');
};

connection.onclose = function() {
    if (connection.getAllParticipants().length) {
        document.querySelector('h1').innerHTML = 'You are still connected with: ' + connection.getAllParticipants().join(', ');
    } else {
        document.querySelector('h1').innerHTML = 'Seems session has been closed or all participants left.';
    }
};

connection.onEntireSessionClosed = function(event) {
    document.getElementById('share-file').disabled = true;
    document.getElementById('input-text-chat').disabled = true;
    document.getElementById('btn-leave-room').disabled = true;

    document.getElementById('open-or-join-room').disabled = false;
    document.getElementById('open-room').disabled = false;
    document.getElementById('join-room').disabled = false;
    document.getElementById('room-id').disabled = false;

    connection.attachStreams.forEach(function(stream) {
        stream.stop();
    });

    // don't display alert for moderator
    if (connection.userid === event.userid) return;
    document.querySelector('h1').innerHTML = 'Entire session has been closed by the moderator: ' + event.userid;
};

connection.onUserIdAlreadyTaken = function(useridAlreadyTaken, yourNewUserId) {
    // seems room is already opened
    connection.join(useridAlreadyTaken);
};

function disableInputButtons() {
    document.getElementById('open-or-join-room').disabled = true;
    document.getElementById('open-room').disabled = true;
    document.getElementById('join-room').disabled = true;
    document.getElementById('room-id').disabled = true;
}

// ......................................................
// ......................Handling Room-ID................
// ......................................................

function showRoomURL(roomid) {
    var roomHashURL = '#' + roomid;
    var roomQueryStringURL = '?roomid=' + roomid;

    var html = '<h2>Unique URL for your room:</h2><br>';

    html += 'Hash URL: <a href="' + roomHashURL + '" target="_blank">' + roomHashURL + '</a>';
    html += '<br>';
    html += 'QueryString URL: <a href="' + roomQueryStringURL + '" target="_blank">' + roomQueryStringURL + '</a>';

    var roomURLsDiv = document.getElementById('room-urls');
    roomURLsDiv.innerHTML = html;

    roomURLsDiv.style.display = 'block';
}

(function() {
    var params = {},
        r = /([^&=]+)=?([^&]*)/g;

    function d(s) {
        return decodeURIComponent(s.replace(/\+/g, ' '));
    }
    var match, search = window.location.search;
    while (match = r.exec(search.substring(1)))
        params[d(match[1])] = d(match[2]);
    window.params = params;
})();

var roomid = '';
if (localStorage.getItem(connection.socketMessageEvent)) {
    roomid = localStorage.getItem(connection.socketMessageEvent);
} else {
    roomid = connection.token();
}
document.getElementById('room-id').value = roomid;
document.getElementById('room-id').onkeyup = function() {
    localStorage.setItem(connection.socketMessageEvent, this.value);
};

var hashString = location.hash.replace('#', '');
if (hashString.length && hashString.indexOf('comment-') == 0) {
    hashString = '';
}

var roomid = params.roomid;
if (!roomid && hashString.length) {
    roomid = hashString;
}

if (roomid && roomid.length) {
    document.getElementById('room-id').value = roomid;
    localStorage.setItem(connection.socketMessageEvent, roomid);

    // auto-join-room
    (function reCheckRoomPresence() {
        connection.checkPresence(roomid, function(isRoomExists) {
            if (isRoomExists) {
                connection.join(roomid);
                return;
            }

            setTimeout(reCheckRoomPresence, 5000);
        });
    })();

    disableInputButtons();
}
</script>

  <footer>
    <small id="send-message"></small>
  </footer>

  <script src="common.js"></script>
</body>
</html>

XHRConnection.js:

function XHRConnection(connection, connectCallback) {

    connection.socket = {
        send: function(data) {
            data = {
                message: data,
                sender: connection.userid
            };

            // posting data to server
            // data is also JSON-ified.
            xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
        }
    };


    // this object is used to make sure identical messages are not used multiple times
    var messagesReceived = {};

    function repeatedlyCheck() {
        xhr('xhr-signalhandler-get.php', function(data) {
            // if server says nothing; wait.
            if (data == false) return setTimeout(repeatedlyCheck, 400);

            // if already receied same message; skip.
            if (messagesReceived[data.ID]) return setTimeout(repeatedlyCheck, 400);
            messagesReceived[data.ID] = data.Message;

            // "Message" property is JSON-ified in "openSignalingChannel handler
            data = JSON.parse(data.Message);

            if (data.eventName === connection.socketMessageEvent) {
                onMessagesCallback(data.data);
            }

            if (data.eventName === 'presence') {
                data = data.data;
                if (data.userid === connection.userid) return;
                connection.onUserStatusChanged({
                    userid: data.userid,
                    status: data.isOnline === true ? 'online' : 'offline',
                    extra: connection.peers[data.userid] ? connection.peers[data.userid].extra : {}
                });
            }

            // repeatedly check the database
            setTimeout(repeatedlyCheck, 1);
        });
    }

    repeatedlyCheck();

    setTimeout
    (
        function() {

            if (connection.enableLogs) {
                console.info('XHR connection opened');
            }

            connection.socket.emit('presence', {
                userid: connection.userid,
                isOnline: true
            });

            if( connectCallback ) {
                console.log( 'Calling connectCallback...' );
                connectCallback(connection.socket);
                console.log( 'Done' );
            }
        }, 

        2000 
    );

    connection.socket.emit = function(eventName, data, callback) {
        if (eventName === 'changed-uuid') return;
        if (data.message && data.message.shiftedModerationControl) return;

        connection.socket.send({
            eventName: eventName,
            data: data
        });

        if (callback) {
            callback();
        }
    };

    var mPeer = connection.multiPeersHandler;

    function onMessagesCallback(message) {
        if (message.remoteUserId != connection.userid) return;

        if (connection.peers[message.sender] && connection.peers[message.sender].extra != message.extra) {
            connection.peers[message.sender].extra = message.extra;
            connection.onExtraDataUpdated({
                userid: message.sender,
                extra: message.extra
            });
        }

        if (message.message.streamSyncNeeded && connection.peers[message.sender]) {
            var stream = connection.streamEvents[message.message.streamid];
            if (!stream || !stream.stream) {
                return;
            }

            var action = message.message.action;

            if (action === 'ended' || action === 'stream-removed') {
                connection.onstreamended(stream);
                return;
            }

            var type = message.message.type != 'both' ? message.message.type : null;
            stream.stream[action](type);
            return;
        }

        if (message.message === 'connectWithAllParticipants') {
            if (connection.broadcasters.indexOf(message.sender) === -1) {
                connection.broadcasters.push(message.sender);
            }

            mPeer.onNegotiationNeeded({
                allParticipants: connection.getAllParticipants(message.sender)
            }, message.sender);
            return;
        }

        if (message.message === 'removeFromBroadcastersList') {
            if (connection.broadcasters.indexOf(message.sender) !== -1) {
                delete connection.broadcasters[connection.broadcasters.indexOf(message.sender)];
                connection.broadcasters = removeNullEntries(connection.broadcasters);
            }
            return;
        }

        if (message.message === 'dropPeerConnection') {
            connection.deletePeer(message.sender);
            return;
        }

        if (message.message.allParticipants) {
            if (message.message.allParticipants.indexOf(message.sender) === -1) {
                message.message.allParticipants.push(message.sender);
            }

            message.message.allParticipants.forEach(function(participant) {
                mPeer[!connection.peers[participant] ? 'createNewPeer' : 'renegotiatePeer'](participant, {
                    localPeerSdpConstraints: {
                        OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                        OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
                    },
                    remotePeerSdpConstraints: {
                        OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                        OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
                    },
                    isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
                    isDataOnly: isData(connection.session)
                });
            });
            return;
        }

        if (message.message.newParticipant) {
            if (message.message.newParticipant == connection.userid) return;
            if (!!connection.peers[message.message.newParticipant]) return;

            mPeer.createNewPeer(message.message.newParticipant, message.message.userPreferences || {
                localPeerSdpConstraints: {
                    OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                    OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
                },
                remotePeerSdpConstraints: {
                    OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                    OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
                },
                isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
                isDataOnly: isData(connection.session)
            });
            return;
        }

        if (message.message.readyForOffer || message.message.addMeAsBroadcaster) {
            connection.addNewBroadcaster(message.sender);
        }

        if (message.message.newParticipationRequest && message.sender !== connection.userid) {
            if (connection.peers[message.sender]) {
                connection.deletePeer(message.sender);
            }

            var userPreferences = {
                extra: message.extra || {},
                localPeerSdpConstraints: message.message.remotePeerSdpConstraints || {
                    OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                    OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
                },
                remotePeerSdpConstraints: message.message.localPeerSdpConstraints || {
                    OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
                    OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
                },
                isOneWay: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
                isDataOnly: typeof message.message.isDataOnly !== 'undefined' ? message.message.isDataOnly : isData(connection.session),
                dontGetRemoteStream: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
                dontAttachLocalStream: !!message.message.dontGetRemoteStream,
                connectionDescription: message,
                successCallback: function() {
                    // if its oneway----- todo: THIS SEEMS NOT IMPORTANT.
                    if (typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way') {
                        connection.addNewBroadcaster(message.sender, userPreferences);
                    }

                    if (!!connection.session.oneway || connection.direction === 'one-way' || isData(connection.session)) {
                        connection.addNewBroadcaster(message.sender, userPreferences);
                    }
                }
            };

            connection.onNewParticipant(message.sender, userPreferences);
            return;
        }

        if (message.message.shiftedModerationControl) {
            connection.onShiftedModerationControl(message.sender, message.message.broadcasters);
            return;
        }

        if (message.message.changedUUID) {
            if (connection.peers[message.message.oldUUID]) {
                connection.peers[message.message.newUUID] = connection.peers[message.message.oldUUID];
                delete connection.peers[message.message.oldUUID];
            }
        }

        if (message.message.userLeft) {
            mPeer.onUserLeft(message.sender);

            if (!!message.message.autoCloseEntireSession) {
                connection.leave();
            }

            return;
        }

        mPeer.addNegotiatedMessage(message.message, message.sender);
    }

    window.addEventListener('beforeunload', function() {
        connection.socket.emit('presence', {
            userid: connection.userid,
            isOnline: false
        });
    }, false);
}


// a simple function to make XMLHttpRequests
function xhr( url, callback, data ) {

    // if( data ) console.log('[' + url + '] sending: ' + JSON.stringify( data ) );

    if (!window.XMLHttpRequest || !window.JSON){
        console.log( 'No JSON and/or XMLHttpRequest support' );
        return;
    }

    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (callback && request.readyState == 4 && request.status == 200) {
            // server MUST return JSON text

            if( request.responseText != 'false' )
                console.log('Logging non-false data [from ' + url + ']: ' + request.responseText + "[...data POST'ed: " + JSON.stringify( data ) + "]" );

            callback(JSON.parse(request.responseText));
        }
    };

    request.open( 'POST', url );
    var formData = new FormData();

    // you're passing "message" parameter
    formData.append( 'message', data );
    request.send(formData);
}

start-broadcast.php:

<?php
require( "connection.inc.php" );

if( isset( $_POST['message'] ) )
{
    $data = json_decode( $_POST['message'] , true );
    // Now, if someone initiates WebRTC session; you should make an XHR request to create a record in the room-table; and 
    // set "Owner-id" equals to that user's "user-id".

    //{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}

    $query = " INSERT INTO active_broadcasts ( name ) VALUES ( '{$data['name']}' ) ";

    if( $mysqli->query( $query ) )
    {
        $transport = json_encode( false );
        exit( $transport );
    }
    else
        exit( $mysqli->error );
}
else
    exit( 'No data sent' );
?>

xhr-signalhandler-post.php:

<?php
require( "connection.inc.php" );

$response = array();

//{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}

// var_dump( $_POST );
// exit;

if( isset( $_POST['message'] ) )
{
    $query = " INSERT INTO webrtc-messages ( name ) VALUES ( '{$_POST['name']}' ) ";

    if( $mysqli->query( $query ) )
    {
        $transport = json_encode( false );
        exit( $transport );
    }
    else
        exit( $mysqli->error );

    // Now, if someone else joins the room; you can update above record; and append his "user-id" in the "Participants-id" column.
}


if( @$_POST["message"] = "undefined" )
    $response = false;

$transport = json_encode( $response );
exit( $transport );

?>

xhr-signalhandler-get.php:

<?php
require( "connection.inc.php" );
$response = array();

// var_dump( $_POST );

if( isset( $_POST['message'] ) )
{
    $query = "SELECT id , message , channel , `sender-id` FROM `webrtc-messages` ";

    if( $mysqli->connect_errno )
        exit ( "Failed to connect to MySQL: " . $mysqli->connect_error );

    if( $res = $mysqli->query( $query ) )
    {
        if( $res->num_rows > 0 )
        {
            while( $value = mysqli_fetch_assoc( $res ) )
            {   
                //
            }
        }
    }
    else
    {
        echo "<center class='text-danger'>Server error</center>";
        exit( $mysqli->error );
    }
}

if( @$_POST["message"] = "undefined" )
    $response = false;

$transport = json_encode( $response );
exit( $transport );
?>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Damilola Olowookere
  • 2,253
  • 2
  • 23
  • 33
  • Did you test this demo? (using SSE over PHP i.e. server sent events): https://rtcmulticonnection.herokuapp.com/demos/SSEConnection.html – Muaz Khan Aug 23 '17 at 18:00
  • @MuazKhan two things needs clarification in the link you provided. 1. Can I use this SSEConnection with the RTCMultiConnection project? (I mean to use it as the signaling server for RTCMultiConnection.js, even as it is localhost) 2. In the source-code you posted for `https://github.com/muaz-khan/RTCMultiConnection/tree/master/demos/SSEConnection`, you said *replace sseDirPath with sseDirPath='https://php-server.com/SSEConnection/'*. Does this not violate the requirement that this project is on localhost, because I believe the domain will need to resolve to the internet? – Damilola Olowookere Aug 23 '17 at 19:32
  • SSEConnection demo is using version 3 of the RTCMultiConnection.js (i.e. latest version). You can upload HTML-demo file in the same directory of "SSE.php" file; meaning that you don't need to set CORS link. Everything (JS+SSE+HTML) will be served by same directory+domain. (so localhost should run PHP to make it work) – Muaz Khan Aug 24 '17 at 01:44
  • @MuazKhan but since the value for `sseDirPath` is an external domain (i.e. php-server.com/SSEConnection/), it means it requires internet at that point, right? Or I just set `sseDirPath = null` because it is on localhost? – Damilola Olowookere Aug 24 '17 at 13:52
  • XHR-signaling (your codes above) also requires PHP. XHR means you publish and retries messages from MySQL/PHP. So you always need a PHP script. SSE also requires PHP whether it is on localhost or on a remote server. You can download SSE.php on localhost and set this: `sseDirPath=http://localhost:9001/demos/SSEConection/SSE.php` – Muaz Khan Aug 25 '17 at 02:23
  • @Muaz Khan I have PHP setup on my localhost. Can you please run the 3 scripts I provided above so that you will understand the situation for the XHR-signaling? (*start-broadcast.php*, *xhr-signalhandler-post.php*, and *xhr-signalhandler-get.php* are all PHP scripts that run on my localhost PHP via Ajax, as shown in the code posted above) – Damilola Olowookere Aug 25 '17 at 12:40

1 Answers1

2

I've never played with WebRTC nor RTCMultiConnection but I think I understand where your problem comes from.

As you're using XHR, there is no direct connection between your client (web browser) and your server. So, there is no way for the server to push information to the client thus, the openSignalingChannel override will never be triggered.

The trick is to call a function on a regular basis to check the server status (aka. long polling).

If you check the documentation of RTCMultiConnection about the openSignalingChannel override ( http://www.rtcmulticonnection.org/docs/openSignalingChannel/#xhr-signaling ), you'll notice the use of repeatedlyCheck();. I think this is the missing piece of your puzzle.

Hope it helps.

Booster2ooo
  • 1,373
  • 9
  • 11
  • That is what `repeatedlyCheck()` is doing in the *XHRConnection.js* file that I posted with the question. I think it is something that has to do with the underlying `RTCMultiConnection.js` script itself, because that seems to be the only script that has a reference to `openSignalingChannel()` – Damilola Olowookere Aug 20 '17 at 18:46
  • @OlowookereEmmanuel indeed, sorry, I didn't pay enought attention to your implementation. I must admit I played a little with your sample, mocking the response of *xhr-signalhandler-get.php* as I don't have access to the whole project but I didn't succeed in entering `openSignalingChannel()`. One thing I notice thought is a difference in using `onMessageCallbacks`, the author creates a property for each channel: `onMessageCallbacks[data.channel]` but the function body is assigned inside `openSignalingChannel()` (`onMessageCallbacks[channel] = config.onmessage;`). – Booster2ooo Aug 21 '17 at 14:22
  • I really wish this project works. It just seems impossible! – Damilola Olowookere Aug 22 '17 at 13:10
  • Hey man I am too am stuck with php/sql implementation did you solved it??? – gp el Feb 20 '18 at 10:43
  • No bro. I have suspended work on the concerned project. However, I will advice that you use the [GitHub page](https://github.com/muaz-khan/RTCMultiConnection) - contributors seems to have now increased and thus the rate of resolving issues has improved. – Damilola Olowookere Feb 08 '19 at 14:04