barrageapi
Version:
A library for sending data to Barrage, an advanced streaming analytics service from MIOsoft
220 lines (187 loc) • 6.65 kB
JavaScript
var Q = require('q');
var W3CWebSocket = require('websocket').w3cwebsocket;
var ServerMessage = require("./ServerMessage.js");
var fs = require("fs");
var ca = [fs.readFileSync(__dirname + '/root.pem'), fs.readFileSync(__dirname + '/inter1.pem'),fs.readFileSync(__dirname + '/inter2.pem')];
var log = require("./log.js")();
//process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
// websocket factory that return a class that needs to be instatiated in each case - allow multiple websockets
/* WebSocket javascript API
var ws = new WebSocket(url); // url format is "ws://www.example.com/socketserver"
ws.onopen = function(event) { //do something on connecting to the websocket};
ws.onclose = function(event) { //do something after closing the connection };
ws.onerror = function(event) { // };
ws.onmessage = function(event) { //event.data is a message from the server};
ws.send(JSON.stringify(message)); //send message to server
if (ws == true) { //socket is already open };
*/
// ------------ internal private methods ---------
function connectToSocket() {
var self = this;
return Q.Promise(function(resolve,reject) {
log("Connecting to ",self.url);
self.ws = new W3CWebSocket(self.url, null, null, null, null, {tlsOptions: {
ca: ca
}});
self.ws.onopen = function(event) {
log("Socket opened.");
resolve("Success");
};
self.ws.onmessage = function(event) {
listener(self,JSON.parse(event.data));
};
self.ws.onclose = function(event) {
log("Socket closed.", event.code, event.reason);
//Reject all outstanding callbacks
for (var key in self.callbacks) {
if (self.callbacks.hasOwnProperty(key)) {
self.callbacks[key].cb.reject("Socket closed.");
delete self.callbacks[key];
}
}
};
self.ws.onerror = function(event) {
log("Failed to open a connection.");
reject("Failed. This may be because of a failure to open a connection.");
//Reject all outstanding callbacks
for (var key in self.callbacks) {
if (self.callbacks.hasOwnProperty(key)) {
self.callbacks[key].cb.reject("Failed. This may be because of a failure to open a connection.");
delete self.callbacks[key];
}
}
};
});
}
//generate a new deferred promise and unique ID, add this request event to the callbacks array
//attach the ID to the request, send it through the pipe, and return the promise
function sendRequest(request) {
var self = this;
var defer = Q.defer();
//If the socket is not connected, try to connect it and autologin.
if (self.ws.readyState !== 1) {
// Prevent infinite recursion
if (!self.retried) {
self.retried = true;
return connectToSocket.call(self).then(function () {
log("RECONNECTED SOCKET");
//if (self.reconnectObject) {
// return sendRequest.call(self, self.reconnectObject).then(function () {
// log("REGAINED SESSION!!!");
// ServerMessage.broadcast("reconnect", self.ids);
// return sendRequest.call(self,request);
// }).catch(function () {
// if (self.loginObject) {
// return sendRequest.call(self, self.loginObject).then(function () {
// log("RELOGGED IN!!!");
// ServerMessage.broadcast("reconnect", self.ids);
// return sendRequest.call(self,request);
// });
// }
// });
//}
/*else*/ if (self.loginObject) {
return sendRequest.call(self, self.loginObject).then(function () {
log("RELOGGED IN!!!");
ServerMessage.broadcast("reconnect", self.ids);
return sendRequest.call(self,request);
});
}
return sendRequest.call(self,request);
}).finally(function (err) {
self.retried = false;
});
}
return defer.promise;
}
var callbackID = getCallbackID(self);
self.callbacks[callbackID] = {
time: new Date(),
cb: defer
};
request.callbackID = callbackID;
self.ws.send(JSON.stringify(request));
return defer.promise;
}
//function for creating a new callback ID for requests
function getCallbackID(self) {
self.currentCallbackId += 1;
if (self.currentCallbackId > 10000) {
self.currentCallbackId = 1;
}
return self.currentCallbackId;
}
//listener function for processing events/messages from the server
function listener(self,data) {
var messageObj = data;
//if object has a callback_id - resolve the promise by broadcasting though $rootScope (so all controllers can see it)
if (self.callbacks.hasOwnProperty(messageObj.callbackID)) {
//server response
if (messageObj.callbackID > 0) {
self.callbacks[messageObj.callbackID].cb.resolve(messageObj);
delete self.callbacks[messageObj.callbackID];
}
// Messages originating from the server will have callbackID = 0
if (messageObj.callbackID === 0) {
log(messageObj);
ServerMessage.broadcast(messageObj.eventName, messageObj.data);
}
//server unable to process message
else if (messageObj.callbackID === -1) {
log('Server could not process a message from the client far enough to get a callback ID.');
self.callbacks[messageObj.callbackID].cb.reject(messageObj);
delete self.callbacks[messageObj.callbackID];
} else {
//nonvalid callbackID means what?
//log(messageObj);
}
}
else {
//handle messages without callback ids here
log(messageObj);
}
}
// ------------- constructor -------------
function WebSocketClass(url, id) {
this.url = url;
this.ids = [id];
this.currentCallbackId = 0;
this.callbacks = {};
this.ws = {};
this.loginObject = {};
}
// ------------- class methods - websocket API -------------
WebSocketClass.prototype = {
addID : function (newID) {
if (this.ids.indexOf(newID) === -1) {
this.ids.push(newID);
}
},
makeRequest: function(message) {
var self = this;
return sendRequest.call(self,message);
},
cancelAllRequests: function () {
var self = this;
var serviceObject = {service : "cancelService", cancel: Object.keys(self.callbacks).map(function (d) { return +d; })};
return sendRequest.call(self, serviceObject);
},
initializeSocket: function() {
var self = this;
return connectToSocket.call(self);
},
closeSocket: function() {
this.ws.close();
},
checkSocketConnected: function() {
/*
readyState:
0 - connection not yet established
1 - connected established and communication possible
2 - connection going through closing handshake
3 - connection closed (or could not be opened)
*/
return this.ws.readyState === 1;
},
};
module.exports = WebSocketClass;