Integrates fippo's work on audio only for firefox and other fixes.

This commit is contained in:
Yana Stamcheva 2014-01-03 17:41:50 +01:00
parent acaa5f74eb
commit d3f2532172
6 changed files with 222 additions and 178 deletions

8
app.js
View File

@ -383,6 +383,7 @@ $(window).bind('beforeunload', function () {
});
function dump(elem, filename) {
console.log("ELEMENT", elem);
elem = elem.parentNode;
elem.download = filename || 'xmpplog.json';
elem.href = 'data:application/json;charset=utf-8,\n';
@ -487,7 +488,7 @@ function openLockDialog() {
if(v)
{
setSharedKey('');
lockRoom();
lockRoom(false);
}
}
});
@ -508,7 +509,6 @@ function openLockDialog() {
if (lockKey.value)
{
console.log("LOCK KEY", lockKey.value);
setSharedKey(lockKey.value);
lockRoom(true);
}
@ -537,7 +537,11 @@ function openLinkDialog() {
* Locks / unlocks the room.
*/
function lockRoom(lock) {
console.log("LOCK", sharedKey);
if (lock)
connection.emuc.lockRoom(sharedKey);
else
connection.emuc.lockRoom('');
updateLockButton();
}

View File

@ -326,3 +326,12 @@ form {
-moz-transition: height 0.2s;
transition: height 0.2s;
}
#downloadlog {
position: absolute;
bottom: 5;
left: 5;
overflow: visible;
z-index: 100;
}

View File

@ -2,13 +2,13 @@
<head>
<title>WebRTC, meet the Jitsi Videobridge</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="libs/strophejingle.bundle.js?v=1"></script><!-- strophe.jingle bundle -->
<script src="libs/colibri.js?v=1"></script><!-- colibri focus implementation -->
<script src="libs/strophejingle.bundle.js?v=2"></script><!-- strophe.jingle bundle -->
<script src="libs/colibri.js?v=2"></script><!-- colibri focus implementation -->
<script src="muc.js?v=2"></script><!-- simple MUC library -->
<script src="estos_log.js?v=1"></script><!-- simple stanza logger -->
<script src="app.js?v=2"></script><!-- application logic -->
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=1"/>
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=2"/>
<link rel="stylesheet" href="css/jquery-impromptu.css?v=1">
<link rel="stylesheet" href="css/modaldialog.css?v=1">
<script src="libs/jquery-impromptu.js"></script>
@ -65,7 +65,7 @@
<div id="chatconversation"></div>
<textarea id="usermsg" class= "animated" placeholder='Enter text...' autofocus></textarea>
</div>
<a id="downloadlog" class="fa fa-cloud-download" title="Download logfile for support" onclick="connection.logger.dump(event.target);" style="position: absolute; bottom: 5; left: 5; overflow: visible; z-index: 100;"></a>
<a id="downloadlog" onclick='dump(event.target);'><i title="Download support information" class="fa fa-cloud-download"></i></a>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)

View File

@ -59,7 +59,7 @@ function ColibriFocus(connection, bridgejid) {
// creates a conferences with an initial set of peers
ColibriFocus.prototype.makeConference = function (peers) {
var ob = this;
var self = this;
if (this.confid !== null) {
console.error('makeConference called twice? Ignoring...');
// FIXME: just invite peers?
@ -68,52 +68,53 @@ ColibriFocus.prototype.makeConference = function (peers) {
this.confid = 0; // !null
this.peers = [];
peers.forEach(function (peer) {
ob.peers.push(peer);
ob.channels.push([]);
self.peers.push(peer);
self.channels.push([]);
});
this.peerconnection = new TraceablePeerConnection(this.connection.jingle.ice_config, this.connection.jingle.pc_constraints);
this.peerconnection.addStream(this.connection.jingle.localStream);
this.peerconnection.oniceconnectionstatechange = function (event) {
console.warn('ice connection state changed to', ob.peerconnection.iceConnectionState);
console.warn('ice connection state changed to', self.peerconnection.iceConnectionState);
/*
if (ob.peerconnection.signalingState == 'stable' && ob.peerconnection.iceConnectionState == 'connected') {
if (self.peerconnection.signalingState == 'stable' && self.peerconnection.iceConnectionState == 'connected') {
console.log('adding new remote SSRCs from iceconnectionstatechange');
window.setTimeout(function() { ob.modifySources(); }, 1000);
window.setTimeout(function() { self.modifySources(); }, 1000);
}
*/
};
this.peerconnection.onsignalingstatechange = function (event) {
console.warn(ob.peerconnection.signalingState);
console.warn(self.peerconnection.signalingState);
/*
if (ob.peerconnection.signalingState == 'stable' && ob.peerconnection.iceConnectionState == 'connected') {
if (self.peerconnection.signalingState == 'stable' && self.peerconnection.iceConnectionState == 'connected') {
console.log('adding new remote SSRCs from signalingstatechange');
window.setTimeout(function() { ob.modifySources(); }, 1000);
window.setTimeout(function() { self.modifySources(); }, 1000);
}
*/
};
this.peerconnection.onaddstream = function (event) {
ob.remoteStream = event.stream;
self.remoteStream = event.stream;
// search the jid associated with this stream
Object.keys(ob.remotessrc).forEach(function (jid) {
if (ob.remotessrc[jid].join('\r\n').indexOf('mslabel:' + event.stream.id) != -1) {
Object.keys(self.remotessrc).forEach(function (jid) {
if (self.remotessrc[jid].join('\r\n').indexOf('mslabel:' + event.stream.id) != -1) {
event.peerjid = jid;
if (ob.connection.jingle.jid2session[jid]) {
ob.connection.jingle.jid2session[jid].remotestream = event.stream;
if (self.connection.jingle.jid2session[jid]) {
self.connection.jingle.jid2session[jid].remotestream = event.stream;
}
}
});
$(document).trigger('remotestreamadded.jingle', [event, ob.sid]);
$(document).trigger('remotestreamadded.jingle', [event, self.sid]);
};
this.peerconnection.onicecandidate = function (event) {
ob.sendIceCandidate(event.candidate);
self.sendIceCandidate(event.candidate);
};
this.peerconnection.createOffer(
function (offer) {
ob.peerconnection.setLocalDescription(
self.peerconnection.setLocalDescription(
offer,
function () {
// success
$(document).trigger('setLocalDescription.jingle', [self.sid]);
// FIXME: could call _makeConference here and trickle candidates later
},
function (error) {
@ -126,17 +127,16 @@ ColibriFocus.prototype.makeConference = function (peers) {
}
);
this.peerconnection.onicecandidate = function (event) {
console.log('candidate', event.candidate);
if (!event.candidate) {
console.log('end of candidates');
ob._makeConference();
self._makeConference();
return;
}
};
};
ColibriFocus.prototype._makeConference = function () {
var ob = this;
var self = this;
var elem = $iq({to: this.bridgejid, type: 'get'});
elem.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri'});
@ -157,7 +157,7 @@ ColibriFocus.prototype._makeConference = function () {
localSDP.TransportToJingle(channel, elem);
elem.up(); // end of channel
for (j = 0; j < ob.peers.length; j++) {
for (j = 0; j < self.peers.length; j++) {
elem.c('channel', {initiator: 'true', expire:'15' }).up();
}
elem.up(); // end of content
@ -165,7 +165,7 @@ ColibriFocus.prototype._makeConference = function () {
this.connection.sendIQ(elem,
function (result) {
ob.createdConference(result);
self.createdConference(result);
},
function (error) {
console.warn(error);
@ -267,19 +267,21 @@ ColibriFocus.prototype.createdConference = function (result) {
bridgeSDP.media[channel] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\r\n';
if (tmp.attr('setup')) {
bridgeSDP.media[channel] += 'a=setup:' + tmp.attr('setup') + '\r\n';
} else {
bridgeSDP.media[channel] += 'a=setup:active\r\n';
}
}
}
}
bridgeSDP.raw = bridgeSDP.session + bridgeSDP.media.join('');
var ob = this;
var self = this;
this.peerconnection.setRemoteDescription(
new RTCSessionDescription({type: 'answer', sdp: bridgeSDP.raw}),
function () {
console.log('setRemoteDescription success');
for (var i = 0; i < numparticipants; i++) {
ob.initiate(ob.peers[i], true);
self.initiate(self.peers[i], true);
}
},
function (error) {
@ -406,12 +408,12 @@ ColibriFocus.prototype.initiate = function (peer, isInitiator) {
// pull in a new participant into the conference
ColibriFocus.prototype.addNewParticipant = function (peer) {
var ob = this;
var self = this;
if (this.confid === 0) {
// bad state
console.log('confid does not exist yet, postponing', peer);
window.setTimeout(function () {
ob.addNewParticipant(peer);
self.addNewParticipant(peer);
}, 250);
return;
}
@ -435,9 +437,9 @@ ColibriFocus.prototype.addNewParticipant = function (peer) {
var contents = $(result).find('>conference>content').get();
for (var i = 0; i < contents.length; i++) {
tmp = $(contents[i]).find('>channel').get();
ob.channels[index][i] = tmp[0];
self.channels[index][i] = tmp[0];
}
ob.initiate(peer, true);
self.initiate(peer, true);
},
function (error) {
console.warn(error);
@ -491,17 +493,17 @@ ColibriFocus.prototype.updateChannel = function (remoteSDP, participant) {
// or a leaving participants a=ssrc lines
// FIXME: should not take an SDP, but rather the a=ssrc lines and probably a=mid
ColibriFocus.prototype.sendSSRCUpdate = function (sdp, jid, isadd) {
var ob = this;
var self = this;
this.peers.forEach(function (peerjid) {
if (peerjid == jid) return;
console.log('tell', peerjid, 'about ' + (isadd ? 'new' : 'removed') + ' ssrcs from', jid);
if (!ob.remotessrc[peerjid]) {
if (!self.remotessrc[peerjid]) {
// FIXME: this should only send to participants that are stable, i.e. who have sent a session-accept
// possibly, this.remoteSSRC[session.peerjid] does not exist yet
console.warn('do we really want to bother', peerjid, 'with updates yet?');
}
var channel;
var peersess = ob.connection.jingle.jid2session[peerjid];
var peersess = self.connection.jingle.jid2session[peerjid];
var modify = $iq({to: peerjid, type: 'set'})
.c('jingle', {
xmlns: 'urn:xmpp:jingle:1',
@ -538,7 +540,7 @@ ColibriFocus.prototype.sendSSRCUpdate = function (sdp, jid, isadd) {
modify.up(); // end of content
}
if (modified) {
ob.connection.sendIQ(modify,
self.connection.sendIQ(modify,
function (res) {
console.warn('got modify result');
},
@ -555,7 +557,7 @@ ColibriFocus.prototype.sendSSRCUpdate = function (sdp, jid, isadd) {
ColibriFocus.prototype.setRemoteDescription = function (session, elem, desctype) {
var participant = this.peers.indexOf(session.peerjid);
console.log('Colibri.setRemoteDescription from', session.peerjid, participant);
var ob = this;
var self = this;
var remoteSDP = new SDP('');
var tmp;
var channel;
@ -585,9 +587,9 @@ ColibriFocus.prototype.setRemoteDescription = function (session, elem, desctype)
// relay ice candidates to bridge using trickle
ColibriFocus.prototype.addIceCandidate = function (session, elem) {
var ob = this;
var self = this;
var participant = this.peers.indexOf(session.peerjid);
console.log('change transport allocation for', this.confid, session.peerjid, participant);
//console.log('change transport allocation for', this.confid, session.peerjid, participant);
var change = $iq({to: this.bridgejid, type: 'set'});
change.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: this.confid});
$(elem).each(function () {
@ -595,7 +597,7 @@ ColibriFocus.prototype.addIceCandidate = function (session, elem) {
var channel = name == 'audio' ? 0 : 1; // FIXME: search mlineindex in localdesc
change.c('content', {name: name});
change.c('channel', {id: $(ob.channels[participant][channel]).attr('id')});
change.c('channel', {id: $(self.channels[participant][channel]).attr('id')});
$(this).find('>transport').each(function () {
change.c('transport', {
ufrag: $(this).attr('ufrag'),
@ -702,7 +704,7 @@ ColibriFocus.prototype.terminate = function (session, reason) {
};
ColibriFocus.prototype.modifySources = function () {
var ob = this;
var self = this;
if (!(this.addssrc.length || this.removessrc.length)) return;
if (this.peerconnection.signalingState == 'closed') return;
@ -710,12 +712,12 @@ ColibriFocus.prototype.modifySources = function () {
// https://code.google.com/p/webrtc/issues/detail?id=2688
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
window.setTimeout(function () { ob.modifySources(); }, 250);
window.setTimeout(function () { self.modifySources(); }, 250);
this.wait = true;
return;
}
if (this.wait) {
window.setTimeout(function () { ob.modifySources(); }, 2500);
window.setTimeout(function () { self.modifySources(); }, 2500);
this.wait = false;
return;
}
@ -738,19 +740,25 @@ ColibriFocus.prototype.modifySources = function () {
this.removessrc = [];
sdp.raw = sdp.session + sdp.media.join('');
/*
* this seems to create a number of problems...
this.peerconnection.setRemoteDescription(
new RTCSessionDescription({type: 'offer', sdp: sdp.raw }),
function () {
console.log('setModifiedRemoteDescription ok');
ob.peerconnection.createAnswer(
self.peerconnection.createAnswer(
function (modifiedAnswer) {
console.log('modifiedAnswer created');
console.log('modifiedAnswer created', modifiedAnswer.sdp);
// FIXME: pushing down an answer while ice connection state
// is still checking is bad...
console.log(ob.peerconnection.iceConnectionState);
ob.peerconnection.setLocalDescription(modifiedAnswer,
console.log(self.peerconnection.iceConnectionState);
// trying to work around another chrome bug
//modifiedAnswer.sdp = modifiedAnswer.sdp.replace(/a=setup:active/g, 'a=setup:actpass');
self.peerconnection.setLocalDescription(modifiedAnswer,
function () {
console.log('setModifiedLocalDescription ok');
$(document).trigger('setLocalDescription.jingle', [self.sid]);
},
function (error) {
console.log('setModifiedLocalDescription failed');
@ -766,6 +774,33 @@ ColibriFocus.prototype.modifySources = function () {
console.log('setModifiedRemoteDescription failed');
}
);
*/
this.peerconnection.createOffer(
function (modifiedOffer) {
console.log('created (un)modified offer');
self.peerconnection.setLocalDescription(modifiedOffer,
function () {
console.log('setModifiedLocalDescription ok');
self.peerconnection.setRemoteDescription(
new RTCSessionDescription({type: 'answer', sdp: sdp.raw }),
function () {
console.log('setModifiedRemoteDescription ok');
},
function (error) {
console.log('setModifiedRemoteDescription failed');
}
);
$(document).trigger('setLocalDescription.jingle', [self.sid]);
},
function (error) {
console.log('setModifiedLocalDescription failed');
}
);
},
function (error) {
console.log('creating (un)modified offerfailed');
}
);
};

View File

@ -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);

1
muc.js
View File

@ -109,6 +109,7 @@ Strophe.addConnectionPlugin('emuc', {
var formsubmit = $iq({to: ob.roomjid, type: 'set'}).c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'});
formsubmit.c('x', {xmlns: 'jabber:x:data', type: 'submit'});
formsubmit.c('field', {'var': 'FORM_TYPE'}).c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up();
console.log("THE KEY TO SET", key);
formsubmit.c('field', {'var': 'muc#roomconfig_roomsecret'}).c('value').t(key).up().up();
// FIXME: is muc#roomconfig_passwordprotectedroom required?
this.connection.sendIQ(formsubmit,