Skip to content

Commit 2c9a310

Browse files
committed
- Do not allow reject-ing a Message or Session with an incorrect status code
- Extract 'accept()' and 'reject()' Message methods to the prototype - Extract 'reject()' and 'cancel()' Session methods to the prototype
1 parent 35e5874 commit 2c9a310

File tree

4 files changed

+127
-50
lines changed

4 files changed

+127
-50
lines changed

src/Message.js

+36-12
Original file line numberDiff line numberDiff line change
@@ -163,21 +163,10 @@ JsSIP.Message.prototype.init_incoming = function(request) {
163163
contentType = request.getHeader('content-type');
164164

165165
this.direction = 'incoming';
166+
this.request = request;
166167
this.local_identity = request.s('to').uri;
167168
this.remote_identity = request.s('from').uri;
168169

169-
this.accept = function() {
170-
request.reply(200);
171-
};
172-
173-
this.reject = function(status_code, reason_phrase) {
174-
if (status_code && reason_phrase) {
175-
request.reply(status_code, reason_phrase);
176-
} else {
177-
request.reply(480);
178-
}
179-
};
180-
181170
if (contentType && (contentType.match(/^text\/plain(\s*;\s*.+)*$/i) || contentType.match(/^text\/html(\s*;\s*.+)*$/i))) {
182171
this.ua.emit('newMessage', this.ua, {
183172
originator: 'remote',
@@ -194,3 +183,38 @@ JsSIP.Message.prototype.init_incoming = function(request) {
194183
request.reply(415, JsSIP.c.REASON_PHRASE[415], ["Accept: text/plain, text/html"]);
195184
}
196185
};
186+
187+
/**
188+
* Accept the incoming Message
189+
* Only valid for incoming Messages
190+
*/
191+
JsSIP.Message.prototype.accept = function() {
192+
if (this.direction !== 'incoming') {
193+
throw new JsSIP.exceptions.InvalidMethodError();
194+
}
195+
196+
this.request.reply(200);
197+
};
198+
199+
/**
200+
* Reject the incoming Message
201+
* Only valid for incoming Messages
202+
*
203+
* @param {Number} status_code
204+
* @param {String} [reason_phrase]
205+
*/
206+
JsSIP.Message.prototype.reject = function(status_code, reason_phrase) {
207+
if (this.direction !== 'incoming') {
208+
throw new JsSIP.exceptions.InvalidMethodError();
209+
}
210+
211+
if (status_code) {
212+
if ((status_code < 300 || status_code >= 700)) {
213+
throw new JsSIP.exceptions.InvalidValueError();
214+
} else {
215+
this.request.reply(status_code, reason_phrase);
216+
}
217+
} else {
218+
this.request.reply(480);
219+
}
220+
};

src/Session.js

+65-33
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ JsSIP.Session = function(ua) {
1818
];
1919

2020
this.ua = ua;
21-
this.status = null;
21+
this.status = JsSIP.c.SESSION_NULL;
2222
this.dialog = null;
2323
this.earlyDialogs = [];
2424
this.mediaSession = null;
@@ -64,6 +64,7 @@ JsSIP.Session.prototype.init_incoming = function(request) {
6464
this.from_tag = request.from_tag;
6565
this.status = JsSIP.c.SESSION_INVITE_RECEIVED;
6666
this.id = request.call_id + this.from_tag;
67+
this.request = request;
6768

6869
//Save the session into the ua sessions collection.
6970
this.ua.sessions[this.id] = this;
@@ -84,7 +85,7 @@ JsSIP.Session.prototype.connect = function(target, options) {
8485
}
8586

8687
// Check Session Status
87-
if (this.status !== null) {
88+
if (this.status !== JsSIP.c.SESSION_NULL) {
8889
throw new JsSIP.exceptions.InvalidStateError();
8990
}
9091

@@ -145,23 +146,6 @@ JsSIP.Session.prototype.connect = function(target, options) {
145146
//Save the session into the ua sessions collection.
146147
this.ua.sessions[this.id] = this;
147148

148-
/**
149-
* @private
150-
*/
151-
this.cancel = function() {
152-
if (this.status === JsSIP.c.SESSION_INVITE_SENT) {
153-
if(this.received_100) {
154-
request.cancel();
155-
} else {
156-
this.isCanceled = true;
157-
}
158-
} else if(this.status === JsSIP.c.SESSION_1XX_RECEIVED) {
159-
request.cancel();
160-
}
161-
162-
this.failed('local', null, JsSIP.c.causes.CANCELED);
163-
};
164-
165149
this.newSession('local', request, target);
166150
this.connecting('local', request, target);
167151
this.sendInitialRequest(mediaType);
@@ -455,18 +439,6 @@ JsSIP.Session.prototype.receiveInitialRequest = function(ua, request) {
455439
session.mediaSession.startCallee(onMediaSuccess, onMediaFailure, onSdpFailure, offer);
456440
};
457441

458-
/**
459-
* Reject the call
460-
* @private
461-
*/
462-
this.reject = function() {
463-
if (this.status === JsSIP.c.SESSION_WAITING_FOR_ANSWER) {
464-
request.reply(486);
465-
466-
this.failed('local', null, JsSIP.c.causes.REJECTED);
467-
}
468-
};
469-
470442
// Fire 'call' event callback
471443
this.newSession('remote', request);
472444

@@ -498,7 +470,7 @@ JsSIP.Session.prototype.receiveResponse = function(response) {
498470
// Proceed to cancelation if the user requested.
499471
if(this.isCanceled) {
500472
if(response.status_code >= 100 && response.status_code < 200) {
501-
this.request.cancel();
473+
this.request.cancel(this.cancelReason);
502474
} else if(response.status_code >= 200 && response.status_code < 299) {
503475
this.acceptAndTerminate(response);
504476
}
@@ -885,6 +857,66 @@ JsSIP.Session.prototype.terminate = function() {
885857
this.close();
886858
};
887859

860+
/**
861+
* Reject the incoming call
862+
* Only valid for incoming Messages
863+
*
864+
* @param {Number} status_code
865+
* @param {String} [reason_phrase]
866+
*/
867+
JsSIP.Session.prototype.reject = function(status_code, reason_phrase) {
868+
// Check Session Direction and Status
869+
if (this.direction !== 'incoming') {
870+
throw new JsSIP.exceptions.InvalidMethodError();
871+
} else if (this.status !== JsSIP.c.SESSION_WAITING_FOR_ANSWER) {
872+
throw new JsSIP.exceptions.InvalidStateError();
873+
}
874+
875+
if (status_code) {
876+
if ((status_code < 300 || status_code >= 700)) {
877+
throw new JsSIP.exceptions.InvalidValueError();
878+
} else {
879+
this.request.reply(status_code, reason_phrase);
880+
}
881+
} else {
882+
this.request.reply(480);
883+
}
884+
885+
this.failed('local', null, JsSIP.c.causes.REJECTED);
886+
};
887+
888+
/**
889+
* Cancel the outgoing call
890+
*
891+
* @param {String} [reason]
892+
*/
893+
JsSIP.Session.prototype.cancel = function(reason) {
894+
// Check Session Direction
895+
if (this.direction !== 'outgoing') {
896+
throw new JsSIP.exceptions.InvalidMethodError();
897+
}
898+
899+
// Check Session Status
900+
if (this.status === JsSIP.c.SESSION_NULL) {
901+
this.isCanceled = true;
902+
this.cancelReason = reason;
903+
} else if (this.status === JsSIP.c.SESSION_INVITE_SENT) {
904+
if(this.received_100) {
905+
this.request.cancel(reason);
906+
} else {
907+
this.isCanceled = true;
908+
this.cancelReason = reason;
909+
}
910+
} else if(this.status === JsSIP.c.SESSION_1XX_RECEIVED) {
911+
this.request.cancel(reason);
912+
} else {
913+
throw new JsSIP.exceptions.InvalidStateError();
914+
}
915+
916+
this.failed('local', null, JsSIP.c.causes.CANCELED);
917+
};
918+
919+
888920

889921
/**
890922
* Initial Request Sender
@@ -899,7 +931,7 @@ JsSIP.Session.prototype.sendInitialRequest = function(mediaType) {
899931
request_sender = new JsSIP.RequestSender(self, this.ua);
900932

901933
function onMediaSuccess() {
902-
if (self.status === JsSIP.c.SESSION_TERMINATED) {
934+
if (self.isCanceled || self.status === JsSIP.c.SESSION_TERMINATED) {
903935
self.mediaSession.close();
904936
return;
905937
}

src/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ JsSIP.c = {
1717
LOG_DIGEST_AUTHENTICATION: JsSIP.name() +' | '+ 'DIGEST AUTHENTICATION' +' | ',
1818
LOG_SANITY_CHECK: JsSIP.name() +' | '+ 'SANITY CHECK' +' | ',
1919
LOG_UTILS: JsSIP.name() +' | '+ 'UTILS' +' | ',
20+
LOG_EXCEPTION: JsSIP.name() +' | '+ 'EXCEPTION' +' | ',
2021

2122
// Classes
2223
LOG_TRANSPORT: JsSIP.name() +' | '+ 'TRANSPORT' +' | ',

src/exceptions.js

+25-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ JsSIP.exceptions = {
1313
var exception = function() {
1414
this.code = 1;
1515
this.name = 'CONFIGURATION_ERROR';
16-
this.message = this.name +': JsSIP Exception '+ this.code;
16+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
1717
};
1818
exception.prototype = new Error();
1919
return exception;
@@ -23,7 +23,7 @@ JsSIP.exceptions = {
2323
var exception = function() {
2424
this.code = 2;
2525
this.name = 'NOT_READY_ERROR';
26-
this.message = this.name +': JsSIP Exception '+ this.code;
26+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
2727
};
2828
exception.prototype = new Error();
2929
return exception;
@@ -33,7 +33,7 @@ JsSIP.exceptions = {
3333
var exception = function() {
3434
this.code = 3;
3535
this.name = 'INVALID_TARGET_ERROR';
36-
this.message = this.name +': JsSIP Exception '+ this.code;
36+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
3737
};
3838
exception.prototype = new Error();
3939
return exception;
@@ -43,7 +43,7 @@ JsSIP.exceptions = {
4343
var exception = function(){
4444
this.code = 4;
4545
this.name = 'WEBRTC_NO_SUPPORTED_ERROR';
46-
this.message = this.name +': JsSIP Exception '+ this.code;
46+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
4747
};
4848
exception.prototype = new Error();
4949
return exception;
@@ -53,7 +53,27 @@ JsSIP.exceptions = {
5353
var exception = function() {
5454
this.code = 5;
5555
this.name = 'INVALID_STATE_ERROR';
56-
this.message = this.name +': JsSIP Exception '+ this.code;
56+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
57+
};
58+
exception.prototype = new Error();
59+
return exception;
60+
}()),
61+
62+
InvalidMethodError: (function(){
63+
var exception = function() {
64+
this.code = 6;
65+
this.name = 'INVALID_METHOD_ERROR';
66+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
67+
};
68+
exception.prototype = new Error();
69+
return exception;
70+
}()),
71+
72+
InvalidValueError: (function(){
73+
var exception = function() {
74+
this.code = 7;
75+
this.name = 'INVALID_VALUE_ERROR';
76+
this.message = JsSIP.c.LOG_EXCEPTION + this.code;
5777
};
5878
exception.prototype = new Error();
5979
return exception;

0 commit comments

Comments
 (0)