Skip to content

Commit

Permalink
[NEW] Enable outbound calling for EE (#25843) (#25960)
Browse files Browse the repository at this point in the history
* Clickup Task: https://app.clickup.com/t/22bmce2
Description: Creating EE structure for outbound dialing.
Refactored VoIPUser.ts and made necessary fields protected.
Created VoIPUser or EEVoipClient based on the licensing in SimpleVoipUser
Made necessary changes for using the voip client.

* Clickup Task: https://app.clickup.com/t/22bmce2
Description: Adding missing file.

* Clickup Task: https://app.clickup.com/t/22bmce2
Description: Connector changes for detecting the outbound call.

* Clickup Task: https://app.clickup.com/t/22bmce2
Description: Handling review comments.<!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. -->

<!-- Your Pull Request name should start with one of the following tags
  [NEW] For new features
  [IMPROVE] For an improvement (performance or little improvements) in existing features
  [FIX] For bug fixes that affect the end-user
  [BREAK] For pull requests including breaking changes
  Chore: For small tasks
  Doc: For documentation
-->

<!-- Checklist!!! If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code. 
  - I have read the Contributing Guide - https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat doc
  - I have signed the CLA - https://cla-assistant.io/RocketChat/Rocket.Chat
  - Lint and unit tests pass locally with my changes
  - I have added tests that prove my fix is effective or that my feature works (if applicable)
  - I have added necessary documentation (if applicable)
  - Any dependent changes have been merged and published in downstream modules
-->

## Proposed changes (including videos or screenshots)
<!-- CHANGELOG -->
<!--
  Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.
  If it fixes a bug or resolves a feature request, be sure to link to that issue below.
  This description will appear in the release notes if we accept the contribution.
-->

<!-- END CHANGELOG -->

## Issue(s)
<!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 -->

## Steps to test or reproduce
<!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable -->

## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->


Co-authored-by: amolghode1981 <86001342+amolghode1981@users.noreply.github.com>
Co-authored-by: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com>
Co-authored-by: Aleksander Nicacio da Silva <6494543+aleksandernsilva@users.noreply.github.com>
Co-authored-by: Tiago Evangelista Pinto <17487063+tiagoevanp@users.noreply.github.com>
Co-authored-by: Guilherme Gazzo <5263975+ggazzo@users.noreply.github.com>
  • Loading branch information
6 people committed Jun 28, 2022
1 parent e2cbce2 commit 957c69d
Show file tree
Hide file tree
Showing 17 changed files with 442 additions and 159 deletions.
1 change: 1 addition & 0 deletions apps/meteor/client/contexts/CallContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type CallContextEnabled = {
ready: unknown;
};
type CallContextReady = {
canMakeCall: boolean;
enabled: true;
ready: true;
voipClient: VoIPUser;
Expand Down
30 changes: 0 additions & 30 deletions apps/meteor/client/lib/voip/SimpleVoipUser.ts

This file was deleted.

87 changes: 62 additions & 25 deletions apps/meteor/client/lib/voip/VoIPUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ export class VoIPUser extends Emitter<VoipEvents> {
enableVideo: false,
};

private session: Session | undefined;

private remoteStream: Stream | undefined;

userAgentOptions: UserAgentOptions = {};
Expand All @@ -59,12 +57,6 @@ export class VoIPUser extends Emitter<VoipEvents> {

mediaStreamRendered?: IMediaStreamRenderer;

private _callState: CallStates = 'INITIAL';

private _callerInfo: ICallerInfo | undefined;

private _userState: UserState = UserState.IDLE;

private _connectionState: ConnectionState = 'INITIAL';

private _held = false;
Expand All @@ -89,6 +81,24 @@ export class VoIPUser extends Emitter<VoipEvents> {

private attemptRegistration = false;

protected session: Session | undefined;

protected _callState: CallStates = 'INITIAL';

protected _callerInfo: ICallerInfo | undefined;

protected _userState: UserState = UserState.IDLE;

protected _opInProgress: Operation = Operation.OP_NONE;

get operationInProgress(): Operation {
return this._opInProgress;
}

get userState(): UserState | undefined {
return this._userState;
}

constructor(private readonly config: VoIPUserConfiguration, mediaRenderer?: IMediaStreamRenderer) {
super();
this.mediaStreamRendered = mediaRenderer;
Expand Down Expand Up @@ -116,7 +126,7 @@ export class VoIPUser extends Emitter<VoipEvents> {
server: this.config.webSocketURI,
connectionTimeout: 100, // Replace this with config
keepAliveInterval: 20,
// traceSip: true
// traceSip: true,
};
const sdpFactoryOptions = {
iceGatheringTimeout: 10,
Expand Down Expand Up @@ -242,16 +252,6 @@ export class VoIPUser extends Emitter<VoipEvents> {
};
}

private _opInProgress: Operation = Operation.OP_NONE;

get operationInProgress(): Operation {
return this._opInProgress;
}

get userState(): UserState | undefined {
return this._userState;
}

/* Media Stream functions begin */
/** The local media stream. Undefined if call not answered. */
get localMediaStream(): MediaStream | undefined {
Expand Down Expand Up @@ -322,7 +322,7 @@ export class VoIPUser extends Emitter<VoipEvents> {
* This class handles such session state changes and takes necessary actions.
*/

private setupSessionEventHandlers(session: Session): void {
protected setupSessionEventHandlers(session: Session): void {
this.session?.stateChange.addListener((state: SessionState) => {
if (this.session !== session) {
return; // if our session has changed, just return
Expand All @@ -331,12 +331,32 @@ export class VoIPUser extends Emitter<VoipEvents> {
case SessionState.Initial:
break;
case SessionState.Establishing:
this.emit('ringing', { userState: this._userState, callInfo: this._callerInfo });
break;
case SessionState.Established:
if (this._userState === UserState.UAC) {
/**
* We need to decide about user-state ANSWER-RECEIVED for outbound.
* This state is there for the symmetry of ANSWER-SENT.
* ANSWER-SENT occurs when there is incoming invite. So then the UA
* accepts a call, it sends the answer and state becomes ANSWER-SENT.
* The call gets established only when the remote party sends ACK.
*
* But in case of UAC where the invite is sent out, there is no intermediate
* state where the UA can be in ANSWER-RECEIVED. As soon this UA receives the answer,
* it sends ack and changes the SessionState to established.
*
* So we do not have an actual state transitions from ANSWER-RECEIVED to IN-CALL.
*
* Nevertheless, this state is just added to maintain the symmetry. This can be safely removed.
*
* */
this._callState = 'ANSWER_RECEIVED';
}
this._opInProgress = Operation.OP_NONE;
this._callState = 'IN_CALL';
this.setupRemoteMedia();
this.emit('callestablished');
this._callState = 'IN_CALL';
this.emit('callestablished', { userState: this._userState, callInfo: this._callerInfo });
this.emit('stateChanged');
break;
case SessionState.Terminating:
Expand Down Expand Up @@ -633,6 +653,18 @@ export class VoIPUser extends Emitter<VoipEvents> {
throw new Error('Something went wrong');
}

/* Helper routines for checking call actions BEGIN */

private canRejectCall(): boolean {
return ['OFFER_RECEIVED', 'OFFER_SENT'].includes(this._callState);
}

private canEndOrHoldCall(): boolean {
return ['ANSWER_SENT', 'ANSWER_RECEIVED', 'IN_CALL', 'ON_HOLD'].includes(this._callState);
}

/* Helper routines for checking call actions END */

/**
* Public method called from outside to reject a call.
* @remarks
Expand All @@ -641,7 +673,7 @@ export class VoIPUser extends Emitter<VoipEvents> {
if (!this.session) {
throw new Error('Session does not exist.');
}
if (this._callState !== 'OFFER_RECEIVED') {
if (!this.canRejectCall()) {
throw new Error(`Incorrect call State = ${this.callState}`);
}
if (!(this.session instanceof Invitation)) {
Expand All @@ -658,7 +690,7 @@ export class VoIPUser extends Emitter<VoipEvents> {
if (!this.session) {
throw new Error('Session does not exist.');
}
if (this._callState !== 'ANSWER_SENT' && this._callState !== 'IN_CALL' && this._callState !== 'ON_HOLD') {
if (!this.canEndOrHoldCall()) {
throw new Error(`Incorrect call State = ${this.callState}`);
}

Expand Down Expand Up @@ -708,7 +740,7 @@ export class VoIPUser extends Emitter<VoipEvents> {
if (!this.session) {
throw new Error('Session does not exist.');
}
if (this._callState !== 'ANSWER_SENT' && this._callState !== 'IN_CALL' && this._callState !== 'ON_HOLD') {
if (!this.canEndOrHoldCall()) {
throw new Error(`Incorrect call State = ${this.callState}`);
}
this.handleHoldUnhold(holdState);
Expand Down Expand Up @@ -966,4 +998,9 @@ export class VoIPUser extends Emitter<VoipEvents> {
},
});
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
async makeCall(_callee: string, _mediaRenderer?: IMediaStreamRenderer): Promise<void> {
throw new Error('Not implemented');
}
}
Loading

0 comments on commit 957c69d

Please sign in to comment.