Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOMException: Failed to set local answer sdp: Called in wrong state: kStable #8

Open
meghq opened this issue Sep 26, 2018 · 9 comments

Comments

@meghq
Copy link

meghq commented Sep 26, 2018

I am trying to run the webRTC code which i have mentioned below, it is working fine when i am connecting with two devices using same network. But it is not connecting when the devices are in different networks and i am getting DOM Exception. please help me to fix it.

// Generate random room name if needed
if (!location.hash) {
location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16);
}
const roomHash = location.hash.substring(1);

// TODO: Replace with your own channel ID
const drone = new ScaleDrone('yiS12Ts5RdNhebyM');
// Room name needs to be prefixed with 'observable-'
const roomName = 'observable-' + roomHash;
const configuration = {
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
};
let room;
let pc;

function onSuccess() {};
function onError(error) {
console.error(error);
};

drone.on('open', error => {
if (error) {
return console.error(error);
}
room = drone.subscribe(roomName);
room.on('open', error => {
if (error) {
onError(error);
}
});
// We're connected to the room and received an array of 'members'
// connected to the room (including us). Signaling server is ready.
room.on('members', members => {
console.log('MEMBERS', members);
// If we are the second user to connect to the room we will be creating the offer
const isOfferer = members.length === 2;
startWebRTC(isOfferer);
});
});

// Send signaling data via Scaledrone
function sendMessage(message) {
drone.publish({
room: roomName,
message
});
}

function startWebRTC(isOfferer) {
pc = new RTCPeerConnection(configuration);

// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
pc.onicecandidate = event => {
if (event.candidate) {
sendMessage({'candidate': event.candidate});
}
};

// If user is offerer let the 'negotiationneeded' event create the offer
if (isOfferer) {
pc.onnegotiationneeded = () => {
pc.createOffer().then(localDescCreated).catch(onError);
}
}

// When a remote stream arrives display it in the #remoteVideo element
pc.ontrack = event => {
const stream = event.streams[0];
if (!remoteVideo.srcObject || remoteVideo.srcObject.id !== stream.id) {
remoteVideo.srcObject = stream;
}
};

navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
}).then(stream => {
// Display your local video in #localVideo element
localVideo.srcObject = stream;
// Add your stream to be sent to the conneting peer
stream.getTracks().forEach(track => pc.addTrack(track, stream));
}, onError);

// Listen to signaling data from Scaledrone
room.on('data', (message, client) => {
// Message was sent by us
if (client.id === drone.clientId) {
return;
}

if (message.sdp) {
  // This is called after receiving an offer or answer from another peer
  pc.setRemoteDescription(new RTCSessionDescription(message.sdp), () => {
    // When receiving an offer lets answer it
    if (pc.remoteDescription.type === 'offer') {
      pc.createAnswer().then(localDescCreated).catch(onError);
    }
  }, onError);
} else if (message.candidate) {
  // Add the new ICE candidate to our connections remote description
  pc.addIceCandidate(
    new RTCIceCandidate(message.candidate), onSuccess, onError
  );
}

});
}

function localDescCreated(desc) {
pc.setLocalDescription(
desc,
() => sendMessage({'sdp': pc.localDescription}),
onError
);
}

@Pierre-Demessence
Copy link

Hello,

As far as I know, the issues comes from Chrome Desktop who's sending the request twice.
Using another browser fixed the issue for me.

@kirusiya
Copy link

kirusiya commented Dec 3, 2018

i have same problem, how con i fixed

@AlekRuzic
Copy link

I currently have the exact same problem, I'll try using a different browser when I get a chance to test across different networks again

@rawars
Copy link

rawars commented Apr 15, 2020

Dude, I had the same problem and you can fix it by deploying the signaling server on port 8080.

Also I had to add these iceServers:

const config = {
  'iceServers': [
      { url: 'stun:stun1.l.google.com:19302' },
      {
          url: 'turn:numb.viagenie.ca',
          credential: 'muazkh',
          username: 'webrtc@live.com'
      }
  ]
}
const peerConnection = new RTCPeerConnection(config);

I managed to deploy with the fixes on an amazon server.

@rsingh2083
Copy link

@rawars How do I deploy it on port 8080 ? Where is the option to change port ?
Im running on my localhost desktop and trying to connect to it from laptop.

@DanielNogueraDevelopment

Going to port 8080 worked for me!

@rawars
Copy link

rawars commented May 24, 2020

Hello, for those who still do not work even changing the port to 8080, it is because they need to go through the configuration, the ice servers:

const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]}
const peerConnection = new RTCPeerConnection(configuration);

@sehdev
Copy link

sehdev commented Jun 10, 2020

@rawars how to deploy signaling server on port 8080?

@rawars
Copy link

rawars commented Jun 16, 2020

@rawars how to deploy signaling server on port 8080?

In Amazon lightsail:

const express = require('express');
const socketIO = require('socket.io');

const http = require('http');
const https = require('https');
const path = require('path');
const fs = require('fs');

var PatientsSockets = [];
var DoctorsSockets = [];

const DEFAULT_PORT = 8080;

const app = express()

var Server = null;

Server = https.createServer({
    key: fs.readFileSync('/etc/letsencrypt/live/domain.com/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/domain.com/fullchain.pem'),
}, app);

var io = socketIO(Server);

app.use(express.static(path.join(__dirname, "public")));

io.on("connection", socket => {

    socket.on("new-paciente", (data) => {
        const existingSocket = PatientsSockets.find(existingSocket => existingSocket.socket === socket.id);
        if (!existingSocket) {

            PatientsSockets.push({
                names: data.names,
                surnames: data.surnames,
                socket: socket.id,
                role: 'PATIENT'
            });
            socket.broadcast.emit("update-list-patients", {
                patients: PatientsSockets
            });

        }
    });

    socket.on("new-doctor", (data) => {
        const existingSocket = DoctorsSockets.find(existingSocket => existingSocket.socket === socket.id);
        if (!existingSocket) {
            DoctorsSockets.push({
                socket: socket.id,
                role: 'DOCTOR'
            });
        }
    });

    socket.on("make-answer", data => {
        socket.to(data.to).emit("answer-made", {
            socket: socket.id,
            answer: data.answer
        });
    });

    socket.on("call-patient", (data) => {
        socket.to(data.to).emit("notify-call", {
            offer: data.offer,
            socket: socket.id
        });
    });

    socket.on("load-patients", (data) => {
        socket.emit("update-list-patients", {
            patients: PatientsSockets
        });
    });

    socket.on("disconnect", () => {
        PatientsSockets = PatientsSockets.filter(existingSocket => existingSocket.socket !== socket.id);
        socket.broadcast.emit("remove-user", {
            disconnected: socket.id,
            patients: PatientsSockets
        });
    });
});

Server.listen(DEFAULT_PORT, () => {
    console.log('HTTPS Server running on port ' + DEFAULT_PORT);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants