simple-peer: "Cannot set remote answer in state stable"

Hi. I switched from native WebRTC to Simple Peer, hoping a library would already control webRTC’s pretty fragile state machines.

I am developing an app for online conferencing and need to heavily connect, disconnect and reconnect various peers.

connection works flawlessly on first attempt. After closing the connection and trying to reconnect, I get the error Cannot set remote answer in state stable in latest Firefox, or DOMException: Failed to set remote answer sdp: Called in wrong state: kStable in latest chrome (chromium)

That behavior is quite annoying. I am looking for a way to control peers. Disconnecting should really disconnect peers from each other without any leftovers. It looks like the ICE-Servers are still expecting the peers to have a stable connection still?

When a connection is closed I call peer.destroy() and null my peer-object. I hoped that is enough to completely clean up, but WebRTC (or rather the ICE magic) is not really behaving deterministic.

here are some code snippets:

//connects to a client
//target: ID in OpenSlides
//offer: bool. should be true if initial
function connectToClient(target, offer, video) {
    var peer = registerClient(target, offer, video);
    var doSendVideo = false;
    if (video) {
        doSendVideo = true;
    }
    peer.on('signal', function (data) {
        // this is sending the given JSON to target over a python server
        Notify.notify("signalling", {
            id: operator.user.id,
            signal: data,
            video: doSendVideo,
        }, [target]);
    });
    return peer;
}
//registers a new client
//returns a client if already exists
function registerClient(id, initiator, video) {
    console.log('registerClient: ', clients);
    var peerConfig = {
        initiator: initiator,
        stream: video,
        tickle: true,
        reconnectTimer: 2000,
        iceTransportPolicy: 'relay',
    };

    if (clients[id] === undefined) {
        clients[id] = {};
    }
    if (clients[id].history === undefined) {
        clients[id].history = [];
    }
    if (clients[id].peer === undefined) {
        clients[id].peer = new SimplePeer(peerConfig);
        setupPeer(clients[id].peer); //this is just setting up the peer.on('xxx')-stuff 
    }
    return clients[id].peer;
}

this will be executed on the other peer. Ignore video for now

var signallingCallback = Notify.registerCallback("signalling" , function (notify) {
    if (!notify.sendBySelf) {
        var clientInfo = notify.params;

        if (clientInfo.video) {
            getMediaClient(clientInfo.id, false).then( function (peer) {
                console.log('getMedieClient, peer, video: ' , peer);
                peer.signal(clientInfo.signal);
            });
        } else {
            var peer = connectToClient(clientInfo.id, false, false);
            peer.signal(clientInfo.signal);
        }
    }
});

I hope somebody can help me or suggest something.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (1 by maintainers)

Most upvoted comments

That fiddle works fine for me. Can you try this modified one and post the console log?

https://jsfiddle.net/h1y7khk6/2/

You call connectToClient once at the beginning and then each time you receive signal event. In connectToClient however you subscribe to signal event. Hence, for each signal event dispatched by simple-peer you’ll get multiple notify->peer.signal calls, which in turn causes issues.

Separate instance creation from getting existing instance and it should be fine.

I don’t see peer.destroy() in snippet above. I only see clients[id].peer === undefined, which indicates that you’re trying to use the same connection again even after it was destroyed.

In one of my projects simple-peer opens and closes a lot of connections (hundreds to thousands) without issues.

Make sure you don’t reuse instance after destruction and it will work fine.