Skip to content
Snippets Groups Projects
WebRTC.js 2.69 KiB
Newer Older
import AbstractConnection from "./Connection.js"

import LioWebRTC from "liowebrtc"

export default class WebRTCConnection extends AbstractConnection {
  constructor(options) {
    super(options)

    this.webrtc = new LioWebRTC({
      url: this.options.url,
      dataOnly: true,
      constraints: {
        minPeers: this.options.mesh.minPeers,
        maxPeers: this.options.mesh.maxPeers,
      },
    })

    this.webrtc.on("ready", () => {
      this.webrtc.joinRoom(this.options.room)
    })

    this.webrtc.on("joinedRoom", () => {
      this.dispatchEvent(new CustomEvent("roomJoined"))
    })

    this.webrtc.on("leftRoom", () => {
      this.dispatchEvent(new CustomEvent("roomLeft"))
    })

    this.webrtc.on("channelOpen", (dataChannel, peer) => {
      this.dispatchEvent(new CustomEvent("channelOpened", { detail: peer.id }))
    })

    this.webrtc.on("channelError", (dataChannel, peer) => {
      this.dispatchEvent(new CustomEvent("channelError", { detail: peer.id }))
    })

    this.webrtc.on("channelClose", (dataChannel, peer) => {
      this.dispatchEvent(new CustomEvent("channelClosed", { detail: peer.id }))
    })

    this.webrtc.on("receivedPeerData", (channel, message, peer) => {
      // Message could have been forwarded but interface only needs to know about directly connected peers
      this.dispatchEvent(
        new CustomEvent("messageReceived", {
          detail: {
            uid: peer.forwardedBy ? peer.forwardedBy.id : peer.id,
            channel,
            message,
          },
        }),
      )
    })
  }

  getUserID() {
    return this.webrtc.getMyId()
  }

  getPeerHandle(uid) {
    return this.webrtc.getPeerById(uid)
  }

  getPeerFootprint(uid) {
    const peer = this.webrtc.getPeerById(uid)

    if (!peer) return Promise.reject()

    return new Promise(function(resolve, reject) {
      peer.getStats(null).then((stats) => {
        let footprint = -1

        stats.forEach((report) => {
          if (
            report.type == "candidate-pair" &&
            report.bytesSent > 0 &&
            report.bytesReceived > 0 &&
            report.writable
          ) {
            footprint = Math.max(footprint, report.bytesReceived)
          }
        })

        if (footprint != -1) {
          resolve(footprint)
        } else {
          reject()
        }
      })
    })
  }

  send(uid, channel, message) {
    const peer = this.webrtc.getPeerById(uid)

    if (!peer) return

    this.webrtc.whisper(peer, channel, message)
  }

  broadcast(channel, message) {
    this.webrtc.shout(channel, message)
  }

  terminatePeer(uid) {
    const peer = this.webrtc.getPeerById(uid)

    if (!peer) return

    peer.end()
  }

  destructor() {
    this.webrtc.quit()
  }
}