You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-25 05:23:13 +03:00
Merge pull request #1559 from matrix-org/dbkr/ignore_party_id_v0
Ignore party ID if opponent is v0
This commit is contained in:
@@ -142,7 +142,7 @@ describe('Call', function() {
|
|||||||
await call.onAnswerReceived({
|
await call.onAnswerReceived({
|
||||||
getContent: () => {
|
getContent: () => {
|
||||||
return {
|
return {
|
||||||
version: 0,
|
version: 1,
|
||||||
call_id: call.callId,
|
call_id: call.callId,
|
||||||
party_id: 'the_correct_party_id',
|
party_id: 'the_correct_party_id',
|
||||||
answer: {
|
answer: {
|
||||||
@@ -156,7 +156,7 @@ describe('Call', function() {
|
|||||||
call.onRemoteIceCandidatesReceived({
|
call.onRemoteIceCandidatesReceived({
|
||||||
getContent: () => {
|
getContent: () => {
|
||||||
return {
|
return {
|
||||||
version: 0,
|
version: 1,
|
||||||
call_id: call.callId,
|
call_id: call.callId,
|
||||||
party_id: 'the_correct_party_id',
|
party_id: 'the_correct_party_id',
|
||||||
candidates: [
|
candidates: [
|
||||||
@@ -173,7 +173,7 @@ describe('Call', function() {
|
|||||||
call.onRemoteIceCandidatesReceived({
|
call.onRemoteIceCandidatesReceived({
|
||||||
getContent: () => {
|
getContent: () => {
|
||||||
return {
|
return {
|
||||||
version: 0,
|
version: 1,
|
||||||
call_id: call.callId,
|
call_id: call.callId,
|
||||||
party_id: 'some_other_party_id',
|
party_id: 'some_other_party_id',
|
||||||
candidates: [
|
candidates: [
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export enum EventType {
|
|||||||
CallReject = "m.call.reject",
|
CallReject = "m.call.reject",
|
||||||
CallSelectAnswer = "m.call.select_answer",
|
CallSelectAnswer = "m.call.select_answer",
|
||||||
CallNegotiate = "m.call.negotiate",
|
CallNegotiate = "m.call.negotiate",
|
||||||
|
CallReplaces = "m.call.replaces",
|
||||||
KeyVerificationRequest = "m.key.verification.request",
|
KeyVerificationRequest = "m.key.verification.request",
|
||||||
KeyVerificationStart = "m.key.verification.start",
|
KeyVerificationStart = "m.key.verification.start",
|
||||||
KeyVerificationCancel = "m.key.verification.cancel",
|
KeyVerificationCancel = "m.key.verification.cancel",
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ function keyFromRecoverySession(session, decryptionKey) {
|
|||||||
* @param {boolean} [opts.forceTURN]
|
* @param {boolean} [opts.forceTURN]
|
||||||
* Optional. Whether relaying calls through a TURN server should be forced.
|
* Optional. Whether relaying calls through a TURN server should be forced.
|
||||||
*
|
*
|
||||||
|
* @param {boolean} [opts.supportsTransfer]
|
||||||
|
* Optional. True to advertise support for call transfers to other parties on Matrix calls.
|
||||||
|
*
|
||||||
* @param {boolean} [opts.fallbackICEServerAllowed]
|
* @param {boolean} [opts.fallbackICEServerAllowed]
|
||||||
* Optional. Whether to allow a fallback ICE server should be used for negotiating a
|
* Optional. Whether to allow a fallback ICE server should be used for negotiating a
|
||||||
* WebRTC connection if the homeserver doesn't provide any servers. Defaults to false.
|
* WebRTC connection if the homeserver doesn't provide any servers. Defaults to false.
|
||||||
@@ -364,6 +367,7 @@ export function MatrixClient(opts) {
|
|||||||
this._cryptoCallbacks = opts.cryptoCallbacks || {};
|
this._cryptoCallbacks = opts.cryptoCallbacks || {};
|
||||||
|
|
||||||
this._forceTURN = opts.forceTURN || false;
|
this._forceTURN = opts.forceTURN || false;
|
||||||
|
this._supportsTransfer = opts.supportsTransfer || false;
|
||||||
this._fallbackICEServerAllowed = opts.fallbackICEServerAllowed || false;
|
this._fallbackICEServerAllowed = opts.fallbackICEServerAllowed || false;
|
||||||
|
|
||||||
// List of which rooms have encryption enabled: separate from crypto because
|
// List of which rooms have encryption enabled: separate from crypto because
|
||||||
@@ -696,6 +700,14 @@ MatrixClient.prototype.setForceTURN = function(forceTURN) {
|
|||||||
this._forceTURN = forceTURN;
|
this._forceTURN = forceTURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether to advertise trabsfer support to other parties on Matrix calls.
|
||||||
|
* @param {bool} supportsTransfer True to advertise the 'm.call.transeree' capability
|
||||||
|
*/
|
||||||
|
MatrixClient.prototype.setSupportsTransfer = function(supportsTransfer) {
|
||||||
|
this._supportsTransfer = supportsTransfer;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current sync state.
|
* Get the current sync state.
|
||||||
* @return {?string} the sync state, which may be null.
|
* @return {?string} the sync state, which may be null.
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ export interface ICreateClientOpts {
|
|||||||
unstableClientRelationAggregation?: boolean;
|
unstableClientRelationAggregation?: boolean;
|
||||||
verificationMethods?: Array<any>;
|
verificationMethods?: Array<any>;
|
||||||
forceTURN?: boolean;
|
forceTURN?: boolean;
|
||||||
|
supportsTransfer?: boolean,
|
||||||
fallbackICEServerAllowed?: boolean;
|
fallbackICEServerAllowed?: boolean;
|
||||||
cryptoCallbacks?: ICryptoCallbacks;
|
cryptoCallbacks?: ICryptoCallbacks;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import * as utils from '../utils';
|
|||||||
import MatrixEvent from '../models/event';
|
import MatrixEvent from '../models/event';
|
||||||
import {EventType} from '../@types/event';
|
import {EventType} from '../@types/event';
|
||||||
import { RoomMember } from '../models/room-member';
|
import { RoomMember } from '../models/room-member';
|
||||||
|
import { randomString } from '../randomstring';
|
||||||
|
|
||||||
// events: hangup, error(err), replaced(call), state(state, oldState)
|
// events: hangup, error(err), replaced(call), state(state, oldState)
|
||||||
|
|
||||||
@@ -60,6 +61,10 @@ interface TurnServer {
|
|||||||
ttl?: number,
|
ttl?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CallCapabilities {
|
||||||
|
'm.call.transferee': boolean,
|
||||||
|
}
|
||||||
|
|
||||||
export enum CallState {
|
export enum CallState {
|
||||||
Fledgling = 'fledgling',
|
Fledgling = 'fledgling',
|
||||||
InviteSent = 'invite_sent',
|
InviteSent = 'invite_sent',
|
||||||
@@ -194,6 +199,10 @@ export class CallError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genCallID() {
|
||||||
|
return Date.now() + randomString(16);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new Matrix Call.
|
* Construct a new Matrix Call.
|
||||||
* @constructor
|
* @constructor
|
||||||
@@ -240,6 +249,7 @@ export class MatrixCall extends EventEmitter {
|
|||||||
// The party ID of the other side: undefined if we haven't chosen a partner
|
// The party ID of the other side: undefined if we haven't chosen a partner
|
||||||
// yet, null if we have but they didn't send a party ID.
|
// yet, null if we have but they didn't send a party ID.
|
||||||
private opponentPartyId: string;
|
private opponentPartyId: string;
|
||||||
|
private opponentCaps: CallCapabilities;
|
||||||
private inviteTimeout: NodeJS.Timeout; // in the browser it's 'number'
|
private inviteTimeout: NodeJS.Timeout; // in the browser it's 'number'
|
||||||
|
|
||||||
// The logic of when & if a call is on hold is nontrivial and explained in is*OnHold
|
// The logic of when & if a call is on hold is nontrivial and explained in is*OnHold
|
||||||
@@ -275,7 +285,7 @@ export class MatrixCall extends EventEmitter {
|
|||||||
utils.checkObjectHasKeys(server, ["urls"]);
|
utils.checkObjectHasKeys(server, ["urls"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callId = "c" + new Date().getTime() + Math.random();
|
this.callId = genCallID();
|
||||||
this.state = CallState.Fledgling;
|
this.state = CallState.Fledgling;
|
||||||
|
|
||||||
// A queue for candidates waiting to go out.
|
// A queue for candidates waiting to go out.
|
||||||
@@ -358,6 +368,10 @@ export class MatrixCall extends EventEmitter {
|
|||||||
return this.opponentMember;
|
return this.opponentMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opponentCanBeTransferred() {
|
||||||
|
return Boolean(this.opponentCaps && this.opponentCaps["m.call.transferee"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the local <code><video></code> DOM element.
|
* Retrieve the local <code><video></code> DOM element.
|
||||||
* @return {Element} The dom element
|
* @return {Element} The dom element
|
||||||
@@ -469,7 +483,11 @@ export class MatrixCall extends EventEmitter {
|
|||||||
|
|
||||||
this.setState(CallState.Ringing);
|
this.setState(CallState.Ringing);
|
||||||
this.opponentVersion = this.msg.version;
|
this.opponentVersion = this.msg.version;
|
||||||
this.opponentPartyId = this.msg.party_id || null;
|
if (this.opponentVersion !== 0) {
|
||||||
|
// ignore party ID in v0 calls: party ID isn't a thing until v1
|
||||||
|
this.opponentPartyId = this.msg.party_id || null;
|
||||||
|
}
|
||||||
|
this.opponentCaps = this.msg.capabilities || {};
|
||||||
this.opponentMember = event.sender;
|
this.opponentMember = event.sender;
|
||||||
|
|
||||||
if (event.getLocalAge()) {
|
if (event.getLocalAge()) {
|
||||||
@@ -779,7 +797,14 @@ export class MatrixCall extends EventEmitter {
|
|||||||
// required to still be sent for backwards compat
|
// required to still be sent for backwards compat
|
||||||
type: this.peerConn.localDescription.type,
|
type: this.peerConn.localDescription.type,
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
|
if (this.client._supportsTransfer) {
|
||||||
|
answerContent.capabilities = {
|
||||||
|
'm.call.transferee': true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We have just taken the local description from the peerconnection which will
|
// We have just taken the local description from the peerconnection which will
|
||||||
// contain all the local candidates added so far, so we can discard any candidates
|
// contain all the local candidates added so far, so we can discard any candidates
|
||||||
// we had queued up because they'll be in the answer.
|
// we had queued up because they'll be in the answer.
|
||||||
@@ -959,7 +984,10 @@ export class MatrixCall extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.opponentVersion = event.getContent().version;
|
this.opponentVersion = event.getContent().version;
|
||||||
this.opponentPartyId = event.getContent().party_id || null;
|
if (this.opponentVersion !== 0) {
|
||||||
|
this.opponentPartyId = event.getContent().party_id || null;
|
||||||
|
}
|
||||||
|
this.opponentCaps = event.getContent().capabilities || {};
|
||||||
this.opponentMember = event.sender;
|
this.opponentMember = event.sender;
|
||||||
|
|
||||||
this.setState(CallState.Connecting);
|
this.setState(CallState.Connecting);
|
||||||
@@ -1102,7 +1130,13 @@ export class MatrixCall extends EventEmitter {
|
|||||||
const content = {
|
const content = {
|
||||||
[keyName]: this.peerConn.localDescription,
|
[keyName]: this.peerConn.localDescription,
|
||||||
lifetime: CALL_TIMEOUT_MS,
|
lifetime: CALL_TIMEOUT_MS,
|
||||||
};
|
} as any;
|
||||||
|
|
||||||
|
if (this.client._supportsTransfer) {
|
||||||
|
content.capabilities = {
|
||||||
|
'm.call.transferee': true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get rid of any candidates waiting to be sent: they'll be included in the local
|
// Get rid of any candidates waiting to be sent: they'll be included in the local
|
||||||
// description we just got and will send in the offer.
|
// description we just got and will send in the offer.
|
||||||
@@ -1379,6 +1413,28 @@ export class MatrixCall extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async transfer(targetUserId: string, targetRoomId?: string) {
|
||||||
|
// Fetch the target user's global profile info: their room avatar / displayname
|
||||||
|
// could be different in whatever room we shae with them.
|
||||||
|
const profileInfo = await this.client.getProfileInfo(targetUserId);
|
||||||
|
|
||||||
|
const replacementId = genCallID();
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
replacement_id: genCallID(),
|
||||||
|
target_user: {
|
||||||
|
id: targetUserId,
|
||||||
|
display_name: profileInfo.display_name,
|
||||||
|
avatar_url: profileInfo.avatar_url,
|
||||||
|
},
|
||||||
|
create_call: replacementId,
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
if (targetRoomId) body.target_room = targetRoomId;
|
||||||
|
|
||||||
|
return this.sendVoipEvent(EventType.CallReplaces, body);
|
||||||
|
}
|
||||||
|
|
||||||
private async terminate(hangupParty: CallParty, hangupReason: CallErrorCode, shouldEmit: boolean) {
|
private async terminate(hangupParty: CallParty, hangupReason: CallErrorCode, shouldEmit: boolean) {
|
||||||
if (this.callHasEnded()) return;
|
if (this.callHasEnded()) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user