diffusion
Version:
Diffusion JavaScript client
116 lines (95 loc) • 3.28 kB
JavaScript
/*eslint valid-jsdoc: "off"*/
/*global Uint8Array*/
var encodeAsString = require('v4-stack/credential-tunnel').encodeAsString;
var Emitter = require('events/emitter');
var log = require('util/logger').create('Websocket transport');
/**
* Construct a valid websocket URI from the given options.
*
* @param {Options} opts - The connection options.
* @returns {String} The connection URI
*/
function constructURI(req, opts) {
var scheme = opts.secure ? 'wss' : 'ws';
var uri = scheme + "://" + opts.host + ":" + opts.port + opts.path;
uri += '?ty=' + req.type;
uri += '&v=' + req.version;
uri += '&ca=' + req.capabilities;
uri += '&r=' + opts.reconnect.timeout;
if (req.token) {
uri += '&c=' + encodeURIComponent(req.token);
uri += "&cs=" + req.availableClientSequence;
uri += "&ss=" + req.lastServerSequence;
}
if (opts.properties) {
uri += "&sp=" + encodeURIComponent(JSON.stringify(opts.properties));
}
if (opts.principal) {
uri += "&username=" + encodeURIComponent(opts.principal);
uri += "&password=" + encodeURIComponent(encodeAsString(opts.credentials));
}
return uri;
}
function WSTransport(opts, constructor) {
var emitter = Emitter.assign(this);
var handler = function(message) {
if (message.data.length > opts.maxMessageSize) {
emitter.error(new Error(
"Received message of size: " +
message.data.length +
", exceeding max message size: " +
opts.maxMessageSize));
} else {
emitter.emit('data', new Buffer(new Uint8Array(message.data)));
}
};
var socket;
/**
* Establish a websocket connection, with provided connection options and
* callback functions.
*
* @param {Object} req - Connection request
* @param {Function} handshake - The handshake handler function
* @param {Function} dataWritten - The data written handler
*/
this.connect = function connect(req, handshake) {
try {
var uri = constructURI(req, opts);
socket = new constructor(uri);
log.debug("Created websocket", uri);
} catch (error) {
throw new Error('Unable to construct WebSocket', error);
}
socket.binaryType = "arraybuffer";
socket.onmessage = function(msg) {
socket.onmessage = handler;
socket.onerror = emitter.error;
handshake(new Buffer(new Uint8Array(msg.data)));
};
socket.onclose = emitter.close;
socket.onerror = emitter.close;
};
/**
* Send a binary message to the server.
*
* @param {Buffer} message - The message to send
*/
this.dispatch = function dispatch(message) {
log.debug("Sending websocket message", message);
try {
socket.send(message);
return true;
} catch (err) {
log.error("Websocket send error", err);
return false;
}
};
/**
* Directly close the websocket connection.
*/
this.close = function() {
log.debug("Closing websocket");
socket.close(1000);
};
}
module.exports = WSTransport;