Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream/20-12-11 #20

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 17 additions & 37 deletions JitsiConference.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ const JINGLE_SI_TIMEOUT = 5000;
* "Math.random() < forceJVB121Ratio" will determine whether a 2 people
* conference should be moved to the JVB instead of P2P. The decision is made on
* the responder side, after ICE succeeds on the P2P connection.
* @param {*} [options.config.openBridgeChannel] Which kind of communication to
* open with the videobridge. Values can be "datachannel", "websocket", true
* (treat it as "datachannel"), undefined (treat it as "datachannel") and false
* (don't open any channel).
* @constructor
*
* FIXME Make all methods which are called from lib-internal classes
Expand Down Expand Up @@ -942,27 +938,23 @@ JitsiConference.prototype.getTranscriptionStatus = function() {

/**
* Adds JitsiLocalTrack object to the conference.
* @param track the JitsiLocalTrack object.
* @param {JitsiLocalTrack} track the JitsiLocalTrack object.
* @returns {Promise<JitsiLocalTrack>}
* @throws {Error} if the specified track is a video track and there is already
* another video track in the conference.
*/
JitsiConference.prototype.addTrack = function(track) {
if (track.isVideoTrack()) {
// Ensure there's exactly 1 local video track in the conference.
const localVideoTrack = this.rtc.getLocalVideoTrack();

if (localVideoTrack) {
// Don't be excessively harsh and severe if the API client happens
// to attempt to add the same local video track twice.
if (track === localVideoTrack) {
return Promise.resolve(track);
}

return Promise.reject(new Error(
'cannot add second video track to the conference'));

const mediaType = track.getType();
const localTracks = this.rtc.getLocalTracks(mediaType);

// Ensure there's exactly 1 local track of each media type in the conference.
if (localTracks.length > 0) {
// Don't be excessively harsh and severe if the API client happens to attempt to add the same local track twice.
if (track === localTracks[0]) {
return Promise.resolve(track);
}

return Promise.reject(new Error(`Cannot add second ${mediaType} track to the conference`));
}

return this.replaceTrack(null, track);
Expand Down Expand Up @@ -2003,23 +1995,12 @@ JitsiConference.prototype._setBridgeChannel = function(offerIq, pc) {
wsUrl = webSocket[0].getAttribute('url');
}

let bridgeChannelType;

switch (this.options.config.openBridgeChannel) {
case 'datachannel':
case true:
case undefined:
bridgeChannelType = 'datachannel';
break;
case 'websocket':
bridgeChannelType = 'websocket';
break;
}

if (bridgeChannelType === 'datachannel') {
this.rtc.initializeBridgeChannel(pc, null);
} else if (bridgeChannelType === 'websocket' && wsUrl) {
if (wsUrl) {
// If the offer contains a websocket use it.
this.rtc.initializeBridgeChannel(null, wsUrl);
} else {
// Otherwise, fall back to an attempt to use SCTP.
this.rtc.initializeBridgeChannel(pc, null);
}
};

Expand Down Expand Up @@ -2860,8 +2841,7 @@ JitsiConference.prototype._updateProperties = function(properties = {}) {
'bridge-count',

// The conference creation time (set by jicofo).
'created-ms',
'octo-enabled'
'created-ms'
];

analyticsKeys.forEach(key => {
Expand Down
2 changes: 2 additions & 0 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ Throws NetworkError or InvalidStateError or Error if the operation fails.
- `propertyKey` - string - custom property name
- `propertyValue` - string - custom property value

38. `getParticipants()` - Retrieves an array of all participants in this conference.

JitsiTrack
======
The object represents single track - video or audio. They can be remote tracks ( from the other participants in the call) or local tracks (from the devices of the local participant).
Expand Down
4 changes: 4 additions & 0 deletions modules/RTC/RTC.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ export default class RTC extends Listenable {
iceConfig.sdpSemantics = 'plan-b';
}

if (options.forceTurnRelay) {
iceConfig.iceTransportPolicy = 'relay';
}

// Set the RTCBundlePolicy to max-bundle so that only one set of ice candidates is generated.
// The default policy generates separate ice candidates for audio and video connections.
// This change is necessary for Unified plan to work properly on Chrome and Safari.
Expand Down
6 changes: 3 additions & 3 deletions modules/RTC/RTCUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,9 +664,9 @@ function onMediaDevicesListChanged(devicesReceived) {
sendDeviceListToAnalytics(availableDevices);

// Used by tracks to update the real device id before the consumer of lib-jitsi-meet receives the new device list.
eventEmitter.emit(RTCEvents.DEVICE_LIST_WILL_CHANGE, devicesReceived);
eventEmitter.emit(RTCEvents.DEVICE_LIST_WILL_CHANGE, availableDevices);

eventEmitter.emit(RTCEvents.DEVICE_LIST_CHANGED, devicesReceived);
eventEmitter.emit(RTCEvents.DEVICE_LIST_CHANGED, availableDevices);
}

/**
Expand Down Expand Up @@ -846,7 +846,7 @@ class RTCUtils extends Listenable {

if (this.isDeviceListAvailable()) {
this.enumerateDevices(ds => {
availableDevices = ds.splice(0);
availableDevices = ds.slice(0);

logger.debug('Available devices: ', availableDevices);
sendDeviceListToAnalytics(availableDevices);
Expand Down
25 changes: 11 additions & 14 deletions modules/RTC/TPCUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import transform from 'sdp-transform';

import * as MediaType from '../../service/RTC/MediaType';
import RTCEvents from '../../service/RTC/RTCEvents';
import VideoType from '../../service/RTC/VideoType';
import browser from '../browser';

const logger = getLogger(__filename);
Expand Down Expand Up @@ -447,20 +446,18 @@ export class TPCUtils {
* @returns {void}
*/
updateEncodingsResolution(parameters) {
const localVideoTrack = this.pc.getLocalVideoTrack();

// Ignore desktop and non-simulcast tracks.
if (!(parameters
&& parameters.encodings
&& Array.isArray(parameters.encodings)
&& this.pc.isSimulcastOn()
&& localVideoTrack
&& localVideoTrack.videoType !== VideoType.DESKTOP)) {
if (!(browser.isSafari() && parameters.encodings && Array.isArray(parameters.encodings))) {
return;
}

parameters.encodings.forEach((encoding, idx) => {
encoding.scaleResolutionDownBy = this.localStreamEncodingsConfig[idx].scaleResolutionDownBy;
});
const allEqualEncodings
= encodings => encodings.every(encoding => typeof encoding.scaleResolutionDownBy !== 'undefined'
&& encoding.scaleResolutionDownBy === encodings[0].scaleResolutionDownBy);

// Implement the workaround only when all the encodings report the same resolution.
if (allEqualEncodings(parameters.encodings)) {
parameters.encodings.forEach((encoding, idx) => {
encoding.scaleResolutionDownBy = this.localStreamEncodingsConfig[idx].scaleResolutionDownBy;
});
}
}
}
1 change: 1 addition & 0 deletions modules/xmpp/JingleSessionPC.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ export default class JingleSessionPC extends JingleSession {
pcOptions.capScreenshareBitrate = false;
pcOptions.enableInsertableStreams = options.enableInsertableStreams;
pcOptions.videoQuality = options.videoQuality;
pcOptions.forceTurnRelay = options.forceTurnRelay;

// codec preference options for jvb connection.
if (pcOptions.videoQuality) {
Expand Down
10 changes: 9 additions & 1 deletion modules/xmpp/XmppConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default class XmppConnection extends Listenable {
super();
this._options = {
enableWebsocketResume: typeof enableWebsocketResume === 'undefined' ? true : enableWebsocketResume,
pingOptions: xmppPing,
websocketKeepAlive: typeof websocketKeepAlive === 'undefined' ? 4 * 60 * 1000 : Number(websocketKeepAlive)
};

Expand Down Expand Up @@ -174,6 +175,13 @@ export default class XmppConnection extends Listenable {
return this._stropheConn.options;
}

/**
* A getter for the domain to be used for ping.
*/
get pingDomain() {
return this._options.pingOptions?.domain || this.domain;
}

/**
* A getter for the service URL.
*
Expand Down Expand Up @@ -255,7 +263,7 @@ export default class XmppConnection extends Listenable {
this._maybeStartWSKeepAlive();
this._processDeferredIQs();
this._resumeTask.cancel();
this.ping.startInterval(this.domain);
this.ping.startInterval(this._options.pingOptions?.domain || this.domain);
} else if (status === Strophe.Status.DISCONNECTED) {
this.ping.stopInterval();

Expand Down
98 changes: 4 additions & 94 deletions modules/xmpp/moderator.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,9 @@ export default function Moderator(roomName, xmpp, emitter, options) {
this.externalAuthEnabled = false;
this.options = options;

// Sip gateway can be enabled by configuring Jigasi host in config.js or
// it will be enabled automatically if focus detects the component through
// service discovery.
this.sipGatewayEnabled
= this.options.connection.hosts
&& this.options.connection.hosts.call_control !== undefined;
// Whether SIP gateway (jigasi) support is enabled. This is set
// based on conference properties received in presence.
this.sipGatewayEnabled = false;

this.eventEmitter = emitter;

Expand Down Expand Up @@ -160,63 +157,13 @@ Moderator.prototype.createConferenceIq = function() {
if (sessionId) {
elem.attrs({ 'session-id': sessionId });
}
if (this.options.connection.enforcedBridge !== undefined) {
elem.c(
'property', {
name: 'enforcedBridge',
value: this.options.connection.enforcedBridge
}).up();
}

// Tell the focus we have Jigasi configured
if (this.options.connection.hosts !== undefined
&& this.options.connection.hosts.call_control !== undefined) {
elem.c(
'property', {
name: 'call_control',
value: this.options.connection.hosts.call_control
}).up();
}
elem.c(
'property', {
name: 'disableRtx',
value: Boolean(config.disableRtx)
}).up();

if (config.enableTcc !== undefined) {
elem.c(
'property', {
name: 'enableTcc',
value: Boolean(config.enableTcc)
}).up();
}
if (config.enableRemb !== undefined) {
elem.c(
'property', {
name: 'enableRemb',
value: Boolean(config.enableRemb)
}).up();
}
if (config.enableOpusRed === true) {
elem.c(
'property', {
name: 'enableOpusRed',
value: true
}).up();
}
if (config.minParticipants !== undefined) {
elem.c(
'property', {
name: 'minParticipants',
value: config.minParticipants
}).up();
}

elem.c(
'property', {
name: 'enableLipSync',
value: this.options.connection.enableLipSync === true
}).up();
if (config.audioPacketDelay !== undefined) {
elem.c(
'property', {
Expand All @@ -238,35 +185,6 @@ Moderator.prototype.createConferenceIq = function() {
value: config.minBitrate
}).up();
}
if (config.testing && config.testing.octo
&& typeof config.testing.octo.probability === 'number') {
if (Math.random() < config.testing.octo.probability) {
elem.c(
'property', {
name: 'octo',
value: true
}).up();
}
}

let openSctp;

switch (this.options.conference.openBridgeChannel) {
case 'datachannel':
case true:
case undefined:
openSctp = true;
break;
case 'websocket':
openSctp = false;
break;
}

elem.c(
'property', {
name: 'openSctp',
value: openSctp
}).up();

if (config.opusMaxAverageBitrate) {
elem.c(
Expand Down Expand Up @@ -296,13 +214,6 @@ Moderator.prototype.createConferenceIq = function() {
value: this.options.conference.stereo
}).up();
}
if (this.options.conference.useRoomAsSharedDocumentName !== undefined) {
elem.c(
'property', {
name: 'useRoomAsSharedDocumentName',
value: this.options.conference.useRoomAsSharedDocumentName
}).up();
}
elem.up();

return elem;
Expand Down Expand Up @@ -348,8 +259,7 @@ Moderator.prototype.parseConfigOptions = function(resultIq) {
this.eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
authenticationEnabled, authIdentity);

// Check if focus has auto-detected Jigasi component(this will be also
// included if we have passed our host from the config)
// Check if jicofo has jigasi support enabled.
if ($(resultIq).find(
'>conference>property'
+ '[name=\'sipGatewayEnabled\'][value=\'true\']').length) {
Expand Down
2 changes: 1 addition & 1 deletion modules/xmpp/strophe.jingle.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ export default class JingleConnectionPlugin extends ConnectionPlugin {
// https://code.google.com/p/webrtc/issues/detail?id=1650
this.connection.sendIQ(
$iq({ type: 'get',
to: this.connection.domain })
to: this.xmpp.options.hosts.domain })
.c('services', { xmlns: 'urn:xmpp:extdisco:1' }),
res => {
const iceservers = [];
Expand Down
Loading