peers / peerjs

Simple peer-to-peer with WebRTC.
https://peerjs.com
MIT License
12.48k stars 1.43k forks source link

Peer & MediaConnection Leak using React/Redux #392

Closed leroy-p closed 5 years ago

leroy-p commented 7 years ago

Hi, I'm using Peer.js in my application, built with React/Redux (single page application). I want the user to be able to establish several video connections in a row without refreshing the page. Although, it leads to a memory leak since MediaConnection, RTCPeerConnection and Peer instances are not getting deleted after each video connections ends. I tried to delete them myself on "disconnected" event using MediaConnection.close() and Peer.destroy() but it does not clean them up. I can see them alive using the memory tab in Chrome developer tools.

Here is my code :

  this.listenForClient = function (localStream) {
    let that = this;
    this.peer = new Peer(this.peerId, { host: "peerjs-server.simbiozprod.com", port: 9000, secure: true });
    this.peer.on("call", mediaConnection => {
      that.mediaConnection = mediaConnection;
      // If we receive a call while already connected, ignore it
      if (that.status === Status.CONNECTED) return;

      // Initialize the remote video view when we receive a data stream from the client
      that.mediaConnection.on("stream", remoteStream => that.didConnect(remoteStream));

      // If the connection is closed, start listening for incoming calls again
      that.mediaConnection.on("close", () => that.didDisconnect(localStream));
      that.mediaConnection.on("disconnected", () => that.didDisconnect(localStream));

      // Try answering (only consider that we're connected when we receive the actual stream)
      that.mediaConnection.answer(localStream);
      Log.info("MediaConnection: Answering the client...");
    });
  };

  this.connectToServer = function (localStream) {
    let that = this;

    // If we're already connected to a server, do not try to connect again
    if (this.status === Status.CONNECTED) return;

    this.peer = new Peer({ host: "peerjs-server.simbiozprod.com", port: 9000, secure: true });

    // Call the server with our local stream
    this.mediaConnection = this.peer.call(this.peerId, localStream);
    Log.info("MediaConnection: Calling the server...");

    // Initialize the remote video view when we receive a data stream from the server.
    // We can also assume that we've connected successfully from this point on.
    this.mediaConnection.on("stream", remoteStream => that.didConnect(remoteStream));
    this.mediaConnection.on("close", () => that.didDisconnect(localStream));
    this.mediaConnection.on("disconnected", () => that.didDisconnect(localStream));
  };

  this.didConnect = function (remoteStream) {
    setStatus(Status.CONNECTED);
    this.emit("remoteStream", remoteStream);
    Log.info("MediaConnection: Connected!");
  };

  this.didDisconnect = function (localStream) {
    let tracks = localStream.getTracks();
    tracks.forEach((track) => {
      track.stop();
    });

    this.emit("disconnected");
    this.mediaConnection.close();
    delete this.mediaConnection;
    this.close();
    setStatus(Status.READY_TO_CONNECT);
  };

  this.close = function() {
    if (this.peer) {
      this.peer.destroy();
      delete this.peer;
    }
  };

Do you have any suggestion ?

Thank you for your Help. Etienne

afrokick commented 5 years ago

You should use .off method to unsubscribe from mediaConnection, dataConnection and peer