|
@@ -53,6 +53,10 @@ function ColibriFocus(connection, bridgejid) {
|
53
|
53
|
// ssrc lines to be removed on next update
|
54
|
54
|
this.removessrc = [];
|
55
|
55
|
|
|
56
|
+ // container for candidates from the focus
|
|
57
|
+ // gathered before confid is known
|
|
58
|
+ this.drip_container = [];
|
|
59
|
+
|
56
|
60
|
// silly wait flag
|
57
|
61
|
this.wait = true;
|
58
|
62
|
}
|
|
@@ -105,9 +109,6 @@ ColibriFocus.prototype.makeConference = function (peers) {
|
105
|
109
|
});
|
106
|
110
|
$(document).trigger('remotestreamadded.jingle', [event, self.sid]);
|
107
|
111
|
};
|
108
|
|
- this.peerconnection.onicecandidate = function (event) {
|
109
|
|
- self.sendIceCandidate(event.candidate);
|
110
|
|
- };
|
111
|
112
|
this.peerconnection.createOffer(
|
112
|
113
|
function (offer) {
|
113
|
114
|
self.peerconnection.setLocalDescription(
|
|
@@ -116,6 +117,7 @@ ColibriFocus.prototype.makeConference = function (peers) {
|
116
|
117
|
// success
|
117
|
118
|
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
118
|
119
|
// FIXME: could call _makeConference here and trickle candidates later
|
|
120
|
+ self._makeConference();
|
119
|
121
|
},
|
120
|
122
|
function (error) {
|
121
|
123
|
console.log('setLocalDescription failed', error);
|
|
@@ -127,11 +129,16 @@ ColibriFocus.prototype.makeConference = function (peers) {
|
127
|
129
|
}
|
128
|
130
|
);
|
129
|
131
|
this.peerconnection.onicecandidate = function (event) {
|
|
132
|
+ //console.log('focus onicecandidate', self.confid, new Date().getTime(), event.candidate);
|
130
|
133
|
if (!event.candidate) {
|
131
|
134
|
console.log('end of candidates');
|
132
|
|
- self._makeConference();
|
133
|
135
|
return;
|
134
|
136
|
}
|
|
137
|
+ if (self.confid === 0) {
|
|
138
|
+ self.drip_container.push(event.candidate);
|
|
139
|
+ } else {
|
|
140
|
+ self.sendIceCandidate(candidate);
|
|
141
|
+ }
|
135
|
142
|
};
|
136
|
143
|
};
|
137
|
144
|
|
|
@@ -176,6 +183,7 @@ ColibriFocus.prototype._makeConference = function () {
|
176
|
183
|
// callback when a conference was created
|
177
|
184
|
ColibriFocus.prototype.createdConference = function (result) {
|
178
|
185
|
console.log('created a conference on the bridge');
|
|
186
|
+ var self = this;
|
179
|
187
|
var tmp;
|
180
|
188
|
|
181
|
189
|
this.confid = $(result).find('>conference').attr('id');
|
|
@@ -197,6 +205,11 @@ ColibriFocus.prototype.createdConference = function (result) {
|
197
|
205
|
localSDP.removeSessionLines('a=group:');
|
198
|
206
|
localSDP.removeSessionLines('a=msid-semantic:');
|
199
|
207
|
|
|
208
|
+ if (this.drip_container.length) {
|
|
209
|
+ this.sendIceCandidates(this.drip_container);
|
|
210
|
+ this.drip_container = [];
|
|
211
|
+ }
|
|
212
|
+
|
200
|
213
|
// establish our channel with the bridge
|
201
|
214
|
// static answer taken from chrome M31, should be replaced by a
|
202
|
215
|
// dynamic one that is based on our offer FIXME
|
|
@@ -275,7 +288,6 @@ ColibriFocus.prototype.createdConference = function (result) {
|
275
|
288
|
}
|
276
|
289
|
bridgeSDP.raw = bridgeSDP.session + bridgeSDP.media.join('');
|
277
|
290
|
|
278
|
|
- var self = this;
|
279
|
291
|
this.peerconnection.setRemoteDescription(
|
280
|
292
|
new RTCSessionDescription({type: 'answer', sdp: bridgeSDP.raw}),
|
281
|
293
|
function () {
|
|
@@ -638,13 +650,30 @@ ColibriFocus.prototype.sendIceCandidate = function (candidate) {
|
638
|
650
|
console.log('end of candidates');
|
639
|
651
|
return;
|
640
|
652
|
}
|
|
653
|
+ this.sendIceCandidates([candidate]);
|
|
654
|
+};
|
|
655
|
+
|
|
656
|
+// sort and send multiple candidates
|
|
657
|
+ColibriFocus.prototype.sendIceCandidates = function (candidates) {
|
|
658
|
+ var self = this;
|
641
|
659
|
var mycands = $iq({to: this.bridgejid, type: 'set'});
|
642
|
660
|
mycands.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: this.confid});
|
643
|
|
- mycands.c('content', {name: candidate.sdpMid });
|
644
|
|
- mycands.c('channel', {id: $(this.mychannel[candidate.sdpMLineIndex]).attr('id')});
|
645
|
|
- mycands.c('transport', {xmlns: 'urn:xmpp:jingle:transports:ice-udp:1'});
|
646
|
|
- tmp = SDPUtil.candidateToJingle(candidate.candidate);
|
647
|
|
- mycands.c('candidate', tmp).up();
|
|
661
|
+ // FIXME: multi-candidate logic is taken from strophe.jingle, should be refactored there
|
|
662
|
+ var localSDP = new SDP(this.peerconnection.localDescription.sdp);
|
|
663
|
+ for (var mid = 0; mid < localSDP.media.length; mid++) {
|
|
664
|
+ var cands = candidates.filter(function (el) { return el.sdpMLineIndex == mid; });
|
|
665
|
+ if (cands.length > 0) {
|
|
666
|
+ mycands.c('content', {name: cands[0].sdpMid });
|
|
667
|
+ mycands.c('channel', {id: $(this.mychannel[cands[0].sdpMLineIndex]).attr('id')});
|
|
668
|
+ mycands.c('transport', {xmlns: 'urn:xmpp:jingle:transports:ice-udp:1'});
|
|
669
|
+ for (var i = 0; i < cands.length; i++) {
|
|
670
|
+ mycands.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up();
|
|
671
|
+ }
|
|
672
|
+ mycands.up(); // transport
|
|
673
|
+ mycands.up(); // channel
|
|
674
|
+ mycands.up(); // content
|
|
675
|
+ }
|
|
676
|
+ }
|
648
|
677
|
this.connection.sendIQ(mycands,
|
649
|
678
|
function (res) {
|
650
|
679
|
console.log('got result');
|