4

I am creating a small WebRTC app that for now used to exchange text message. I have got the WebRTC connection working but Datachannel always remains in "connecting" state and never goes to "Open".

Please tell me what I am missing here.

Following is the JS.

socket.onmessage = function(e){
            console.log("Message from signaling server");
                writeToScreen('<span class="server">Server: </span>'+e.data);
                var data = JSON.parse(e.data);
    switch(data.type) {
    case "login":
    onLogin(data.success);
    break;
    case "offer":
    onOffer(data.offer, data.name);
    break;
    case "answer":
    onAnswer(data.answer);
    break;
    case "candidate":
    onCandidate(data.candidate);
    break;
    default:
    break;
}


            }
            // Enable send and close button
            $('#send').prop('disabled', false);
            $('#close').prop('disabled', false);
            $('#connect').prop('disabled', true);
        }
        function close(){
            socket.close();
        }
        function writeToScreen(msg){
            var screen = $('#screen');
            screen.append('<p>'+msg+'</p>');
            screen.animate({scrollTop: screen.height()}, 10);
        }
        function clearScreen(){
            $('#screen').html('');
        }
        function sendMessage(){
            if(!socket || socket == undefined) return false;
            var mess = $.trim($('#message').val());
            if(mess == '') return;
            writeToScreen('<span class="client">Client: </span>'+mess);
            socket.send(mess);
            // Clear input
            $('#message').val('');
        }
        $(document).ready(function(){
            $('#message').focus();
            $('#frmInput').submit(function(){
                sendMessage();
            });
            $('#connect').click(function(){
                connect();
            });
            $('#close').click(function(){
                close();
            });
            $('#clear').click(function(){
                clearScreen();
            });
        });

        if (!window.RTCPeerConnection) {
    window.RTCPeerConnection = window.webkitRTCPeerConnection;
}

var configuration = {
  "iceServers": [
  {
    "urls": "stun:mmt-stun.verkstad.net"
  },
  {
    "urls": "turn:mmt-turn.verkstad.net",
    "username": "webrtc",
    "credential": "secret"
  }
  ]
};


myConnection = new RTCPeerConnection(configuration,{optional:[{RtpDataChannels: true},{DtlsSrtpKeyAgreement: true}]});

                console.log("RTCPeerConnection object was created");
                console.log(myConnection);  
                openDataChannel();

                //when the browser finds an ice candidate we send it to another peer

                myConnection.onicecandidate = function (event) {
                console.log(event.candidate);
                if (event.candidate) {
                    send({
                    type: "candidate",
                    candidate: event.candidate
                    });
                    }
                };  


// Datachannel

    var mediaConstraints = {
        'offerToReceiveAudio': 1,
        'offerToReceiveVideo': 1
    };


   var connectToOtherUsernameBtn =  document.getElementById("connectToOtherUsernameBtn");   
        console.log(connectToOtherUsernameBtn);

        connectToOtherUsernameBtn.addEventListener("click", function () {
        console.log("ice state : "+myConnection.iceGatheringState);
var otherUsername = connectToOtherUsernameBtn.value;
connectedUser = otherUsername;
        if (otherUsername.length > 0) {
        //make an offer

        myConnection.createOffer(function (offer) {
        send({
        type: "offer",
        offer: offer
        });
        console.log(offer);
        console.log(typeof(offer));
        myConnection.setLocalDescription(offer);
        console.log("localDescription");
        console.log(myConnection.localDescription);
        }, function (error) {
        alert("An error has occurred.");
        console.log(error);
        });
        }
        });


function send(message) {
if (connectedUser) {
message.name = connectedUser;
 }
socket.send(JSON.stringify(message));
};

//when somebody wants to call us
function onOffer(offer, name) {
console.log("offer recieved");
connectedUser = name;
 myConnection.setRemoteDescription(new RTCSessionDescription(offer));
 myConnection.createAnswer(function (answer) {
 myConnection.setLocalDescription(answer);
 send({
 type: "answer",
 answer: answer
 });
 }, function (error) {
 alert("oops...error");
 console.log(error);
 });
  console.log("Answer sent");
}

//when another user answers to our offer
function onAnswer(answer) {
console.log("answer recieved");
myConnection.setRemoteDescription(new RTCSessionDescription(answer));
console.log(myConnection.iceConnectionState );
}
//when we got ice candidate from another user
function onCandidate(candidate) {
myConnection.addIceCandidate(new RTCIceCandidate(candidate));
}


}); 

//data channel

//creating data channel
function openDataChannel() {
console.log("opening Data Channel");
var dataChannelOptions = {
reliable:true,
};
dataChannel = myConnection.createDataChannel("myDataChannel",dataChannelOptions);

 dataChannel.onerror = function (error) {
 console.log("Error:", error);
 };
 dataChannel.onmessage = function (event) {
 console.log("Got message:", event.data);
 };
}



function sendmsg() {
console.log("send message");
var msgInput=document.getElementById("msgInput");
var val = msgInput.value;
console.log(val);
 dataChannel.send(val);
}




function checkstatus(){
console.log("Checking Status");
console.log("signalingState: "+myConnection.signalingState);
console.log("iceConnectionState: "+myConnection.iceConnectionState);
console.log("iceGatheringState: "+myConnection.iceGatheringState);
console.log("localDescription: ");
console.log(myConnection.localDescription);
console.log("remoteDescription:");
console.log(myConnection.remoteDescription);
console.log("Connestion id");
console.log(dataChannel.id);
console.log("Connestion readyState");
console.log(dataChannel.readyState);
}

Following is the console log from chrome. enter image description here

user2288650
  • 412
  • 1
  • 6
  • 23

2 Answers2

2

remove {RtpDataChannels: true} try again and if it works burn the tutorial or book which recommended those "rtp data channels". They are broken.

Philipp Hancke
  • 15,855
  • 2
  • 23
  • 31
  • Yeahh tutorials aren't clear enough. I figured out the problem. I had to use RTCPeerconnection.onDatachannel method to capture the Datachannel on the client to which the offer was made and get the Datachannel using "event.channel". I am not sure how right I am but its working now. – user2288650 Jan 21 '17 at 00:27
  • I still have loads of questions on how to make WebRTC robust. Many times the connections will not work and I get error " DOM exception: Error in procession icecandidates". Other times things work without any issue. – user2288650 Jan 21 '17 at 00:30
  • Please ask a new question rather than adding to an existing question – Mikkel Jan 21 '17 at 02:26
  • I have same problem i don't have RtpDataChannels defined in my config. but datachannel is still in connecting state. – Cozdemir Oct 26 '19 at 17:17
2

I had the same problem. my code was working fine on mozilla using localhost signalling server without internet but on chrome i had this problem. Its Trickle ICE problem. one solution is you may set trickle ice off.

In chrome, may be you need the internet connection to gather the all possible ICE candidates. because in Chrome Datachannel will not get opened untill peer get all possible ICE candidates.

you can try the following link with internet or without internet. you will have brief idea. https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/

for further information you can check this https://webrtcstandards.info/webrtc-trickle-ice/

  • hey! Do you know how to disable trickle ice? Can't find any info on this. – manidos Dec 18 '17 at 12:39
  • Hoi you may use this Webrtc api https://www.npmjs.com/package/simple-peer. or you can refer the ice candidate enable disable code. this is further info to see how ice candidate works. https://webrtchacks.com/trickle-ice/ – Dhaval Shekhada Feb 07 '18 at 15:43