Skip to content
Draft
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
3 changes: 2 additions & 1 deletion ee/packages/media-calls/src/internal/SignalProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ export class GlobalSignalProcessor {
}

const services = signal.supportedServices ?? [];
const requestedService = services.includes('webrtc') ? 'webrtc' : services[0];
// const requestedService = services.includes('webrtc') ? 'webrtc' : services[0];
const requestedService = services.includes('pexip') ? 'pexip' : services[0];
const features = signal.supportedFeatures ?? DEFAULT_CALL_FEATURES;

const params: InternalCallParams = {
Expand Down
22 changes: 19 additions & 3 deletions ee/packages/media-calls/src/server/CallDirector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
ServerActor,
MediaCallNegotiationStream,
} from '@rocket.chat/core-typings';
import type { CallFeature, CallHangupReason, CallRole } from '@rocket.chat/media-signaling';
import type { CallFeature, CallHangupReason, CallRole, CallService } from '@rocket.chat/media-signaling';
import type { InsertionModel } from '@rocket.chat/model-typings';
import { MediaCallNegotiations, MediaCalls } from '@rocket.chat/models';

Expand Down Expand Up @@ -104,6 +104,10 @@ class MediaCallDirector {
call: MediaCallHeader,
offer?: RTCSessionDescriptionInit,
): Promise<IMediaCallNegotiation['_id'] | null> {
if (call.service !== 'webrtc') {
return null;
}

const negotiation = await MediaCallNegotiations.findLatestByCallId(call._id);
// If the call already has a negotiation, do nothing
if (negotiation) {
Expand Down Expand Up @@ -192,7 +196,7 @@ class MediaCallDirector {
const service = requestedService || 'webrtc';

// webrtc is our only known service right now, but if the call was requested by a client that doesn't also implement it, we don't need to even create a call
if (service !== 'webrtc') {
if (service !== 'webrtc' && service !== 'pexip') {
throw new Error('invalid-call-service');
}

Expand All @@ -207,7 +211,9 @@ class MediaCallDirector {
callerAgent.oppositeAgent = calleeAgent;
calleeAgent.oppositeAgent = callerAgent;

const allowedFeatures = features.filter((feature) => getMediaCallServer().isFeatureAvailableForUser(caller.id, feature));
const allowedFeatures = features.filter(
(feature) => getMediaCallServer().isFeatureAvailableForUser(caller.id, feature) && this.isFeatureSupportedByService(feature, service),
);
const call: Omit<IMediaCall, '_updatedAt'> = {
// Use UUIDs to identify all media calls, for better compatibility with libs that require it (such as React Native's CallKit)
_id: randomUUID(),
Expand Down Expand Up @@ -253,6 +259,16 @@ class MediaCallDirector {
return newCall;
}

private isFeatureSupportedByService(feature: CallFeature, service: CallService): boolean {
if (service === 'pexip') {
if (['hold', 'transfer'].includes(feature)) {
return false;
}
}

return true;
}

public async transferCall(
call: MediaCallHeader,
to: MediaCallContact,
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/media-calls/src/server/MediaCallServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class MediaCallServer implements IMediaCallServer {
public async createCall(params: InternalCallParams): Promise<void> {
logger.debug({ msg: 'MediaCallServer.createCall', params });

if (params.callee.type === 'sip') {
if (params.callee.type === 'sip' && params.requestedService !== 'pexip') {
await this.session.createOutgoingCall(params);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core-typings/src/mediaCalls/IMediaCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export type MediaCallSignedContact<T extends MediaCallActorType = MediaCallActor
type MediaCallState = 'none' | 'ringing' | 'accepted' | 'active' | 'hangup';

export interface IMediaCall extends IRocketChatRecord {
service: 'webrtc';
service: 'webrtc' | 'pexip';
kind: 'direct';

state: MediaCallState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
} from './IClientMediaCallParticipant';
import type { CallActorType } from './common';

export type CallService = 'webrtc';
export type CallService = 'webrtc' | 'pexip';

export const callFeatureList = ['audio', 'screen-share', 'transfer', 'hold'] as const;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { PexRTCProcessorFactory } from './pexip/IPexRTCProcessor';
import type { WebRTCProcessorFactory } from './webrtc/IWebRTCProcessor';

export interface IServiceProcessorFactoryList {
webrtc?: WebRTCProcessorFactory;
pexip?: PexRTCProcessorFactory;
}
25 changes: 25 additions & 0 deletions packages/media-signaling/src/definition/services/pexip/IPexRTC.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type PinStatus = 'none' | 'optional' | 'required';

export type CallType = 'none' | 'presentation' | 'screen' | 'audioonly' | 'video' | `recvonly${string}` | 'screen_http' | 'WEBRTC';

export interface IPexRTC {
screenshare_requested: boolean;

disconnect(reason?: string, referral?: boolean): void;
connect(pin?: string, extension?: unknown, idp_uuid?: unknown, sso_token?: unknown): void;
getPresentation(): void;
makeCall(node: string, conferenceAlias: string, displayName: string, bandwidth?: string, call_type?: CallType): void;
present(call_type: 'screen' | 'screen_http' | null): void;
muteVideo(muted: boolean): void;
muteAudio(muted: boolean): void;

onSetup?(localStream: MediaStream | null | undefined, pinStatus: PinStatus, conferenceExtension: unknown, idpChoices: unknown): void;
onConnect?(remoteStream: MediaStream | null): void;
onDisconnect?(reason?: string): void;
onError?(error: unknown): void;
onPresentation?(setting: boolean, presenter: string, uuid: string, presenter_source: string): void;
onPresentationConnected?(stream: MediaStream | string | null): void;
onPresentationDisconnected?(reason?: string): void;
onScreenshareConnected?(stream: MediaStream | null): void;
onScreenshareStopped?(reason?: string): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { Emitter } from '@rocket.chat/emitter';

import type { IClientMediaCall } from '../../call';
import type { IMediaSignalLogger } from '../../logger';
import type { IMediaStreamManager } from '../../media/IMediaStreamManager';
import type { IServiceProcessor, ServiceProcessorEvents } from '../IServiceProcessor';

export type PexipConnectionState = 'disconnected' | 'connecting' | 'joining' | 'connected' | 'error';

export type PexRTCInternalStateMap = {
connection: PexipConnectionState;
};

export type PexRTCUniqueEvents = {
streamChanged: void;
};

export type PexRTCProcessorEvents = ServiceProcessorEvents<PexRTCInternalStateMap> & PexRTCUniqueEvents;

export interface IPexRTCProcessor extends IServiceProcessor<PexRTCInternalStateMap, PexRTCUniqueEvents> {
emitter: Emitter<PexRTCProcessorEvents>;

muted: boolean;
held: boolean;
setMuted(muted: boolean): void;
setHeld(held: boolean): void;
stop(): void;

joinConference(): void;
disconnect(): void;
requestScreenShare(requested: boolean): void;

readonly streams: IMediaStreamManager;

// setInputTrack(newInputTrack: MediaStreamTrack | null): Promise<void>;
// setScreenVideoTrack(newVideoTrack: MediaStreamTrack | null): Promise<void>;
}

export type PexRTCProcessorConfig = {
call: IClientMediaCall;
logger?: IMediaSignalLogger;
nodeDomain: string;
conferenceAlias: string;
displayName: string;
pin?: string;
};

export type PexRTCProcessorFactory = (config: PexRTCProcessorConfig) => Promise<IPexRTCProcessor>;
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const clientMediaSignalRequestCallSchema: JSONSchemaType<ClientMediaSigna
type: 'array',
items: {
type: 'string',
enum: ['webrtc'],
enum: ['webrtc', 'pexip'],
nullable: false,
},
nullable: false,
Expand Down
Loading
Loading