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

Generic INVITE dialog NOTIFY as basis for talk & hold NOTIFY #748

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
11 changes: 11 additions & 0 deletions lib/RTCSession.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface AnswerOptions extends ExtraHeaders {
rtcAnswerConstraints?: RTCOfferOptions;
rtcOfferConstraints?: RTCOfferOptions;
sessionTimersExpires?: number;
allowEvents?: string[];
}

export interface RejectOptions extends ExtraHeaders {
Expand Down Expand Up @@ -136,6 +137,12 @@ export interface OutgoingInfoEvent {
request: OutgoingRequest;
}

export interface NotifyEvent {
originator: Originator.REMOTE;
type: string;
request: IncomingRequest;
}

export interface HoldEvent {
originator: Originator
}
Expand Down Expand Up @@ -183,6 +190,7 @@ export type DTMFListener = IncomingDTMFListener | OutgoingDTMFListener;
export type IncomingInfoListener = (event: IncomingInfoEvent) => void;
export type OutgoingInfoListener = (event: OutgoingInfoEvent) => void;
export type InfoListener = IncomingInfoListener | OutgoingInfoListener;
export type NotifyListener = (event: NotifyEvent) => void
export type HoldListener = (event: HoldEvent) => void;
export type MuteListener = (event: MediaConstraints) => void;
export type ReInviteListener = (event: ReInviteEvent) => void;
Expand All @@ -202,6 +210,7 @@ export interface RTCSessionEventMap {
'failed': EndListener;
'newDTMF': DTMFListener;
'newInfo': InfoListener;
'newNotify': NotifyListener;
'hold': HoldListener;
'unhold': HoldListener;
'muted': MuteListener;
Expand Down Expand Up @@ -244,6 +253,8 @@ export class RTCSession extends EventEmitter {
set data(_data: any);
get data(): any;

set allow_events(events: string[]);

get connection(): RTCPeerConnectionDeprecated;

get contact(): string;
Expand Down
65 changes: 56 additions & 9 deletions lib/RTCSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ module.exports = class RTCSession extends EventEmitter

// Custom session empty object for high level use.
this._data = {};

// List of allowed NOTIFY events for the Allow-Events header.
this._allowEvents = [];
}

/**
Expand Down Expand Up @@ -202,6 +205,11 @@ module.exports = class RTCSession extends EventEmitter
this._data = _data;
}

set allow_events(events)
{
this._allowEvents = events;
}

get status()
{
return this._status;
Expand Down Expand Up @@ -283,6 +291,7 @@ module.exports = class RTCSession extends EventEmitter
this._rtcAnswerConstraints = options.rtcAnswerConstraints || null;

this._data = options.data || this._data;
this._allowEvents = options.allowEvents || this._allowEvents;

// Check target.
if (target === undefined)
Expand Down Expand Up @@ -374,6 +383,12 @@ module.exports = class RTCSession extends EventEmitter
extraHeaders.push(`Session-Expires: ${this._sessionTimers.defaultExpires}${this._ua.configuration.session_timers_force_refresher ? ';refresher=uac' : ''}`);
}

// If in-dialog NOTIFY events are allowed the Allow-Events header gets set.
if (this._allowEvents.length > 0)
{
extraHeaders.push(`Allow-Events: ${this._allowEvents.join()}`);
}

this._request = new SIPMessage.InitialOutgoingInviteRequest(
target, this._ua, requestParams, extraHeaders);

Expand Down Expand Up @@ -495,8 +510,16 @@ module.exports = class RTCSession extends EventEmitter
return;
}

const extraHeaders = [ `Contact: ${this._contact}` ];

// If in-dialog NOTIFY events are allowed the Allow-Events header gets set.
if (this._allowEvents.length > 0)
{
extraHeaders.push(`Allow-Events: ${this._allowEvents.join()}`);
}

// Reply 180.
request.reply(180, null, [ `Contact: ${this._contact}` ]);
request.reply(180, null, extraHeaders);

// Fire 'progress' event.
// TODO: Document that 'response' field in 'progress' event is null for incoming calls.
Expand Down Expand Up @@ -529,6 +552,7 @@ module.exports = class RTCSession extends EventEmitter
this._rtcOfferConstraints = options.rtcOfferConstraints || null;

this._data = options.data || this._data;
this._allowEvents = options.allowEvents || this._allowEvents;

// Check Session Direction and Status.
if (this._direction !== 'incoming')
Expand Down Expand Up @@ -572,6 +596,12 @@ module.exports = class RTCSession extends EventEmitter

extraHeaders.unshift(`Contact: ${this._contact}`);

// If in-dialog NOTIFY events are allowed the Allow-Events header gets set.
if (this._allowEvents.length > 0)
{
extraHeaders.push(`Allow-Events: ${this._allowEvents.join()}`);
}

// Determine incoming media from incoming SDP offer (if any).
const sdp = request.parseSDP();

Expand Down Expand Up @@ -1598,7 +1628,11 @@ module.exports = class RTCSession extends EventEmitter
}
break;
case JsSIP_C.NOTIFY:
if (this._status === C.STATUS_CONFIRMED)
if (this._status === C.STATUS_1XX_RECEIVED ||
this._status === C.STATUS_WAITING_FOR_ANSWER ||
this._status === C.STATUS_ANSWERED ||
this._status === C.STATUS_WAITING_FOR_ACK ||
this._status === C.STATUS_CONFIRMED)
{
this._receiveNotify(request);
}
Expand Down Expand Up @@ -2505,9 +2539,10 @@ module.exports = class RTCSession extends EventEmitter
request.reply(400);
}

switch (request.event.event)
if (request.event.event === 'refer')
{
case 'refer': {
if (this._status === C.STATUS_CONFIRMED)
{
let id;
let referSubscriber;

Expand Down Expand Up @@ -2537,14 +2572,26 @@ module.exports = class RTCSession extends EventEmitter

referSubscriber.receiveNotify(request);
request.reply(200);

break;
}

default: {
request.reply(489);
else
{
request.reply(403, 'Wrong Status');
}
}
else if (this._allowEvents.indexOf(request.event.event) !== -1)
{
this.emit('newNotify', {
originator : 'remote',
type : request.event.event,
request : request
});

request.reply(200);
}
else
{
request.reply(489);
}
}

/**
Expand Down