UNPKG

lumberjack-protocol

Version:

Node.js implementation of the lumberjack protocol.

136 lines (109 loc) 4.42 kB
// Generated by CoffeeScript 1.12.1 (function() { var ClientSocket, DEFAULT_WINDOW_SIZE, DroppedError, EventEmitter, MAX_UINT_32, SEND_WINDOW_SIZE_FACTOR, assert, id, lumberjack, tls, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; assert = require('assert'); EventEmitter = require('events').EventEmitter; tls = require('tls'); lumberjack = require('./lumberjack'); MAX_UINT_32 = require('./constants').MAX_UINT_32; DEFAULT_WINDOW_SIZE = 1000; SEND_WINDOW_SIZE_FACTOR = 10; DroppedError = function(message) { Error.captureStackTrace(this, lumberjack.TooShortError); this.name = 'DroppedError'; return this.message = message; }; DroppedError.prototype = Object.create(Error.prototype); id = 0; ClientSocket = (function(superClass) { extend(ClientSocket, superClass); ClientSocket.prototype.DroppedError = DroppedError; function ClientSocket(options) { var ref; this.options = options != null ? options : {}; this._onData = bind(this._onData, this); this._disconnect = bind(this._disconnect, this); this.connected = false; this._closed = false; this.id = id++; this._windowSize = (ref = this.options.windowSize) != null ? ref : DEFAULT_WINDOW_SIZE; this._nextSequenceNumber = 1; this.lastAck = 0; this._parser = new lumberjack.Parser(); this._parser.on('data', this._onData); this._parser.on('error', this._disconnect); } ClientSocket.prototype.connect = function(tlsConnectOptions) { this._socket = tls.connect(tlsConnectOptions); this._socket.on('secureConnect', (function(_this) { return function() { return _this._socket.write(lumberjack.makeWindowSizeFrame(_this._windowSize), null, function() { _this.connected = true; return _this.emit('connect'); }); }; })(this)); this._socket.on('error', this._disconnect); this._socket.on('end', this._disconnect); return this._socket.pipe(this._parser); }; ClientSocket.prototype._disconnect = function(err) { if (this._closed) { return; } if (err) { this.emit('error', err); } else { this.emit('end'); } this.connected = false; if (this._socket) { this._socket.removeAllListeners(); this._socket.on('error', function() {}); } this._socket = null; return this.removeAllListeners(); }; ClientSocket.prototype._onData = function(data) { assert(data.type === 'ack', "Receiver should only ever send 'ack' messages: " + data.type); this.lastAck = data.seq; return this.emit('ack', data.seq); }; ClientSocket.prototype._getSequenceNumber = function() { this.lastSequenceNumber = this._nextSequenceNumber++; if (this._nextSequenceNumber > MAX_UINT_32) { this._nextSequenceNumber = 0; } return this.lastSequenceNumber; }; ClientSocket.prototype.writeDataFrame = function(data, done) { var drop; if (!this.connected) { done(new Error("Can't write data when not connected.")); } drop = ((this._nextSequenceNumber - this.lastAck) > (this._windowSize * SEND_WINDOW_SIZE_FACTOR)) && ((this.options.allowDrop == null) || !!this.options.allowDrop(data)); if (drop) { this.emit('dropped', 1); return done(new DroppedError("Dropped message")); } else { return this._socket.write(lumberjack.makeDataFrame(this._getSequenceNumber(), data), null, done); } }; ClientSocket.prototype.getLastSequenceNumber = function() { return this._nextSequenceNumber - 1; }; ClientSocket.prototype.close = function() { this._closed = true; return this._disconnect(); }; ClientSocket.prototype.unref = function() { return this._socket.unref(); }; return ClientSocket; })(EventEmitter); module.exports = ClientSocket; module.exports.DroppedError = DroppedError; }).call(this);