-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
86 lines (63 loc) · 2.36 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const { RTCPeerConnection, RTCIceCandidate } = require('get-webrtc')
const Protomux = require('protomux')
const c = require('compact-encoding')
const safetyCatch = require('safety-catch')
const WebStream = require('./lib/web-stream.js')
// TODO: Investigate how to deploy STUN servers
const ICES = [
{ urls: 'stun:stun.l.google.com:19302' }
]
module.exports = class WebPeer {
constructor (relay, opts = {}) {
this._rtc = new RTCPeerConnection({ iceServers: opts.iceServers || ICES })
this._relay = relay
this._mux = Protomux.from(relay)
this._channel = this._mux.createChannel({ protocol: 'hyper-webrtc/signal' })
if (this._channel === null) throw new Error('Channel duplicated')
this._ice = this._channel.addMessage({ encoding: c.json, onmessage: this._onice.bind(this) })
this._offer = this._channel.addMessage({ encoding: c.json, onmessage: this._onoffer.bind(this) })
this._answer = this._channel.addMessage({ encoding: c.json, onmessage: this._onanswer.bind(this) })
this._channel.open()
this._rtc.onicecandidate = onicecandidate.bind(this)
}
static from (relay) {
const peer = new this(relay)
const rawStream = peer._rtc.createDataChannel('wire', { negotiated: true, id: 0 })
const stream = new WebStream(relay.isInitiator, rawStream, {
publicKey: relay.publicKey,
remotePublicKey: relay.remotePublicKey,
handshakeHash: relay.handshakeHash
})
relay.on('close', () => {
peer._rtc.close()
rawStream.close()
})
stream.on('close', () => {
peer._rtc.close()
relay.destroy()
})
peer.negotiate().catch(safetyCatch)
return stream
}
async negotiate () {
if (!this._relay.isInitiator) return
const offer = await this._rtc.createOffer()
await this._rtc.setLocalDescription(offer)
this._offer.send({ offer: this._rtc.localDescription })
}
async _onice ({ ice }) {
await this._rtc.addIceCandidate(new RTCIceCandidate(ice))
}
async _onoffer ({ offer }) {
await this._rtc.setRemoteDescription(offer)
const answer = await this._rtc.createAnswer()
await this._rtc.setLocalDescription(answer)
this._answer.send({ answer: this._rtc.localDescription })
}
async _onanswer ({ answer }) {
await this._rtc.setRemoteDescription(answer)
}
}
function onicecandidate (e) {
if (e.candidate) this._ice.send({ ice: e.candidate })
}