openvidu-browser: reconnection fix for unexpected ws close (HttpSession expiring)

pull/178/head
pabloFuente 2019-01-14 10:18:04 +01:00
parent 05dc6e21aa
commit cb8594373e
6 changed files with 83 additions and 66 deletions

View File

@ -59,6 +59,11 @@ export class Connection {
*/
disposed = false;
/**
* @hidden
*/
rpcSessionId: string;
/**
* @hidden
*/

View File

@ -636,7 +636,7 @@ export class OpenVidu {
* @hidden
*/
closeWs(): void {
this.jsonRpcClient.close();
this.jsonRpcClient.close(4102, "Connection closed by client");
}
/**
@ -678,7 +678,7 @@ export class OpenVidu {
private disconnectCallback(): void {
console.warn('Websocket connection lost');
if (this.isRoomAvailable()) {
this.session.onLostConnection();
this.session.onLostConnection('networkDisconnect');
} else {
alert('Connection error. Please reload page.');
}
@ -686,9 +686,7 @@ export class OpenVidu {
private reconnectingCallback(): void {
console.warn('Websocket connection lost (reconnecting)');
if (this.isRoomAvailable()) {
this.session.onLostConnection();
} else {
if (!this.isRoomAvailable()) {
alert('Connection error. Please reload page.');
}
}
@ -696,7 +694,16 @@ export class OpenVidu {
private reconnectedCallback(): void {
console.warn('Websocket reconnected');
if (this.isRoomAvailable()) {
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
if (!!error) {
console.error(error);
this.session.onLostConnection("networkDisconnect");
this.jsonRpcClient.close(4101, "Reconnection fault");
} else {
this.jsonRpcClient.resetPing();
this.session.onRecoveredConnection();
}
});
} else {
alert('Connection error. Please reload page.');
}

View File

@ -899,22 +899,10 @@ export class Session implements EventDispatcher {
/**
* @hidden
*/
onLostConnection(): void {
/*if (!this.connection) {
console.warn('Not connected to session: if you are not debugging, this is probably a certificate error');
const url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/openvidu')[0];
if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) {
location.assign(url + '/accept-certificate');
}
return;
}*/
console.warn('Lost connection in Session ' + this.sessionId);
onLostConnection(reason: string): void {
console.warn('Lost connection in session ' + this.sessionId + ' waiting for reconnect');
if (!!this.sessionId && !this.connection.disposed) {
this.leave(true, 'networkDisconnect');
this.leave(true, reason);
}
}
@ -923,7 +911,7 @@ export class Session implements EventDispatcher {
*/
onRecoveredConnection(): void {
console.warn('Recovered connection in Session ' + this.sessionId);
this.ee.emitEvent('connectionRecovered', []);
// this.ee.emitEvent('connectionRecovered', []);
}
/**
@ -1048,6 +1036,7 @@ export class Session implements EventDispatcher {
this.connection.connectionId = response.id;
this.connection.creationTime = response.createdAt;
this.connection.data = response.metadata;
this.connection.rpcSessionId = response.sessionId;
// Initialize remote Connections with value returned by openvidu-server
const events = {

View File

@ -18,7 +18,7 @@
var RpcBuilder = require('../');
var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
Date.now = Date.now || function() {
Date.now = Date.now || function () {
return +new Date;
};
@ -39,7 +39,7 @@ var Logger = console;
* uri : URI to conntect to,
* useSockJS : true (use SockJS) / false (use WebSocket) by default,
* onconnected : callback method to invoke when connection is successful,
* ondisconnect : callback method to invoke when the connection is lost,
* ondisconnect : callback method to invoke when the connection is lost (max retries for reconnecting reached),
* onreconnecting : callback method to invoke when the client is reconnecting,
* onreconnected : callback method to invoke when the client successfully reconnects,
* onerror : callback method to invoke when there is an error
@ -71,24 +71,26 @@ function JsonRpcClient(configuration) {
var onconnected = wsConfig.onconnected;
var onerror = wsConfig.onerror;
configuration.rpc.pull = function(params, request) {
configuration.rpc.pull = function (params, request) {
request.reply(null, "push");
}
wsConfig.onreconnecting = function() {
wsConfig.onreconnecting = function () {
Logger.debug("--------- ONRECONNECTING -----------");
if (status === RECONNECTING) {
Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
return;
}
stopPing();
status = RECONNECTING;
if (onreconnecting) {
onreconnecting();
}
}
wsConfig.onreconnected = function() {
wsConfig.onreconnected = function () {
Logger.debug("--------- ONRECONNECTED -----------");
if (status === CONNECTED) {
Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
@ -96,16 +98,14 @@ function JsonRpcClient(configuration) {
}
status = CONNECTED;
enabledPings = true;
updateNotReconnectIfLessThan();
usePing();
if (onreconnected) {
onreconnected();
}
}
wsConfig.onconnected = function() {
wsConfig.onconnected = function () {
Logger.debug("--------- ONCONNECTED -----------");
if (status === CONNECTED) {
Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
@ -121,11 +121,13 @@ function JsonRpcClient(configuration) {
}
}
wsConfig.onerror = function(error) {
wsConfig.onerror = function (error) {
Logger.debug("--------- ONERROR -----------");
status = DISCONNECTED;
stopPing();
if (onerror) {
onerror(error);
}
@ -141,7 +143,7 @@ function JsonRpcClient(configuration) {
};
var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws,
function(request) {
function (request) {
Logger.debug('Received request: ' + JSON.stringify(request));
@ -159,14 +161,14 @@ function JsonRpcClient(configuration) {
}
});
this.send = function(method, params, callback) {
this.send = function (method, params, callback) {
if (method !== 'ping') {
Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
}
var requestTime = Date.now();
rpc.encode(method, params, function(error, result) {
rpc.encode(method, params, function (error, result) {
if (error) {
try {
Logger.error("ERROR:" + error.message + " in Request: method:" +
@ -203,8 +205,8 @@ function JsonRpcClient(configuration) {
}
pingNextNum++;
self.send('ping', params, (function(pingNum) {
return function(error, result) {
self.send('ping', params, (function (pingNum) {
return function (error, result) {
if (error) {
Logger.debug("Error in ping request #" + pingNum + " (" +
error.message + ")");
@ -239,8 +241,16 @@ function JsonRpcClient(configuration) {
}
}
this.close = function() {
Logger.debug("Closing jsonRpcClient explicitly by client");
function stopPing() {
clearInterval(pingInterval);
pingPongStarted = false;
enabledPings = false;
pingNextNum = -1;
rpc.cancel();
}
this.close = function (code, reason) {
Logger.debug("Closing with code: " + code + " because: " + reason);
if (pingInterval != undefined) {
Logger.debug("Clearing ping interval");
@ -251,25 +261,31 @@ function JsonRpcClient(configuration) {
if (configuration.sendCloseMessage) {
Logger.debug("Sending close message")
this.send('closeSession', null, function(error, result) {
this.send('closeSession', null, function (error, result) {
if (error) {
Logger.error("Error sending close message: " + JSON.stringify(error));
}
ws.close();
ws.close(code, reason);
});
} else {
ws.close();
ws.close(code, reason);
}
}
// This method is only for testing
this.forceClose = function(millis) {
this.forceClose = function (millis) {
ws.forceClose(millis);
}
this.reconnect = function() {
this.reconnect = function () {
ws.reconnectWs();
}
this.resetPing = function () {
enabledPings = true;
pingNextNum = 0;
usePing();
}
}

View File

@ -48,7 +48,7 @@ config = {
uri : wsUri,
useSockJS : true (use SockJS) / false (use WebSocket) by default,
onconnected : callback method to invoke when connection is successful,
ondisconnect : callback method to invoke when the connection is lost,
ondisconnect : callback method to invoke when the connection is lost (max retries for reconnecting reached),
onreconnecting : callback method to invoke when the client is reconnecting,
onreconnected : callback method to invoke when the client successfully reconnects,
};
@ -71,14 +71,14 @@ function WebSocketWithReconnection(config) {
ws = new WebSocket(wsUri);
}
ws.onopen = function() {
ws.onopen = function () {
logConnected(ws, wsUri);
if (config.onconnected) {
config.onconnected();
}
};
ws.onerror = function(error) {
ws.onerror = function (error) {
Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
if (config.onerror) {
config.onerror(error);
@ -93,7 +93,7 @@ function WebSocketWithReconnection(config) {
}
}
var reconnectionOnClose = function() {
var reconnectionOnClose = function () {
if (ws.readyState === CLOSED) {
if (closing) {
Logger.debug("Connection closed by user");
@ -129,11 +129,11 @@ function WebSocketWithReconnection(config) {
} else {
if (config.newWsUriOnReconnection) {
config.newWsUriOnReconnection(function(error, newWsUri) {
config.newWsUriOnReconnection(function (error, newWsUri) {
if (error) {
Logger.debug(error);
setTimeout(function() {
setTimeout(function () {
reconnectToSameUri(maxRetries, numRetries + 1);
}, RETRY_TIME_MS);
} else {
@ -161,7 +161,7 @@ function WebSocketWithReconnection(config) {
newWs = new WebSocket(wsUri);
}
newWs.onopen = function() {
newWs.onopen = function () {
Logger.debug("Reconnected after " + numRetries + " attempts...");
logConnected(newWs, wsUri);
reconnecting = false;
@ -173,7 +173,7 @@ function WebSocketWithReconnection(config) {
newWs.onclose = reconnectionOnClose;
};
var onErrorOrClose = function(error) {
var onErrorOrClose = function (error) {
Logger.warn("Reconnection error: ", error);
if (numRetries === maxRetries) {
@ -181,7 +181,7 @@ function WebSocketWithReconnection(config) {
config.ondisconnect();
}
} else {
setTimeout(function() {
setTimeout(function () {
reconnectToSameUri(maxRetries, numRetries + 1);
}, RETRY_TIME_MS);
}
@ -192,14 +192,14 @@ function WebSocketWithReconnection(config) {
ws = newWs;
}
this.close = function() {
this.close = function () {
closing = true;
ws.close();
};
// This method is only for testing
this.forceClose = function(millis) {
this.forceClose = function (millis) {
Logger.debug("Testing: Force WebSocket close");
if (millis) {
@ -209,7 +209,7 @@ function WebSocketWithReconnection(config) {
forcingDisconnection = true;
setTimeout(function() {
setTimeout(function () {
Logger.debug("Testing: Recover good wsUri " + goodWsUri);
wsUri = goodWsUri;
@ -221,17 +221,17 @@ function WebSocketWithReconnection(config) {
ws.close();
};
this.reconnectWs = function() {
this.reconnectWs = function () {
Logger.debug("reconnectWs");
reconnectToSameUri(MAX_RETRIES, 1);
};
this.send = function(message) {
this.send = function (message) {
ws.send(message);
};
this.addEventListener = function(type, callback) {
registerMessageHandler = function() {
this.addEventListener = function (type, callback) {
registerMessageHandler = function () {
ws.addEventListener(type, callback);
};

View File

@ -519,7 +519,7 @@ function RpcBuilder(packer, options, transport, onRequest)
// Prevent to receive new messages
var transport = this.getTransport();
if(transport && transport.close)
transport.close();
transport.close(4003, "Cancel request");
// Request & processed responses
this.cancel();