demo/3d_demo/resources/src/js/ws_msgpack.js

var WebsocketMsgPack = function () {
// Exported module
var lib = {}
/** -----------------------------
* Private variables
*/
var ws = null
var connected = false
var wsTimer = null
var savedUrl = null
var forcedClosed = false
var logger = Logger('[WSMSGPACK] ')
/** -----------------------------
* Public variables
*/
lib.reconnectPeriod = 3000
lib.onConnected = null
lib.onDisconnected = null
lib.onMessage = null
/** -----------------------------
* Public methods
*/
/**
*
*/
lib.isConnected = function() {
return !!ws && connected
}
/**
*
*/
lib.isConnecting = function() {
return (!!ws || !!wsTimer) && !connected
}
/**
* Open websocket
*/
lib.open = function(url) {
if(connected) {
throw Error('Already connected')
}
if(ws) {
logger.warn('Already attempting to connect ...')
return
}
if(!url) {
url = savedUrl
}
if(!url) {
throw Error('Must provide URL')
}
if(!url.startsWith('ws://') && !url.startsWith('wss://')) {
url = 'ws://' + url
}
if(wsTimer) {
clearTimeout(wsTimer)
wsTimer = null
}
forcedClosed = false
savedUrl = url
logger.info('Opening connection to ' + url + ' ...')
ws = new WebSocket(url)
ws.onerror = onWsOpenFailed
ws.onmessage = onWsMessage
ws.onopen = onWsOpen
}
/**
* Close connection
*/
lib.close = function() {
if(wsTimer) {
clearTimeout(wsTimer)
wsTimer = null
}
forcedClosed = true
if(ws) {
logger.info('Closing connection')
connected = false
ws.close()
ws = null
} else {
if(lib.onDisconnected) {
lib.onDisconnected()
}
}
}
/**
* Send message
*/
lib.send = function(msg) {
if(!connected) {
throw new Error('Not connected')
}
var d
try {
d = msgpack.encode(msg)
} catch(e) {
throw new Error('Failed to encode msg, err: ' + e)
return
}
try {
ws.send(d)
} catch(e) {
throw new Error('Failed to send msg, err: ' + e)
}
}
/**
* Set the logger
*/
lib.setLogger = function(l) {
logger.setLogger(l)
}
/** -----------------------------
* Private methods
*/
/**
*
*/
var onWsOpenFailed = function(msg) {
if(connected) {
return
}
logger.error('Failed to open connection, err: ' + msg.toString())
wsTimer = null
ws = null
if(forcedClosed) {
if(lib.onDisconnected) {
lib.onDisconnected()
}
}
else if(lib.reconnectPeriod) {
logger.info('Re-opening connection in ' + lib.reconnectPeriod + 'ms ...')
wsTimer = setTimeout(lib.open, lib.reconnectPeriod)
}
}
/**
*
*/
var onWsOpen = function() {
logger.info('Connection opened')
ws.onclose = onWsClose
connected = true
if(lib.onConnected) {
lib.onConnected()
}
}
/**
*
*/
var onWsClose = function() {
logger.info('Connection closed')
ws = null
wsTimer = null
connected = false
if(lib.onDisconnected) {
lib.onDisconnected()
}
if(lib.reconnectPeriod && !forcedClosed) {
logger.info('Re-opening connection ...')
wsTimer = setTimeout(lib.open, 100)
}
}
/**
*
*/
var onWsMessage = function(event) {
logger.debug('RX msg')
if(!lib.onMessage) {
logger.warn('No onMessage handler specified, dropping RX msg')
return
}
if(event.data instanceof Blob) {
var reader = new FileReader()
reader.onload = function() {
var msg
try {
var d = new Uint8Array(reader.result)
msg = msgpack.decode(d);
} catch(e) {
logger.error('Failed to decode RX msg, err: ' + e)
return
}
try {
lib.onMessage(msg)
} catch(e) {
logger.error('Unhandler error while processing msg, err: ' + e)
}
};
reader.readAsArrayBuffer(event.data);
} else {
logger.warn('RX msg NOT instance of Blob, dropping msg')
}
}
return lib
};