bigbluebutton-Github/bigbluebutton-client/resources/prod/lib/vertxbus.js
2018-04-23 15:49:07 -07:00

229 lines
6.8 KiB
JavaScript
Executable File

/*
* Copyright 2014 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
var vertx = vertx || {};
!function(factory) {
if (typeof define === "function" && define.amd) {
// Expose as an AMD module with SockJS dependency.
// "vertxbus" and "sockjs" names are used because
// AMD module names are derived from file names.
define("vertxbus", ["sockjs"], factory);
} else {
// No AMD-compliant loader
factory(SockJS);
}
}(function(SockJS) {
vertx.EventBus = function(url, options) {
var that = this;
var sockJSConn = new SockJS(url, undefined, options);
var handlerMap = {};
var replyHandlers = {};
var state = vertx.EventBus.CONNECTING;
var pingTimerID = null;
var pingInterval = null;
if (options) {
pingInterval = options['vertxbus_ping_interval'];
}
if (!pingInterval) {
pingInterval = 5000;
}
that.onopen = null;
that.onclose = null;
that.send = function(address, message, replyHandler) {
sendOrPub("send", address, message, replyHandler)
}
that.publish = function(address, message) {
sendOrPub("publish", address, message, null)
}
that.registerHandler = function(address, handler) {
checkSpecified("address", 'string', address);
checkSpecified("handler", 'function', handler);
checkOpen();
var handlers = handlerMap[address];
if (!handlers) {
handlers = [handler];
handlerMap[address] = handlers;
// First handler for this address so we should register the connection
var msg = { type : "register",
address: address };
sockJSConn.send(JSON.stringify(msg));
} else {
handlers[handlers.length] = handler;
}
}
that.unregisterHandler = function(address, handler) {
checkSpecified("address", 'string', address);
checkSpecified("handler", 'function', handler);
checkOpen();
var handlers = handlerMap[address];
if (handlers) {
var idx = handlers.indexOf(handler);
if (idx != -1) handlers.splice(idx, 1);
if (handlers.length == 0) {
// No more local handlers so we should unregister the connection
var msg = { type : "unregister",
address: address};
sockJSConn.send(JSON.stringify(msg));
delete handlerMap[address];
}
}
}
that.close = function() {
checkOpen();
state = vertx.EventBus.CLOSING;
sockJSConn.close();
}
that.readyState = function() {
return state;
}
sockJSConn.onopen = function() {
// Send the first ping then send a ping every pingInterval milliseconds
sendPing();
pingTimerID = setInterval(sendPing, pingInterval);
state = vertx.EventBus.OPEN;
if (that.onopen) {
that.onopen();
}
};
sockJSConn.onclose = function() {
state = vertx.EventBus.CLOSED;
if (pingTimerID) clearInterval(pingTimerID);
if (that.onclose) {
that.onclose();
}
};
sockJSConn.onmessage = function(e) {
var msg = e.data;
var json = JSON.parse(msg);
var type = json.type;
if (type === 'err') {
console.error("Error received on connection: " + JSON.stringify(json));
return;
}
var body = json.body;
var replyAddress = json.replyAddress;
var address = json.address;
var replyHandler;
if (replyAddress) {
replyHandler = function(reply, replyHandler) {
// Send back reply
that.send(replyAddress, reply, replyHandler);
};
}
var handlers = handlerMap[address];
if (handlers) {
// We make a copy since the handler might get unregistered from within the
// handler itself, which would screw up our iteration
var copy = handlers.slice(0);
for (var i = 0; i < copy.length; i++) {
copy[i](body, replyHandler);
}
} else {
// Might be a reply message
var handler = replyHandlers[address];
if (handler) {
delete replyHandlers[address];
handler(body, replyHandler);
}
}
}
function sendPing() {
var msg = {
type: "ping"
}
sockJSConn.send(JSON.stringify(msg));
}
function sendOrPub(sendOrPub, address, message, replyHandler) {
checkSpecified("address", 'string', address);
checkSpecified("replyHandler", 'function', replyHandler, true);
checkOpen();
var envelope = { type : sendOrPub,
address: address,
body: message };
if (replyHandler) {
var replyAddress = makeUUID();
envelope.replyAddress = replyAddress;
replyHandlers[replyAddress] = replyHandler;
}
var str = JSON.stringify(envelope);
sockJSConn.send(str);
}
function checkOpen() {
if (state != vertx.EventBus.OPEN) {
throw new Error('INVALID_STATE_ERR');
}
}
function checkSpecified(paramName, paramType, param, optional) {
if (!optional && !param) {
throw new Error("Parameter " + paramName + " must be specified");
}
if (param && typeof param != paramType) {
throw new Error("Parameter " + paramName + " must be of type " + paramType);
}
}
function isFunction(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
}
function makeUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
.replace(/[xy]/g,function(a,b){return b=Math.random()*16,(a=="y"?b&3|8:b|0).toString(16)})}
}
vertx.EventBus.CONNECTING = 0;
vertx.EventBus.OPEN = 1;
vertx.EventBus.CLOSING = 2;
vertx.EventBus.CLOSED = 3;
return vertx.EventBus;
});