UNPKG

mediaproxy

Version:
281 lines (258 loc) 8.86 kB
// Generated by CoffeeScript 1.6.3 (function() { var EventEmitter, MediaProxy, SingleMediaProxy, assert, dgram, log, __hasProp = {}.hasOwnProperty, __extends = 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; }; dgram = require('dgram'); assert = require('assert'); EventEmitter = require('events').EventEmitter; log = require('util').log; SingleMediaProxy = (function(_super) { __extends(SingleMediaProxy, _super); function SingleMediaProxy(local, remote) { var _ref, _this = this; this.local = local; this.remote = remote; assert(this.local != null, 'local is required'); assert(((_ref = this.local) != null ? _ref.port : void 0) != null, 'local.port is required'); this.sent = 0; this.received = 0; this.errors = 0; this.local.socket = dgram.createSocket('udp4'); this.local.socket.on('error', function(err) { log("Received error " + err + " on port " + _this.local.port); return _this.emit('error', err); }); this.local.socket.on('message', function(msg, rinfo) { _this.received += 1; if (_this.remote == null) { _this.remote = rinfo; } _this.emit('message', msg, rinfo); return _this.renew_timeout(); }); if ((this.local.address != null) && this.local.address !== '0.0.0.0' && this.local.address !== '::') { this.local.socket.bind(this.local.port, this.local.address); } else { this.local.socket.bind(this.local.port, function() { return _this.local.address = _this.local.socket.address(); }); } this.renew_timeout(); log("SingleMediaProxy ready on port " + this.local.port); return; } SingleMediaProxy.prototype.close = function() { this.local.socket.close(); delete this.local.socket; if (this.local.timeout != null) { clearTimeout(this.local.timeout); delete this.local.timeout; } log("SingleMediaProxy closed on port " + this.local.port); }; SingleMediaProxy.prototype.send = function(buf) { var _this = this; if (this.local.socket == null) { log('Not ready to send, no local socket.'); return; } if ((this.local.socket != null) && (this.remote != null) && (this.remote.address != null) && (this.remote.port != null)) { this.local.socket.send(buf, 0, buf.length, this.remote.port, this.remote.address, function(err, bytes) { if (err != null) { _this.errors += 1; return log("Send failed with " + err); } else { return _this.sent += 1; } }); } else { log('Not ready to send, still missing remote address or port'); } this.renew_timeout(); }; SingleMediaProxy.prototype.renew_timeout = function() { var _this = this; if (this.local.timeout != null) { clearTimeout(this.local.timeout); } this.local.timeout = setTimeout((function() { return _this.emit('timeout'); }), 30000); }; return SingleMediaProxy; })(EventEmitter); module.exports = MediaProxy = (function() { function MediaProxy(config) { var _base, _base1, _base2; this.config = config; if (this.config == null) { this.config = {}; } if ((_base = this.config).ports == null) { _base.ports = {}; } if ((_base1 = this.config.ports).min == null) { _base1.min = 49152; } if ((_base2 = this.config.ports).max == null) { _base2.max = 65535; } this.config.ports.span = Math.floor((this.config.ports.max - this.config.ports.min) / 2); this.by_uuid = {}; this.by_port = {}; } MediaProxy.prototype.allocate_port = function() { var port; port = this.config.ports.min + 2 * Math.floor(this.config.ports.span * Math.random()); while (this.by_port[port] != null) { port += 2; if (port >= this.config.ports.max) { return false; } } return port; }; MediaProxy.prototype.allocate_proxy = function(leg, linfo) { var _ref; if (leg.local == null) { leg.local = { address: (_ref = linfo.address) != null ? _ref : this.config.address, port: linfo.port || this.allocate_port() }; } if (!leg.local.port) { log('Could not allocate a local port.'); leg.error = 'Could not allocate a local port.'; return; } delete leg.error; leg.proxy = new SingleMediaProxy(leg.local, leg.remote); this.by_port[leg.local.port] = leg; log('Allocate proxy successful'); }; MediaProxy.prototype.remove_leg = function(port) { var leg, name, uuid, _ref; leg = this.by_port[port]; if (leg == null) { log("Did not find a leg for port " + port); return false; } name = leg.name; uuid = leg.uuid; if ((_ref = leg.proxy) != null) { _ref.close(); } delete leg.proxy; delete this.by_port[port]; log("Removed leg " + name + " uuid " + uuid); return true; }; MediaProxy.prototype.add = function(uuid, new_legs) { var legs, name, new_leg, _base, _fn, _this = this; if ((_base = this.by_uuid)[uuid] == null) { _base[uuid] = {}; } legs = this.by_uuid[uuid]; _fn = function(name, new_leg) { var leg, _ref, _ref1, _ref2; log("Updating leg " + name + " in uuid " + uuid); leg = (_ref = legs[name]) != null ? _ref : {}; leg.name = name; leg.uuid = uuid; if (leg.remote == null) { leg.remote = new_leg.remote; } if (leg.local == null) { if (new_leg.local != null) { _this.allocate_proxy(leg, new_leg.local); } if ((_ref1 = leg.proxy) != null) { _ref1.on('message', function(msg) { var l, n, _results; _results = []; for (n in legs) { l = legs[n]; if (n !== name) { _results.push((function(l) { var _ref2; return (_ref2 = l.proxy) != null ? _ref2.send(msg) : void 0; })(l)); } } return _results; }); } if ((_ref2 = leg.proxy) != null) { _ref2.on('timeout', function() { log("Received timeout on uuid " + uuid + " leg " + name + "."); return _this.remove(uuid); }); } } return legs[name] = leg; }; for (name in new_legs) { new_leg = new_legs[name]; _fn(name, new_leg); } return log("Add successful for uuid " + uuid); }; MediaProxy.prototype.get = function(uuid) { var legs, name, response, _, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; response = {}; legs = (_ref = this.by_uuid[uuid]) != null ? _ref : {}; for (name in legs) { _ = legs[name]; response[name] = { error: _.error, remote: { address: (_ref1 = _.remote) != null ? _ref1.address : void 0, port: (_ref2 = _.remote) != null ? _ref2.port : void 0 }, local: { address: (_ref3 = _.local) != null ? _ref3.address : void 0, port: (_ref4 = _.local) != null ? _ref4.port : void 0 }, sent: (_ref5 = _.proxy) != null ? _ref5.sent : void 0, received: (_ref6 = _.proxy) != null ? _ref6.received : void 0, errors: (_ref7 = _.proxy) != null ? _ref7.errors : void 0 }; } return response; }; MediaProxy.prototype.remove = function(uuid) { var leg, legs, name; legs = this.by_uuid[uuid]; if (legs == null) { log("Could not find legs for uuid " + uuid); return { error: "Could not find legs for uuid " + uuid }; } for (name in legs) { leg = legs[name]; if (leg.local != null) { this.remove_leg(leg.local.port); } } delete this.by_uuid[uuid]; log("Removed uuid " + uuid); return { ok: true }; }; MediaProxy.prototype.close = function() { var uuid; for (uuid in this.by_uuid) { this.remove(uuid); } delete this.by_uuid; delete this.by_port; log("Closed"); }; return MediaProxy; })(); }).call(this);