Skip to content

Commit defeabe

Browse files
committed
Automatic connection recovery.
New configuration parameter: 'connection_recovery_min_interval' (seconds) New configuration parameter: 'connection_recovery_max_interval' (seconds) When all outbound proxies get unreachable, User Agent attemps to reconnect applying an exponential backoff algorithm, which takes the minimum and maximum reconnection interval values from those new configuration parameters.
1 parent 4b1adf9 commit defeabe

File tree

2 files changed

+82
-22
lines changed

2 files changed

+82
-22
lines changed

src/Transport.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -239,16 +239,14 @@ JsSIP.Transport.prototype = {
239239

240240
this.reconnection_attempts += 1;
241241

242-
if(this.reconnection_attempts > this.ua.configuration.max_reconnection) {
242+
if(this.reconnection_attempts > this.ua.configuration.ws_server_max_reconnection) {
243243
console.log(JsSIP.c.LOG_TRANSPORT +'Maximum reconnection attempts for: ' + this.server.ws_uri);
244244
this.ua.onTransportError(this);
245245
} else {
246246
console.log(JsSIP.c.LOG_TRANSPORT +'Trying to reconnect to: ' + this.server.ws_uri + '. Reconnection attempt number ' + this.reconnection_attempts);
247247

248248
this.reconnectTimer = window.setTimeout(function() {
249-
transport.reConnect();}, this.ua.configuration.reconnection_timeout * 1000);
250-
251-
this.connect();
249+
transport.connect();}, this.ua.configuration.ws_server_reconnection_timeout * 1000);
252250
}
253251
}
254252
};

src/UA.js

+80-18
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ JsSIP.UA = function(configuration) {
4242
ict: {}
4343
};
4444

45+
this.transportRecoverAttempts = 0;
46+
4547
/**
4648
* Load configuration
4749
*
@@ -61,17 +63,6 @@ JsSIP.UA.prototype = new JsSIP.EventEmitter();
6163
// High Level API
6264
//=================
6365

64-
/**
65-
* Notify the UA about network availability.
66-
*/
67-
JsSIP.UA.prototype.networkIsReady = function() {
68-
console.log('Network Ready notification received');
69-
// Stablish connection if needed.
70-
if(this.status === JsSIP.c.UA_STATUS_NOT_READY && this.error === JsSIP.c.UA_NETWORK_ERROR) {
71-
this.transport.connect();
72-
}
73-
};
74-
7566
/**
7667
* Register.
7768
*
@@ -316,9 +307,14 @@ JsSIP.UA.prototype.onTransportError = function(transport) {
316307
new JsSIP.Transport(this, server);
317308
}else {
318309
this.closeSessionsOnTransportError();
319-
this.status = JsSIP.c.UA_STATUS_NOT_READY;
320-
this.error = JsSIP.c.UA_NETWORK_ERROR;
321-
this.emit('disconnected');
310+
if (!this.error || this.error !== JsSIP.c.UA_NETWORK_ERROR) {
311+
this.status = JsSIP.c.UA_STATUS_NOT_READY;
312+
this.error = JsSIP.c.UA_NETWORK_ERROR;
313+
this.emit('disconnected');
314+
}
315+
316+
// Transport Recovery process
317+
this.recoverTransport();
322318
}
323319
};
324320

@@ -331,6 +327,9 @@ JsSIP.UA.prototype.onTransportError = function(transport) {
331327
JsSIP.UA.prototype.onTransportConnected = function(transport) {
332328
this.transport = transport;
333329

330+
// Reset transport recovery counter
331+
this.transportRecoverAttempts = 0;
332+
334333
transport.server.status = JsSIP.c.WS_SERVER_READY;
335334
console.log(JsSIP.c.LOG_UA +'connection status set to: '+ JsSIP.c.WS_SERVER_READY);
336335

@@ -569,6 +568,36 @@ JsSIP.UA.prototype.closeSessionsOnTransportError = function() {
569568
}
570569
};
571570

571+
JsSIP.UA.prototype.recoverTransport = function(ua) {
572+
var idx, k, nextRetry, count, server;
573+
574+
ua = ua || this;
575+
count = ua.transportRecoverAttempts;
576+
577+
for (idx in ua.configuration.outbound_proxy_set) {
578+
ua.configuration.outbound_proxy_set[idx].status = 0;
579+
}
580+
581+
server = ua.getNextWsServer();
582+
583+
k = Math.floor((Math.random() * Math.pow(2,count)) +1);
584+
nextRetry = k * ua.configuration.connection_recovery_min_interval;
585+
586+
if (nextRetry > ua.configuration.connection_recovery_max_interval) {
587+
console.log(JsSIP.c.LOG_UA + 'Time for next connection attempt exceeds connection_recovery_max_interval. Resetting counter');
588+
nextRetry = ua.configuration.connection_recovery_min_interval;
589+
count = 0;
590+
}
591+
592+
console.log(JsSIP.c.LOG_UA + 'Next connection attempt in: '+ nextRetry +' seconds');
593+
594+
window.setTimeout(
595+
function(){
596+
ua.transportRecoverAttempts = count + 1;
597+
new JsSIP.Transport(ua, server);
598+
}, nextRetry * 1000);
599+
};
600+
572601
/**
573602
* Configuration load.
574603
* @private
@@ -592,8 +621,11 @@ JsSIP.UA.prototype.loadConfig = function(configuration) {
592621
register: true,
593622

594623
// Transport related parameters
595-
max_reconnection: 3,
596-
reconnection_timeout: 4,
624+
ws_server_max_reconnection: 3,
625+
ws_server_reconnection_timeout: 4,
626+
627+
connection_recovery_min_interval: 2,
628+
connection_recovery_max_interval: 30,
597629

598630
// Session parameters
599631
no_answer_timeout: 60,
@@ -654,6 +686,14 @@ JsSIP.UA.prototype.loadConfig = function(configuration) {
654686
}
655687
}
656688

689+
// Sanity Checks
690+
691+
// Connection recovery intervals
692+
if(settings.connection_recovery_max_interval < settings.connection_recovery_min_interval) {
693+
console.error('"connection_recovery_max_interval" parameter is lower than "connection_recovery_min_interval"');
694+
return false;
695+
}
696+
657697
// Post Configuration Process
658698

659699
// Instance-id for GRUU
@@ -731,9 +771,13 @@ JsSIP.UA.configuration_skeleton = (function() {
731771
// Internal parameters
732772
"instance_id",
733773
"jssip_id",
734-
"max_reconnection",
735774

736-
"reconnection_timeout",
775+
"ws_server_max_reconnection",
776+
"ws_server_reconnection_timeout",
777+
778+
"connection_recovery_min_interval",
779+
"connection_recovery_max_interval",
780+
737781
"register_min_expires",
738782

739783
// Mandatory user configurable parameters
@@ -894,6 +938,24 @@ JsSIP.UA.configuration_check = {
894938
return true;
895939
}
896940
},
941+
connection_recovery_min_interval: function(connection_recovery_min_interval) {
942+
if(!Number(connection_recovery_min_interval)) {
943+
return false;
944+
} else if(connection_recovery_min_interval < 0) {
945+
return false;
946+
} else {
947+
return true;
948+
}
949+
},
950+
connection_recovery_max_interval: function(connection_recovery_max_interval) {
951+
if(!Number(connection_recovery_max_interval)) {
952+
return false;
953+
} else if(connection_recovery_max_interval < 0) {
954+
return false;
955+
} else {
956+
return true;
957+
}
958+
},
897959
hack_via_tcp: function(hack_via_tcp) {
898960
if(typeof hack_via_tcp !== 'boolean') {
899961
return false;

0 commit comments

Comments
 (0)