|
@@ -297,6 +297,7 @@ export default class JingleConnectionPlugin extends ConnectionPlugin {
|
297
|
297
|
//
|
298
|
298
|
// See https://modules.prosody.im/mod_turncredentials.html
|
299
|
299
|
// for a prosody module which implements this.
|
|
300
|
+ // Or the new implementation https://modules.prosody.im/mod_external_services which will be in prosody 0.12
|
300
|
301
|
//
|
301
|
302
|
// Currently, this doesn't work with updateIce and therefore credentials
|
302
|
303
|
// with a long validity have to be fetched before creating the
|
|
@@ -306,92 +307,91 @@ export default class JingleConnectionPlugin extends ConnectionPlugin {
|
306
|
307
|
this.connection.sendIQ(
|
307
|
308
|
$iq({ type: 'get',
|
308
|
309
|
to: this.xmpp.options.hosts.domain })
|
309
|
|
- .c('services', { xmlns: 'urn:xmpp:extdisco:1' }),
|
310
|
|
- res => {
|
311
|
|
- const iceservers = [];
|
312
|
|
-
|
313
|
|
- $(res).find('>services>service').each((idx, el) => {
|
314
|
|
- // eslint-disable-next-line no-param-reassign
|
315
|
|
- el = $(el);
|
316
|
|
- const dict = {};
|
317
|
|
- const type = el.attr('type');
|
318
|
|
-
|
319
|
|
- switch (type) {
|
320
|
|
- case 'stun':
|
321
|
|
- dict.urls = `stun:${el.attr('host')}`;
|
322
|
|
- if (el.attr('port')) {
|
323
|
|
- dict.urls += `:${el.attr('port')}`;
|
324
|
|
- }
|
325
|
|
- iceservers.push(dict);
|
326
|
|
- break;
|
327
|
|
- case 'turn':
|
328
|
|
- case 'turns': {
|
329
|
|
- dict.urls = `${type}:`;
|
330
|
|
- const username = el.attr('username');
|
331
|
|
-
|
332
|
|
- // https://code.google.com/p/webrtc/issues/detail
|
333
|
|
- // ?id=1508
|
334
|
|
-
|
335
|
|
- if (username) {
|
336
|
|
- const match
|
337
|
|
- = navigator.userAgent.match(
|
338
|
|
- /Chrom(e|ium)\/([0-9]+)\./);
|
339
|
|
-
|
340
|
|
- if (match && parseInt(match[2], 10) < 28) {
|
341
|
|
- dict.urls += `${username}@`;
|
342
|
|
- } else {
|
343
|
|
- // only works in M28
|
344
|
|
- dict.username = username;
|
345
|
|
- }
|
346
|
|
- }
|
347
|
|
- dict.urls += el.attr('host');
|
348
|
|
- const port = el.attr('port');
|
349
|
|
-
|
350
|
|
- if (port) {
|
351
|
|
- dict.urls += `:${el.attr('port')}`;
|
352
|
|
- }
|
353
|
|
- const transport = el.attr('transport');
|
354
|
|
-
|
355
|
|
- if (transport && transport !== 'udp') {
|
356
|
|
- dict.urls += `?transport=${transport}`;
|
357
|
|
- }
|
358
|
|
-
|
359
|
|
- dict.credential = el.attr('password')
|
360
|
|
- || dict.credential;
|
361
|
|
- iceservers.push(dict);
|
362
|
|
- break;
|
|
310
|
+ .c('services', { xmlns: 'urn:xmpp:extdisco:2' }),
|
|
311
|
+ v2Res => this.onReceiveStunAndTurnCredentials(v2Res),
|
|
312
|
+ v2Err => {
|
|
313
|
+ logger.warn('getting turn credentials with extdisco:2 failed, trying extdisco:1', v2Err);
|
|
314
|
+ this.connection.sendIQ(
|
|
315
|
+ $iq({ type: 'get',
|
|
316
|
+ to: this.xmpp.options.hosts.domain })
|
|
317
|
+ .c('services', { xmlns: 'urn:xmpp:extdisco:1' }),
|
|
318
|
+ v1Res => this.onReceiveStunAndTurnCredentials(v1Res),
|
|
319
|
+ v1Err => {
|
|
320
|
+ logger.warn('getting turn credentials failed', v1Err);
|
|
321
|
+ logger.warn('is mod_turncredentials or similar installed and configured?');
|
363
|
322
|
}
|
364
|
|
- }
|
365
|
|
- });
|
366
|
|
-
|
367
|
|
- const options = this.xmpp.options;
|
|
323
|
+ );
|
|
324
|
+ });
|
|
325
|
+ }
|
368
|
326
|
|
369
|
|
- // Shuffle ICEServers for loadbalancing
|
370
|
|
- for (let i = iceservers.length - 1; i > 0; i--) {
|
371
|
|
- const j = Math.floor(Math.random() * (i + 1));
|
372
|
|
- const temp = iceservers[i];
|
|
327
|
+ /**
|
|
328
|
+ * Parses response when querying for services using urn:xmpp:extdisco:1 or urn:xmpp:extdisco:2.
|
|
329
|
+ * Stores results in jvbIceConfig and p2pIceConfig.
|
|
330
|
+ * @param res The response iq.
|
|
331
|
+ */
|
|
332
|
+ onReceiveStunAndTurnCredentials(res) {
|
|
333
|
+ const iceservers = [];
|
|
334
|
+
|
|
335
|
+ $(res).find('>services>service').each((idx, el) => {
|
|
336
|
+ // eslint-disable-next-line no-param-reassign
|
|
337
|
+ el = $(el);
|
|
338
|
+ const dict = {};
|
|
339
|
+ const type = el.attr('type');
|
|
340
|
+
|
|
341
|
+ switch (type) {
|
|
342
|
+ case 'stun':
|
|
343
|
+ dict.urls = `stun:${el.attr('host')}`;
|
|
344
|
+ if (el.attr('port')) {
|
|
345
|
+ dict.urls += `:${el.attr('port')}`;
|
|
346
|
+ }
|
|
347
|
+ iceservers.push(dict);
|
|
348
|
+ break;
|
|
349
|
+ case 'turn':
|
|
350
|
+ case 'turns': {
|
|
351
|
+ dict.urls = `${type}:`;
|
|
352
|
+ dict.username = el.attr('username');
|
|
353
|
+ dict.urls += el.attr('host');
|
|
354
|
+ const port = el.attr('port');
|
|
355
|
+
|
|
356
|
+ if (port) {
|
|
357
|
+ dict.urls += `:${el.attr('port')}`;
|
|
358
|
+ }
|
|
359
|
+ const transport = el.attr('transport');
|
373
|
360
|
|
374
|
|
- iceservers[i] = iceservers[j];
|
375
|
|
- iceservers[j] = temp;
|
|
361
|
+ if (transport && transport !== 'udp') {
|
|
362
|
+ dict.urls += `?transport=${transport}`;
|
376
|
363
|
}
|
377
|
364
|
|
378
|
|
- let filter;
|
|
365
|
+ dict.credential = el.attr('password')
|
|
366
|
+ || dict.credential;
|
|
367
|
+ iceservers.push(dict);
|
|
368
|
+ break;
|
|
369
|
+ }
|
|
370
|
+ }
|
|
371
|
+ });
|
|
372
|
+
|
|
373
|
+ const options = this.xmpp.options;
|
379
|
374
|
|
380
|
|
- if (options.useTurnUdp) {
|
381
|
|
- filter = s => s.urls.startsWith('turn');
|
382
|
|
- } else {
|
383
|
|
- // By default we filter out STUN and TURN/UDP and leave only TURN/TCP.
|
384
|
|
- filter = s => s.urls.startsWith('turn') && (s.urls.indexOf('transport=tcp') >= 0);
|
385
|
|
- }
|
|
375
|
+ // Shuffle ICEServers for loadbalancing
|
|
376
|
+ for (let i = iceservers.length - 1; i > 0; i--) {
|
|
377
|
+ const j = Math.floor(Math.random() * (i + 1));
|
|
378
|
+ const temp = iceservers[i];
|
386
|
379
|
|
387
|
|
- this.jvbIceConfig.iceServers = iceservers.filter(filter);
|
388
|
|
- this.p2pIceConfig.iceServers = iceservers;
|
389
|
|
- }, err => {
|
390
|
|
- logger.warn('getting turn credentials failed', err);
|
391
|
|
- logger.warn('is mod_turncredentials or similar installed?');
|
392
|
|
- });
|
|
380
|
+ iceservers[i] = iceservers[j];
|
|
381
|
+ iceservers[j] = temp;
|
|
382
|
+ }
|
|
383
|
+
|
|
384
|
+ let filter;
|
|
385
|
+
|
|
386
|
+ if (options.useTurnUdp) {
|
|
387
|
+ filter = s => s.urls.startsWith('turn');
|
|
388
|
+ } else {
|
|
389
|
+ // By default we filter out STUN and TURN/UDP and leave only TURN/TCP.
|
|
390
|
+ filter = s => s.urls.startsWith('turn') && (s.urls.indexOf('transport=tcp') >= 0);
|
|
391
|
+ }
|
393
|
392
|
|
394
|
|
- // implement push?
|
|
393
|
+ this.jvbIceConfig.iceServers = iceservers.filter(filter);
|
|
394
|
+ this.p2pIceConfig.iceServers = iceservers;
|
395
|
395
|
}
|
396
|
396
|
|
397
|
397
|
/**
|