Files
Zos/Skills/@be/node_modules/udp-streams2/index.js

163 lines
4.3 KiB
JavaScript

'use strict';
var Writable = require('stream').Writable,
inherits = require('util').inherits,
net = require('net'),
dns = require('dns'),
dgram = require('dgram');
function UdpStream() {
Writable.call(this);
this.socket = null;
this.host = null;
this.port = null;
}
inherits(UdpStream, Writable);
UdpStream.create = function (opts, cb) {
var stream = new UdpStream();
process.nextTick(function () {
stream.connect(opts, cb);
});
return stream;
};
UdpStream.parseArgs = function () {
if (arguments.length === 0) { return { }; }
var i = arguments.length, args = new Array(i);
while (i--) { args[i] = arguments[i]; }
var opts = { }, cb;
if (typeof args[args.length-1] === 'function') {
opts.cb = args.pop();
}
if (typeof args[0] === 'number') {
opts.port = args.shift();
}
if (typeof args[0] === 'string') {
opts.host = args.shift();
}
if (args[0] && typeof args[0] === 'object') {
Object.keys(args[0]).forEach(function (key) {
opts[key] = args[0][key];
});
}
if (isNaN(parseInt(opts.port, 10))) {
opts.port = null;//delete opts.port;
}
return opts;
};
UdpStream.prototype.connect = function (/*opts, cb*/) {
var self = this, cb;
var opts = UdpStream.parseArgs.apply(this, arguments);
if (opts.cb) { cb = opts.cb; delete opts.cb; }
var _onError = function (err) {
if (typeof cb === 'function') { cb(err); }
else { self.emit('error', err); }
};
var _onConnect = function () {
if (typeof cb === 'function') { cb(null, self); }
process.nextTick(function () {
self.emit('connect', self);
});
};
if (!opts.host) { opts.host = '127.0.0.1'; }
if (!opts.port) { return _onError(new Error('opts.port is required')); }
var connect = function () {
if (net.isIPv4(opts.host)) {
opts.type = 'udp4';
} else if (net.isIPv6(opts.host)) {
opts.type = 'udp6';
} else {
return _onError(new Error('Invalid host: ' + opts.host));
}
try { self.socket = dgram.createSocket(opts.type); }
catch (e) { return _onError(e); }
self.host = opts.host;
self.port = opts.port;
// udp sockets can only be 'closed' manually, but we call
// socket.close() in the 'end' method
var onError, onClose, cleanup;
onError = function (e) {
cleanup();
self.emit('error', e);
self.end();
};
onClose = function () {
cleanup();
};
cleanup = function () {
self.socket.removeListener('error', onError);
self.socket.removeListener('close', onClose);
self.emit('close');
};
self.socket.once('error', onError);
self.socket.once('close', onClose);
_onConnect();
};
if (net.isIP(opts.host)) {
connect();
} else {
dns.lookup(opts.host, function (err, res) {
if (err) { return _onError(err); }
opts.host = res;
connect();
});
}
};
UdpStream.prototype.end = function (/*chunk, encoding, callback*/) {
var i = arguments.length, args = new Array(i);
while (i--) { args[i] = arguments[i]; }
var chunk, encoding = 'utf8', callback, parentCallback;
if (typeof args[args.length-1] === 'function') {
parentCallback = args.pop();
}
if (typeof args[0] === 'string' || Buffer.isBuffer(args[0])) {
chunk = args.shift();
if (typeof chunk === 'string' && args.length && typeof args[0] === 'string') {
encoding = args.shift();
}
}
callback = function () {
this.socket.close();
if (parentCallback) { parentCallback.apply(null, arguments); }
}.bind(this);
if (chunk) {
UdpStream.super_.prototype.end.call(this, chunk, encoding, callback);
} else {
UdpStream.super_.prototype.end.call(this, callback);
}
};
UdpStream.prototype._write = function (chunk, encoding, callback) {
this.socket.send(chunk, 0, chunk.length, this.port, this.host, callback);
};
module.exports = UdpStream;