|
|
|
|
@ -607,10 +607,10 @@ SDP.prototype.mangle = function () { |
|
|
|
|
|
|
|
|
|
// remove lines matching prefix from session section
|
|
|
|
|
SDP.prototype.removeSessionLines = function(prefix) { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
var lines = SDPUtil.find_lines(this.session, prefix); |
|
|
|
|
lines.forEach(function(line) { |
|
|
|
|
ob.session = ob.session.replace(line + '\r\n', ''); |
|
|
|
|
self.session = self.session.replace(line + '\r\n', ''); |
|
|
|
|
}); |
|
|
|
|
this.raw = this.session + this.media.join(''); |
|
|
|
|
return lines; |
|
|
|
|
@ -618,10 +618,10 @@ SDP.prototype.removeSessionLines = function(prefix) { |
|
|
|
|
// remove lines matching prefix from a media section specified by mediaindex
|
|
|
|
|
// TODO: non-numeric mediaindex could match mid
|
|
|
|
|
SDP.prototype.removeMediaLines = function(mediaindex, prefix) { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
var lines = SDPUtil.find_lines(this.media[mediaindex], prefix); |
|
|
|
|
lines.forEach(function(line) { |
|
|
|
|
ob.media[mediaindex] = ob.media[mediaindex].replace(line + '\r\n', ''); |
|
|
|
|
self.media[mediaindex] = self.media[mediaindex].replace(line + '\r\n', ''); |
|
|
|
|
}); |
|
|
|
|
this.raw = this.session + this.media.join(''); |
|
|
|
|
return lines; |
|
|
|
|
@ -630,7 +630,7 @@ SDP.prototype.removeMediaLines = function(mediaindex, prefix) { |
|
|
|
|
// add content's to a jingle element
|
|
|
|
|
SDP.prototype.toJingle = function (elem, thecreator) { |
|
|
|
|
var i, j, k, mline, ssrc, rtpmap, tmp, line, lines; |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
// new bundle plan
|
|
|
|
|
if (SDPUtil.find_line(this.session, 'a=group:')) { |
|
|
|
|
lines = SDPUtil.find_lines(this.session, 'a=group:'); |
|
|
|
|
@ -806,7 +806,7 @@ SDP.prototype.toJingle = function (elem, thecreator) { |
|
|
|
|
SDP.prototype.TransportToJingle = function (mediaindex, elem) { |
|
|
|
|
var i = mediaindex; |
|
|
|
|
var tmp; |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
elem.c('transport'); |
|
|
|
|
|
|
|
|
|
// XEP-0320
|
|
|
|
|
@ -817,7 +817,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) { |
|
|
|
|
// tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0'; -- FIXME: update receivers first
|
|
|
|
|
elem.c('fingerprint').t(tmp.fingerprint); |
|
|
|
|
delete tmp.fingerprint; |
|
|
|
|
line = SDPUtil.find_line(ob.media[mediaindex], 'a=setup:', ob.session); |
|
|
|
|
line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session); |
|
|
|
|
if (line) { |
|
|
|
|
tmp.setup = line.substr(8); |
|
|
|
|
} |
|
|
|
|
@ -881,7 +881,7 @@ SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293 |
|
|
|
|
|
|
|
|
|
// construct an SDP from a jingle stanza
|
|
|
|
|
SDP.prototype.fromJingle = function (jingle) { |
|
|
|
|
var obj = this; |
|
|
|
|
var self = this; |
|
|
|
|
this.raw = 'v=0\r\n' + |
|
|
|
|
'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
|
|
|
|
|
's=-\r\n' + |
|
|
|
|
@ -893,7 +893,7 @@ SDP.prototype.fromJingle = function (jingle) { |
|
|
|
|
return content.getAttribute('name'); |
|
|
|
|
}).get(); |
|
|
|
|
if (contents.length > 0) { |
|
|
|
|
obj.raw += 'a=group:' + (group.getAttribute('semantics') || group.getAttribute('type')) + ' ' + contents.join(' ') + '\r\n'; |
|
|
|
|
self.raw += 'a=group:' + (group.getAttribute('semantics') || group.getAttribute('type')) + ' ' + contents.join(' ') + '\r\n'; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} else if ($(jingle).find('>group[xmlns="urn:ietf:rfc:5888"]').length) { |
|
|
|
|
@ -903,7 +903,7 @@ SDP.prototype.fromJingle = function (jingle) { |
|
|
|
|
return content.getAttribute('name'); |
|
|
|
|
}).get(); |
|
|
|
|
if (group.getAttribute('type') !== null && contents.length > 0) { |
|
|
|
|
obj.raw += 'a=group:' + group.getAttribute('type') + ' ' + contents.join(' ') + '\r\n'; |
|
|
|
|
self.raw += 'a=group:' + group.getAttribute('type') + ' ' + contents.join(' ') + '\r\n'; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
@ -922,8 +922,8 @@ SDP.prototype.fromJingle = function (jingle) { |
|
|
|
|
|
|
|
|
|
this.session = this.raw; |
|
|
|
|
jingle.find('>content').each(function () { |
|
|
|
|
var m = obj.jingle2media($(this)); |
|
|
|
|
obj.media.push(m); |
|
|
|
|
var m = self.jingle2media($(this)); |
|
|
|
|
self.media.push(m); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// reconstruct msid-semantic -- apparently not necessary
|
|
|
|
|
@ -1416,7 +1416,7 @@ function JingleSession(me, sid, connection) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.initiate = function (peerjid, isInitiator) { |
|
|
|
|
var obj = this; |
|
|
|
|
var self = this; |
|
|
|
|
if (this.state !== null) { |
|
|
|
|
console.error('attempt to initiate on session ' + this.sid + |
|
|
|
|
'in state ' + this.state); |
|
|
|
|
@ -1427,11 +1427,10 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) { |
|
|
|
|
this.initiator = isInitiator ? this.me : peerjid; |
|
|
|
|
this.responder = !isInitiator ? this.me : peerjid; |
|
|
|
|
this.peerjid = peerjid; |
|
|
|
|
console.log('create PeerConnection ' + JSON.stringify(this.ice_config)); |
|
|
|
|
//console.log('create PeerConnection ' + JSON.stringify(this.ice_config));
|
|
|
|
|
try { |
|
|
|
|
this.peerconnection = new RTCPeerconnection(this.ice_config, |
|
|
|
|
this.pc_constraints); |
|
|
|
|
console.log('Created RTCPeerConnnection'); |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error('Failed to create PeerConnection, exception: ', |
|
|
|
|
e.message); |
|
|
|
|
@ -1442,26 +1441,24 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) { |
|
|
|
|
this.hadturncandidate = false; |
|
|
|
|
this.lasticecandidate = false; |
|
|
|
|
this.peerconnection.onicecandidate = function (event) { |
|
|
|
|
obj.sendIceCandidate(event.candidate); |
|
|
|
|
self.sendIceCandidate(event.candidate); |
|
|
|
|
}; |
|
|
|
|
this.peerconnection.onaddstream = function (event) { |
|
|
|
|
obj.remoteStream = event.stream; |
|
|
|
|
obj.remoteStreams.push(event.stream); |
|
|
|
|
$(document).trigger('remotestreamadded.jingle', [event, obj.sid]); |
|
|
|
|
self.remoteStream = event.stream; |
|
|
|
|
self.remoteStreams.push(event.stream); |
|
|
|
|
$(document).trigger('remotestreamadded.jingle', [event, self.sid]); |
|
|
|
|
}; |
|
|
|
|
this.peerconnection.onremovestream = function (event) { |
|
|
|
|
obj.remoteStream = null; |
|
|
|
|
self.remoteStream = null; |
|
|
|
|
// FIXME: remove from this.remoteStreams
|
|
|
|
|
$(document).trigger('remotestreamremoved.jingle', [event, obj.sid]); |
|
|
|
|
$(document).trigger('remotestreamremoved.jingle', [event, self.sid]); |
|
|
|
|
}; |
|
|
|
|
this.peerconnection.onsignalingstatechange = function (event) { |
|
|
|
|
if (!(obj && obj.peerconnection)) return; |
|
|
|
|
console.log('signallingstate ', obj.peerconnection.signalingState, event); |
|
|
|
|
if (!(self && self.peerconnection)) return; |
|
|
|
|
}; |
|
|
|
|
this.peerconnection.oniceconnectionstatechange = function (event) { |
|
|
|
|
if (!(obj && obj.peerconnection)) return; |
|
|
|
|
console.log('iceconnectionstatechange', obj.peerconnection.iceConnectionState, event); |
|
|
|
|
switch (obj.peerconnection.iceConnectionState) { |
|
|
|
|
if (!(self && self.peerconnection)) return; |
|
|
|
|
switch (self.peerconnection.iceConnectionState) { |
|
|
|
|
case 'connected': |
|
|
|
|
this.startTime = new Date(); |
|
|
|
|
break; |
|
|
|
|
@ -1469,19 +1466,19 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) { |
|
|
|
|
this.stopTime = new Date(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
$(document).trigger('iceconnectionstatechange.jingle', [obj.sid, obj]); |
|
|
|
|
$(document).trigger('iceconnectionstatechange.jingle', [self.sid, self]); |
|
|
|
|
}; |
|
|
|
|
// add any local and relayed stream
|
|
|
|
|
this.localStreams.forEach(function(stream) { |
|
|
|
|
obj.peerconnection.addStream(stream); |
|
|
|
|
self.peerconnection.addStream(stream); |
|
|
|
|
}); |
|
|
|
|
this.relayedStreams.forEach(function(stream) { |
|
|
|
|
obj.peerconnection.addStream(stream); |
|
|
|
|
self.peerconnection.addStream(stream); |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.accept = function () { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
this.state = 'active'; |
|
|
|
|
|
|
|
|
|
var pranswer = this.peerconnection.localDescription; |
|
|
|
|
@ -1513,7 +1510,7 @@ JingleSession.prototype.accept = function () { |
|
|
|
|
function () { |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'answer'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
@ -1521,7 +1518,7 @@ JingleSession.prototype.accept = function () { |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'answer'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
|
|
|
|
|
@ -1532,7 +1529,7 @@ JingleSession.prototype.accept = function () { |
|
|
|
|
} |
|
|
|
|
this.peerconnection.setLocalDescription(new RTCSessionDescription({type: 'answer', sdp: sdp}), |
|
|
|
|
function () { |
|
|
|
|
console.log('setLocalDescription success'); |
|
|
|
|
//console.log('setLocalDescription success');
|
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('setLocalDescription failed', e); |
|
|
|
|
@ -1555,7 +1552,7 @@ JingleSession.prototype.active = function () { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
if (candidate && !this.lasticecandidate) { |
|
|
|
|
var ice = SDPUtil.iceparams(this.localSDP.media[candidate.sdpMLineIndex], this.localSDP.session); |
|
|
|
|
var jcand = SDPUtil.candidateToJingle(candidate.candidate); |
|
|
|
|
@ -1576,28 +1573,28 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
if (this.drip_container.length === 0) { |
|
|
|
|
// start 10ms callout
|
|
|
|
|
window.setTimeout(function () { |
|
|
|
|
if (ob.drip_container.length === 0) return; |
|
|
|
|
var allcands = ob.drip_container; |
|
|
|
|
ob.drip_container = []; |
|
|
|
|
var cand = $iq({to: ob.peerjid, type: 'set'}) |
|
|
|
|
if (self.drip_container.length === 0) return; |
|
|
|
|
var allcands = self.drip_container; |
|
|
|
|
self.drip_container = []; |
|
|
|
|
var cand = $iq({to: self.peerjid, type: 'set'}) |
|
|
|
|
.c('jingle', {xmlns: 'urn:xmpp:jingle:1', |
|
|
|
|
action: 'transport-info', |
|
|
|
|
initiator: ob.initiator, |
|
|
|
|
sid: ob.sid}); |
|
|
|
|
for (var mid = 0; mid < ob.localSDP.media.length; mid++) { |
|
|
|
|
initiator: self.initiator, |
|
|
|
|
sid: self.sid}); |
|
|
|
|
for (var mid = 0; mid < self.localSDP.media.length; mid++) { |
|
|
|
|
var cands = allcands.filter(function (el) { return el.sdpMLineIndex == mid; }); |
|
|
|
|
if (cands.length > 0) { |
|
|
|
|
var ice = SDPUtil.iceparams(ob.localSDP.media[mid], ob.localSDP.session); |
|
|
|
|
var ice = SDPUtil.iceparams(self.localSDP.media[mid], self.localSDP.session); |
|
|
|
|
ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1'; |
|
|
|
|
cand.c('content', {creator: ob.initiator == ob.me ? 'initiator' : 'responder', |
|
|
|
|
cand.c('content', {creator: self.initiator == self.me ? 'initiator' : 'responder', |
|
|
|
|
name: cands[0].sdpMid |
|
|
|
|
}).c('transport', ice); |
|
|
|
|
for (var i = 0; i < cands.length; i++) { |
|
|
|
|
cand.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up(); |
|
|
|
|
} |
|
|
|
|
// add fingerprint
|
|
|
|
|
if (SDPUtil.find_line(ob.localSDP.media[mid], 'a=fingerprint:', ob.localSDP.session)) { |
|
|
|
|
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(ob.localSDP.media[mid], 'a=fingerprint:', ob.localSDP.session)); |
|
|
|
|
if (SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session)) { |
|
|
|
|
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session)); |
|
|
|
|
tmp.required = true; |
|
|
|
|
cand.c('fingerprint').t(tmp.fingerprint); |
|
|
|
|
delete tmp.fingerprint; |
|
|
|
|
@ -1609,12 +1606,12 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340
|
|
|
|
|
//console.log('was this the last candidate', ob.lasticecandidate);
|
|
|
|
|
ob.connection.sendIQ(cand, |
|
|
|
|
//console.log('was this the last candidate', self.lasticecandidate);
|
|
|
|
|
self.connection.sendIQ(cand, |
|
|
|
|
function () { |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'transportinfo'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
@ -1622,7 +1619,7 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'transportinfo'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
}, 10); |
|
|
|
|
@ -1655,7 +1652,7 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
function () { |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'transportinfo'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
console.error('transport info error'); |
|
|
|
|
@ -1664,14 +1661,14 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'transportinfo'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
console.log('sendIceCandidate: last candidate.'); |
|
|
|
|
//console.log('sendIceCandidate: last candidate.');
|
|
|
|
|
if (!this.usetrickle) { |
|
|
|
|
console.log('should send full offer now...'); |
|
|
|
|
//console.log('should send full offer now...');
|
|
|
|
|
var init = $iq({to: this.peerjid, |
|
|
|
|
type: 'set'}) |
|
|
|
|
.c('jingle', {xmlns: 'urn:xmpp:jingle:1', |
|
|
|
|
@ -1682,20 +1679,20 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
this.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder'); |
|
|
|
|
this.connection.sendIQ(init, |
|
|
|
|
function () { |
|
|
|
|
console.log('session initiate ack'); |
|
|
|
|
//console.log('session initiate ack');
|
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'offer'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
ob.state = 'error'; |
|
|
|
|
ob.peerconnection.close(); |
|
|
|
|
self.state = 'error'; |
|
|
|
|
self.peerconnection.close(); |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
code: $(stanza).find('error').attr('code'), |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'offer'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
} |
|
|
|
|
@ -1710,10 +1707,10 @@ JingleSession.prototype.sendIceCandidate = function (candidate) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.sendOffer = function () { |
|
|
|
|
console.log('sendOffer...'); |
|
|
|
|
var ob = this; |
|
|
|
|
//console.log('sendOffer...');
|
|
|
|
|
var self = this; |
|
|
|
|
this.peerconnection.createOffer(function (sdp) { |
|
|
|
|
ob.createdOffer(sdp); |
|
|
|
|
self.createdOffer(sdp); |
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('createOffer failed', e); |
|
|
|
|
@ -1723,8 +1720,8 @@ JingleSession.prototype.sendOffer = function () { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.createdOffer = function (sdp) { |
|
|
|
|
console.log('createdOffer', sdp); |
|
|
|
|
var ob = this; |
|
|
|
|
//console.log('createdOffer', sdp);
|
|
|
|
|
var self = this; |
|
|
|
|
this.localSDP = new SDP(sdp.sdp); |
|
|
|
|
//this.localSDP.mangle();
|
|
|
|
|
if (this.usetrickle) { |
|
|
|
|
@ -1739,23 +1736,24 @@ JingleSession.prototype.createdOffer = function (sdp) { |
|
|
|
|
function () { |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'offer'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
ob.state = 'error'; |
|
|
|
|
ob.peerconnection.close(); |
|
|
|
|
self.state = 'error'; |
|
|
|
|
self.peerconnection.close(); |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
code: $(stanza).find('error').attr('code'), |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'offer'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
} |
|
|
|
|
sdp.sdp = this.localSDP.raw; |
|
|
|
|
this.peerconnection.setLocalDescription(sdp, function () { |
|
|
|
|
console.log('setLocalDescription success'); |
|
|
|
|
this.peerconnection.setLocalDescription(sdp,
|
|
|
|
|
function () { |
|
|
|
|
//console.log('setLocalDescription success');
|
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('setLocalDescription failed', e); |
|
|
|
|
@ -1773,7 +1771,7 @@ JingleSession.prototype.createdOffer = function (sdp) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.setRemoteDescription = function (elem, desctype) { |
|
|
|
|
console.log('setting remote description... ', desctype); |
|
|
|
|
//console.log('setting remote description... ', desctype);
|
|
|
|
|
this.remoteSDP = new SDP(''); |
|
|
|
|
this.remoteSDP.fromJingle(elem); |
|
|
|
|
if (this.peerconnection.remoteDescription !== null) { |
|
|
|
|
@ -1807,7 +1805,7 @@ JingleSession.prototype.setRemoteDescription = function (elem, desctype) { |
|
|
|
|
|
|
|
|
|
this.peerconnection.setRemoteDescription(remotedesc, |
|
|
|
|
function () { |
|
|
|
|
console.log('setRemoteDescription success'); |
|
|
|
|
//console.log('setRemoteDescription success');
|
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('setRemoteDescription error', e); |
|
|
|
|
@ -1816,7 +1814,7 @@ JingleSession.prototype.setRemoteDescription = function (elem, desctype) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
var obj = this; |
|
|
|
|
var self = this; |
|
|
|
|
if (this.peerconnection.signalingState == 'closed') { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
@ -1841,19 +1839,19 @@ JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
} |
|
|
|
|
// then add things like ice and dtls from remote candidate
|
|
|
|
|
elem.each(function () { |
|
|
|
|
for (var i = 0; i < obj.remoteSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(obj.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
obj.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
if (!SDPUtil.find_line(obj.remoteSDP.media[i], 'a=ice-ufrag:')) { |
|
|
|
|
for (var i = 0; i < self.remoteSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
if (!SDPUtil.find_line(self.remoteSDP.media[i], 'a=ice-ufrag:')) { |
|
|
|
|
var tmp = $(this).find('transport'); |
|
|
|
|
obj.remoteSDP.media[i] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n'; |
|
|
|
|
obj.remoteSDP.media[i] += 'a=ice-pwd:' + tmp.attr('pwd') + '\r\n'; |
|
|
|
|
self.remoteSDP.media[i] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n'; |
|
|
|
|
self.remoteSDP.media[i] += 'a=ice-pwd:' + tmp.attr('pwd') + '\r\n'; |
|
|
|
|
tmp = $(this).find('transport>fingerprint'); |
|
|
|
|
if (tmp.length) { |
|
|
|
|
obj.remoteSDP.media[i] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\r\n'; |
|
|
|
|
self.remoteSDP.media[i] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\r\n'; |
|
|
|
|
} else { |
|
|
|
|
console.log('no dtls fingerprint (webrtc issue #1718?)'); |
|
|
|
|
obj.remoteSDP.media[i] += 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:BAADBAADBAADBAADBAADBAADBAADBAADBAADBAAD\r\n'; |
|
|
|
|
self.remoteSDP.media[i] += 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:BAADBAADBAADBAADBAADBAADBAADBAADBAADBAAD\r\n'; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
@ -1872,12 +1870,17 @@ JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
if (iscomplete) { |
|
|
|
|
console.log('setting pranswer'); |
|
|
|
|
try { |
|
|
|
|
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'pranswer', sdp: this.remoteSDP.raw })); |
|
|
|
|
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'pranswer', sdp: this.remoteSDP.raw }), |
|
|
|
|
function() { |
|
|
|
|
}, |
|
|
|
|
function(e) { |
|
|
|
|
console.log('setRemoteDescription pranswer failed', e.toString()); |
|
|
|
|
}); |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error('setting pranswer failed', e); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
console.log('not yet setting pranswer'); |
|
|
|
|
//console.log('not yet setting pranswer');
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// operate on each content element
|
|
|
|
|
@ -1885,17 +1888,17 @@ JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
// would love to deactivate this, but firefox still requires it
|
|
|
|
|
var idx = -1; |
|
|
|
|
var i; |
|
|
|
|
for (i = 0; i < obj.remoteSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(obj.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
obj.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
for (i = 0; i < self.remoteSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
idx = i; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (idx == -1) { // fall back to localdescription
|
|
|
|
|
for (i = 0; i < obj.localSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(obj.localSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
obj.localSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
for (i = 0; i < self.localSDP.media.length; i++) { |
|
|
|
|
if (SDPUtil.find_line(self.localSDP.media[i], 'a=mid:' + $(this).attr('name')) || |
|
|
|
|
self.localSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) { |
|
|
|
|
idx = i; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
@ -1910,7 +1913,7 @@ JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
sdpMid: name, |
|
|
|
|
candidate: line}); |
|
|
|
|
try { |
|
|
|
|
obj.peerconnection.addIceCandidate(candidate); |
|
|
|
|
self.peerconnection.addIceCandidate(candidate); |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error('addIceCandidate failed', e.toString(), line); |
|
|
|
|
} |
|
|
|
|
@ -1919,11 +1922,11 @@ JingleSession.prototype.addIceCandidate = function (elem) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.sendAnswer = function (provisional) { |
|
|
|
|
console.log('createAnswer', provisional); |
|
|
|
|
var ob = this; |
|
|
|
|
//console.log('createAnswer', provisional);
|
|
|
|
|
var self = this; |
|
|
|
|
this.peerconnection.createAnswer( |
|
|
|
|
function (sdp) { |
|
|
|
|
ob.createdAnswer(sdp, provisional); |
|
|
|
|
self.createdAnswer(sdp, provisional); |
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('createAnswer failed', e); |
|
|
|
|
@ -1933,9 +1936,9 @@ JingleSession.prototype.sendAnswer = function (provisional) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.createdAnswer = function (sdp, provisional) { |
|
|
|
|
console.log('createAnswer callback'); |
|
|
|
|
//console.log('createAnswer callback');
|
|
|
|
|
console.log(sdp); |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
this.localSDP = new SDP(sdp.sdp); |
|
|
|
|
//this.localSDP.mangle();
|
|
|
|
|
this.usepranswer = provisional === true; |
|
|
|
|
@ -1953,7 +1956,7 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) { |
|
|
|
|
function () { |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'answer'; |
|
|
|
|
$(document).trigger('ack.jingle', [ob.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
@ -1961,7 +1964,7 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) { |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
error.source = 'answer'; |
|
|
|
|
$(document).trigger('error.jingle', [ob.sid, error]); |
|
|
|
|
$(document).trigger('error.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
} else { |
|
|
|
|
@ -1975,7 +1978,7 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) { |
|
|
|
|
sdp.sdp = this.localSDP.raw; |
|
|
|
|
this.peerconnection.setLocalDescription(sdp, |
|
|
|
|
function () { |
|
|
|
|
console.log('setLocalDescription success'); |
|
|
|
|
//console.log('setLocalDescription success');
|
|
|
|
|
}, |
|
|
|
|
function (e) { |
|
|
|
|
console.error('setLocalDescription failed', e); |
|
|
|
|
@ -1993,7 +1996,7 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.sendTerminate = function (reason, text) { |
|
|
|
|
var obj = this, |
|
|
|
|
var self = this, |
|
|
|
|
term = $iq({to: this.peerjid, |
|
|
|
|
type: 'set'}) |
|
|
|
|
.c('jingle', {xmlns: 'urn:xmpp:jingle:1', |
|
|
|
|
@ -2009,19 +2012,19 @@ JingleSession.prototype.sendTerminate = function (reason, text) { |
|
|
|
|
|
|
|
|
|
this.connection.sendIQ(term, |
|
|
|
|
function () { |
|
|
|
|
obj.peerconnection.close(); |
|
|
|
|
obj.peerconnection = null; |
|
|
|
|
obj.terminate(); |
|
|
|
|
self.peerconnection.close(); |
|
|
|
|
self.peerconnection = null; |
|
|
|
|
self.terminate(); |
|
|
|
|
var ack = {}; |
|
|
|
|
ack.source = 'terminate'; |
|
|
|
|
$(document).trigger('ack.jingle', [obj.sid, ack]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, ack]); |
|
|
|
|
}, |
|
|
|
|
function (stanza) { |
|
|
|
|
var error = ($(stanza).find('error').length) ? { |
|
|
|
|
code: $(stanza).find('error').attr('code'), |
|
|
|
|
reason: $(stanza).find('error :first')[0].tagName, |
|
|
|
|
}:{}; |
|
|
|
|
$(document).trigger('ack.jingle', [obj.sid, error]); |
|
|
|
|
$(document).trigger('ack.jingle', [self.sid, error]); |
|
|
|
|
}, |
|
|
|
|
10000); |
|
|
|
|
if (this.statsinterval !== null) { |
|
|
|
|
@ -2036,7 +2039,7 @@ JingleSession.prototype.addSource = function (elem) { |
|
|
|
|
console.log('ice', this.peerconnection.iceConnectionState); |
|
|
|
|
var sdp = new SDP(this.peerconnection.remoteDescription.sdp); |
|
|
|
|
|
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
$(elem).each(function (idx, content) { |
|
|
|
|
var name = $(content).attr('name'); |
|
|
|
|
var lines = ''; |
|
|
|
|
@ -2050,13 +2053,12 @@ JingleSession.prototype.addSource = function (elem) { |
|
|
|
|
lines += '\r\n'; |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
console.log(name, lines); |
|
|
|
|
sdp.media.forEach(function(media, idx) { |
|
|
|
|
if (!SDPUtil.find_line(media, 'a=mid:' + name)) |
|
|
|
|
return; |
|
|
|
|
sdp.media[idx] += lines; |
|
|
|
|
if (!ob.addssrc[idx]) ob.addssrc[idx] = ''; |
|
|
|
|
ob.addssrc[idx] += lines; |
|
|
|
|
if (!self.addssrc[idx]) self.addssrc[idx] = ''; |
|
|
|
|
self.addssrc[idx] += lines; |
|
|
|
|
}); |
|
|
|
|
sdp.raw = sdp.session + sdp.media.join(''); |
|
|
|
|
}); |
|
|
|
|
@ -2068,7 +2070,7 @@ JingleSession.prototype.removeSource = function (elem) { |
|
|
|
|
console.log('ice', this.peerconnection.iceConnectionState); |
|
|
|
|
var sdp = new SDP(this.peerconnection.remoteDescription.sdp); |
|
|
|
|
|
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
$(elem).each(function (idx, content) { |
|
|
|
|
var name = $(content).attr('name'); |
|
|
|
|
var lines = ''; |
|
|
|
|
@ -2082,39 +2084,34 @@ JingleSession.prototype.removeSource = function (elem) { |
|
|
|
|
lines += '\r\n'; |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
console.log(name, lines); |
|
|
|
|
sdp.media.forEach(function(media, idx) { |
|
|
|
|
if (!SDPUtil.find_line(media, 'a=mid:' + name)) |
|
|
|
|
return; |
|
|
|
|
sdp.media[idx] += lines; |
|
|
|
|
if (!ob.addssrc[idx]) ob.removessrc[idx] = ''; |
|
|
|
|
ob.removessrc[idx] += lines; |
|
|
|
|
if (!self.addssrc[idx]) self.removessrc[idx] = ''; |
|
|
|
|
self.removessrc[idx] += lines; |
|
|
|
|
}); |
|
|
|
|
sdp.raw = sdp.session + sdp.media.join(''); |
|
|
|
|
}); |
|
|
|
|
console.log(this.removessrc); |
|
|
|
|
this.modifySources(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JingleSession.prototype.modifySources = function() { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
if (!(this.addssrc.length || this.removessrc.length)) return; |
|
|
|
|
if (this.peerconnection.signalingState == 'closed') return; |
|
|
|
|
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) { |
|
|
|
|
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState); |
|
|
|
|
this.wait = true; |
|
|
|
|
window.setTimeout(function() { ob.modifySources(); }, 250); |
|
|
|
|
window.setTimeout(function() { self.modifySources(); }, 250); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (this.wait) { |
|
|
|
|
window.setTimeout(function() { ob.modifySources(); }, 2500); |
|
|
|
|
window.setTimeout(function() { self.modifySources(); }, 2500); |
|
|
|
|
this.wait = false; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
console.log('ice', this.peerconnection.iceConnectionState); |
|
|
|
|
var sdp = new SDP(this.peerconnection.remoteDescription.sdp); |
|
|
|
|
|
|
|
|
|
// add sources
|
|
|
|
|
@ -2136,13 +2133,11 @@ JingleSession.prototype.modifySources = function() { |
|
|
|
|
sdp.raw = sdp.session + sdp.media.join(''); |
|
|
|
|
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}), |
|
|
|
|
function() { |
|
|
|
|
console.log('modify ok'); |
|
|
|
|
ob.peerconnection.createAnswer( |
|
|
|
|
self.peerconnection.createAnswer( |
|
|
|
|
function(modifiedAnswer) { |
|
|
|
|
console.log('modified answer...'); |
|
|
|
|
ob.peerconnection.setLocalDescription(modifiedAnswer, |
|
|
|
|
self.peerconnection.setLocalDescription(modifiedAnswer, |
|
|
|
|
function() { |
|
|
|
|
console.log('modified setLocalDescription ok'); |
|
|
|
|
//console.log('modified setLocalDescription ok');
|
|
|
|
|
}, |
|
|
|
|
function(error) { |
|
|
|
|
console.log('modified setLocalDescription failed'); |
|
|
|
|
@ -2187,7 +2182,7 @@ JingleSession.prototype.sendRinging = function () { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
JingleSession.prototype.getStats = function (interval) { |
|
|
|
|
var ob = this; |
|
|
|
|
var self = this; |
|
|
|
|
var recv = {audio: 0, video: 0}; |
|
|
|
|
var lost = {audio: 0, video: 0}; |
|
|
|
|
var lastrecv = {audio: 0, video: 0}; |
|
|
|
|
@ -2195,8 +2190,8 @@ JingleSession.prototype.getStats = function (interval) { |
|
|
|
|
var loss = {audio: 0, video: 0}; |
|
|
|
|
var delta = {audio: 0, video: 0}; |
|
|
|
|
this.statsinterval = window.setInterval(function () { |
|
|
|
|
if (ob && ob.peerconnection && ob.peerconnection.getStats) { |
|
|
|
|
ob.peerconnection.getStats(function (stats) { |
|
|
|
|
if (self && self.peerconnection && self.peerconnection.getStats) { |
|
|
|
|
self.peerconnection.getStats(function (stats) { |
|
|
|
|
var results = stats.result(); |
|
|
|
|
// TODO: there are so much statistics you can get from this..
|
|
|
|
|
for (var i = 0; i < results.length; ++i) { |
|
|
|
|
@ -2225,7 +2220,7 @@ JingleSession.prototype.getStats = function (interval) { |
|
|
|
|
delta.video = recv.video - lastrecv.video; |
|
|
|
|
loss.audio = (delta.audio > 0) ? Math.ceil(100 * (lost.audio - lastlost.audio) / delta.audio) : 0; |
|
|
|
|
loss.video = (delta.video > 0) ? Math.ceil(100 * (lost.video - lastlost.video) / delta.video) : 0; |
|
|
|
|
$(document).trigger('packetloss.jingle', [ob.sid, loss]); |
|
|
|
|
$(document).trigger('packetloss.jingle', [self.sid, loss]); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
}, interval || 3000); |
|
|
|
|
|