322:7dfdf32e8577
Anton Shestakov <av6@dwimlabs.net>, Sat, 14 Jul 2018 20:23:13 +0800
index: authorizing contact also adds it to the roster Maybe there are cases when this doesn't make sense, but so far this looks like the right thing to do.

next change 327:14066d6ee9ac
previous change 317:d7821033e3c0

coffee/webrtc.coffee

Permissions: -rw-r--r--

Other formats: Feeds:
class Tram.WebRTCInterface
lstream: null
rstream: null
constructor: (@contact) ->
@peerJid = @contact.get('jid')
init: (@initiator, constraints) ->
if constraints.audio || constraints.video
navigator.getUserMedia(constraints, @connect, @fail)
else
@connect()
connect: (stream) =>
@call = calls.add(jid: @peerJid, contact: @contact)
@pc = new RTCPeerConnection(iceServers: Tram.config.iceServers)
if stream?
@lstream = stream
@pc.addStream(stream)
@call.set('local/stream', stream)
@pc.onicecandidate = (event) =>
if event.candidate
@sendPayload(event.candidate, 'ice')
@pc.onaddstream = (event) =>
@rstream = event.stream
@call.set('remote/stream', event.stream)
@contact.set('callstate', 'established')
if @initiator
@sendIntent('initiate')
else
@createOffer()
onPayload: (stanza) ->
if not @call?
return
el = stanza.getElementsByTagNameNS(Tram.NS.WEBRTC, 'payload')[0]
signal = JSON.parse(el.firstChild.nodeValue)
if signal.sdp
if signal.type is 'offer'
@receiveOffer(signal)
else if signal.type is 'answer'
@receiveAnswer(signal)
else if signal.candidate
@pc.addIceCandidate(new RTCIceCandidate(signal))
sendPayload: (data, type) ->
payload = JSON.stringify(data)
msg = $msg(to: @peerJid, type: 'chat')
.c('payload', xmlns: Tram.NS.WEBRTC, type: type).t(payload)
X.conn.send(msg.tree())
sendIntent: (intent) ->
msg = $msg(to: @peerJid, type: 'chat')
.c('intent', xmlns: Tram.NS.WEBRTC).t(intent)
X.conn.send(msg.tree())
createOffer: ->
@pc.createOffer((offer) =>
@pc.setLocalDescription(offer, =>
@sendPayload(@pc.localDescription, 'offer')
, @fail)
, @fail)
receiveOffer: (offer) ->
@pc.setRemoteDescription(new RTCSessionDescription(offer), =>
@pc.createAnswer((answer) =>
@pc.setLocalDescription(answer, =>
@sendPayload(@pc.localDescription, 'answer')
, @fail)
, @fail)
, @fail)
receiveAnswer: (answer) ->
@pc.setRemoteDescription(new RTCSessionDescription(answer))
fail: =>
@disconnect()
@contact.unset('callstate')
disconnect: ->
if @call?
@call.unset('remote/stream')
@call.unset('local/stream')
calls.remove(@call)
if @rstream?
@stopStream(@rstream)
#@pc?.removeStream?(@rstream)
if @lstream?
@stopStream(@lstream)
#@pc?.removeStream?(@lstream)
if @pc?
@pc.close()
@pc = null
stopStream: (stream) ->
if stream.getAudioTracks?
for track in stream.getAudioTracks()
track.stop?()
if stream.getVideoTracks?
for track in stream.getVideoTracks()
track.stop?()
stream.stop?()