Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
74 changes: 10 additions & 64 deletions ee/packages/media-calls/src/internal/SignalProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { IMediaCall, IUser } from '@rocket.chat/core-typings';
import { Emitter } from '@rocket.chat/emitter';
import {
isPendingState,
type ClientMediaSignal,
type ClientMediaSignalRegister,
type ClientMediaSignalRequestCall,
type ServerMediaSignal,
type ServerMediaSignalRejectedCallRequest,
import { isPendingState } from '@rocket.chat/media-signaling';
import type {
ClientMediaSignal,
ClientMediaSignalRegister,
ClientMediaSignalRequestCall,
ServerMediaSignal,
ServerMediaSignalRejectedCallRequest,
} from '@rocket.chat/media-signaling';
import { MediaCalls } from '@rocket.chat/models';

import type { InternalCallParams } from '../definition/common';
import { logger } from '../logger';
import { mediaCallDirector } from '../server/CallDirector';
import { UserActorAgent } from './agents/UserActorAgent';
import { getNewCallTransferredBy } from '../server/getNewCallTransferredBy';
import { buildNewCallSignal } from '../server/buildNewCallSignal';
import { stripSensitiveDataFromSignal } from '../server/stripSensitiveData';

export type SignalProcessorEvents = {
Expand Down Expand Up @@ -147,44 +147,7 @@ export class GlobalSignalProcessor {
await mediaCallDirector.renewCallId(call._id);
}

const transferredBy = getNewCallTransferredBy(call);

if (isCaller) {
this.sendSignal(uid, {
callId: call._id,
type: 'new',
service: call.service,
kind: call.kind,
role: 'caller',
self: {
...call.caller,
},
contact: {
...call.callee,
},
...(call.callerRequestedId && { requestedCallId: call.callerRequestedId }),
...(call.parentCallId && { replacingCallId: call.parentCallId }),
...(transferredBy && { transferredBy }),
});
}

if (isCallee) {
this.sendSignal(uid, {
callId: call._id,
type: 'new',
service: call.service,
kind: call.kind,
role: 'callee',
self: {
...call.callee,
},
contact: {
...call.caller,
},
...(call.parentCallId && { replacingCallId: call.parentCallId }),
...(transferredBy && { transferredBy }),
});
}
this.sendSignal(uid, buildNewCallSignal(call, role));

if (call.state === 'active') {
this.sendSignal(uid, {
Expand Down Expand Up @@ -278,24 +241,7 @@ export class GlobalSignalProcessor {
this.rejectCallRequest(uid, { ...rejection, reason: 'already-requested' });
}

const transferredBy = getNewCallTransferredBy(call);

this.sendSignal(uid, {
callId: call._id,
type: 'new',
service: call.service,
kind: call.kind,
role: 'caller',
self: {
...call.caller,
},
contact: {
...call.callee,
},
requestedCallId: signal.callId,
...(call.parentCallId && { replacingCallId: call.parentCallId }),
...(transferredBy && { transferredBy }),
});
this.sendSignal(uid, buildNewCallSignal(call, 'caller'));

return call;
}
Expand Down
23 changes: 3 additions & 20 deletions ee/packages/media-calls/src/internal/agents/UserActorAgent.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { IMediaCall, MediaCallSignedContact } from '@rocket.chat/core-typings';
import { isBusyState, type ClientMediaSignal, type ServerMediaSignal, type ServerMediaSignalNewCall } from '@rocket.chat/media-signaling';
import { isBusyState, type ClientMediaSignal, type ServerMediaSignal } from '@rocket.chat/media-signaling';
import { MediaCallNegotiations, MediaCalls } from '@rocket.chat/models';

import { UserActorSignalProcessor } from './CallSignalProcessor';
import { BaseMediaCallAgent } from '../../base/BaseAgent';
import { logger } from '../../logger';
import { getNewCallTransferredBy } from '../../server/getNewCallTransferredBy';
import { buildNewCallSignal } from '../../server/buildNewCallSignal';
import { getMediaCallServer } from '../../server/injection';

export class UserActorAgent extends BaseMediaCallAgent {
Expand Down Expand Up @@ -77,7 +77,7 @@ export class UserActorAgent extends BaseMediaCallAgent {
await this.getOrCreateChannel(call, call.caller.contractId);
}

await this.sendSignal(this.buildNewCallSignal(call));
await this.sendSignal(buildNewCallSignal(call, this.role));
}

public async onRemoteDescriptionChanged(callId: string, negotiationId: string): Promise<void> {
Expand Down Expand Up @@ -166,21 +166,4 @@ export class UserActorAgent extends BaseMediaCallAgent {
logger.debug({ msg: 'UserActorAgent.onDTMF', callId, dtmf, duration });
// internal calls have nothing to do with DTMFs
}

protected buildNewCallSignal(call: IMediaCall): ServerMediaSignalNewCall {
const transferredBy = getNewCallTransferredBy(call);

return {
callId: call._id,
type: 'new',
service: call.service,
kind: call.kind,
role: this.role,
self: this.getMyCallActor(call),
contact: this.getOtherCallActor(call),
...(call.parentCallId && { replacingCallId: call.parentCallId }),
...(transferredBy && { transferredBy }),
...(call.callerRequestedId && this.role === 'caller' && { requestedCallId: call.callerRequestedId }),
};
}
}
42 changes: 42 additions & 0 deletions ee/packages/media-calls/src/server/buildNewCallSignal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { IMediaCall } from '@rocket.chat/core-typings';
import type { CallFlag, CallRole, ServerMediaSignalNewCall } from '@rocket.chat/media-signaling';

import { getNewCallTransferredBy } from './getNewCallTransferredBy';

function getCallFlags(call: IMediaCall, role: CallRole): CallFlag[] {
const flags: CallFlag[] = [];

const isInternal = call.caller.type === 'user' && call.callee.type === 'user';
const shouldCreateDataChannel = isInternal && role === 'caller';

if (isInternal) {
flags.push('internal');

if (shouldCreateDataChannel) {
flags.push('create-data-channel');
}
}

return flags;
}

export function buildNewCallSignal(call: IMediaCall, role: CallRole): ServerMediaSignalNewCall {
const self = role === 'caller' ? call.caller : call.callee;
const contact = role === 'caller' ? call.callee : call.caller;
const transferredBy = getNewCallTransferredBy(call);
const flags = getCallFlags(call, role);

return {
callId: call._id,
type: 'new',
service: call.service,
kind: call.kind,
role,
self: { ...self },
contact: { ...contact },
flags,
...(call.parentCallId && { replacingCallId: call.parentCallId }),
...(transferredBy && { transferredBy }),
...(call.callerRequestedId && role === 'caller' && { requestedCallId: call.callerRequestedId }),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,13 @@ export type CallRejectedReason =
| 'invalid-call-params' // something is wrong with the params (eg. no valid route between caller and callee)
| 'forbidden'; // one of the actors on the call doesn't have permission for it

export type CallFlag = 'internal' | 'create-data-channel';

export interface IClientMediaCall {
callId: string;
role: CallRole;
service: CallService | null;
flags: readonly CallFlag[];

state: CallState;
ignored: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type WebRTCInternalStateMap = {
iceConnection: RTCIceConnectionState;
iceGathering: RTCIceGatheringState;
iceUntrickler: 'waiting' | 'not-waiting' | 'timeout';
remoteMute: boolean;
};

export type WebRTCUniqueEvents = {
Expand Down Expand Up @@ -43,6 +44,7 @@ export interface IWebRTCProcessor extends IServiceProcessor<WebRTCInternalStateM

getStats(selector?: MediaStreamTrack | null): Promise<RTCStatsReport | null>;
isRemoteHeld(): boolean;
isRemoteMute(): boolean;
}

export type WebRTCProcessorConfig = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CallContact, CallRole, CallService } from '../../call';
import type { CallContact, CallRole, CallService, CallFlag } from '../../call';

/** Sent by the server to notify an agent that there's a new call for their actor */
export type ServerMediaSignalNewCall = {
Expand All @@ -17,4 +17,7 @@ export type ServerMediaSignalNewCall = {
replacingCallId?: string;
/** If this new call initiated from a transfer, this will hold the information of the user who requested the transfer */
transferredBy?: CallContact;

// A list of flags that may be sent to the client to toggle custom behaviors
flags?: CallFlag[];
};
27 changes: 23 additions & 4 deletions packages/media-signaling/src/lib/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
CallService,
CallHangupReason,
CallActorType,
CallFlag,
} from '../definition/call';
import type { ClientContractState, ClientState } from '../definition/client';
import type { IMediaSignalLogger } from '../definition/logger';
Expand Down Expand Up @@ -131,6 +132,12 @@ export class ClientMediaCall implements IClientMediaCall {
return this._remoteHeld;
}

private _remoteMute: boolean;

public get remoteMute(): boolean {
return this._remoteMute;
}

/** indicates the call is past the "dialing" stage and not yet over */
public get busy(): boolean {
return !this.isPendingAcceptance() && !this.isOver();
Expand Down Expand Up @@ -181,6 +188,12 @@ export class ClientMediaCall implements IClientMediaCall {
return this.webrtcProcessor?.localAudioLevel || 0;
}

private _flags: CallFlag[];

public get flags(): CallFlag[] {
return this._flags;
}

constructor(
private readonly config: IClientMediaCallConfig,
callId: string,
Expand Down Expand Up @@ -215,6 +228,8 @@ export class ClientMediaCall implements IClientMediaCall {
this._transferredBy = null;
this._service = null;
this._remoteHeld = false;
this._remoteMute = false;
this._flags = [];

this.negotiationManager = new NegotiationManager(this, { logger: config.logger });
}
Expand Down Expand Up @@ -278,6 +293,7 @@ export class ClientMediaCall implements IClientMediaCall {
this.hasRemoteData = true;
this._service = signal.service;
this._role = signal.role;
this._flags = signal.flags || [];

this._transferredBy = signal.transferredBy || null;
this.changeContact(signal.contact);
Expand Down Expand Up @@ -994,17 +1010,20 @@ export class ClientMediaCall implements IClientMediaCall {
this.stateTimeoutHandlers.clear();
}

private updateRemoteHeld(): void {
private updateRemoteStates(): void {
if (!this.webrtcProcessor) {
return;
}

const isRemoteHeld = this.webrtcProcessor.isRemoteHeld();
if (isRemoteHeld === this._remoteHeld) {
const isRemoteMute = this.webrtcProcessor.isRemoteMute();

if (isRemoteHeld === this._remoteHeld && isRemoteMute === this._remoteMute) {
return;
}

this._remoteHeld = isRemoteHeld;
this._remoteMute = isRemoteMute;
this.emitter.emit('trackStateChange');
}

Expand All @@ -1015,7 +1034,7 @@ export class ClientMediaCall implements IClientMediaCall {
}
const stateValue = this.webrtcProcessor.getInternalState(stateName);

if (this.serviceStates.get(stateName) !== stateValue) {
if (typeof stateValue === 'string' && this.serviceStates.get(stateName) !== stateValue) {
this.config.logger?.debug(stateName, stateValue);
this.serviceStates.set(stateName, stateValue);

Expand All @@ -1028,7 +1047,7 @@ export class ClientMediaCall implements IClientMediaCall {
this.requestStateReport();
}

this.updateRemoteHeld();
this.updateRemoteStates();
}

private onNegotiationNeeded(oldNegotiationId: string): void {
Expand Down
Loading
Loading