tunnel-packer
Advanced tools
Comparing version 1.0.0 to 1.1.0
225
index.js
'use strict'; | ||
module.exports.create = function (opts) { | ||
var Packer = module.exports; | ||
var machine = { onMessage: opts.onMessage }; | ||
Packer.create = function (opts) { | ||
var machine; | ||
if (!opts.onMessage && !opts.onmessage) { | ||
machine = new (require('events').EventEmitter)(); | ||
} else { | ||
machine = {}; | ||
} | ||
machine.onMessage = opts.onmessage || opts.onMessage; | ||
machine.onmessage = opts.onmessage || opts.onMessage; | ||
machine.onError = opts.onerror || opts.onError; | ||
machine.onerror = opts.onerror || opts.onError; | ||
machine.onEnd = opts.onend || opts.onEnd; | ||
machine.onend = opts.onend || opts.onEnd; | ||
machine._version = 1; | ||
@@ -85,2 +100,4 @@ machine.state = 0; | ||
machine.bodyLen = parseInt(machine._headers[3], 10) || -1; | ||
machine.service = machine._headers[4]; | ||
//console.log('machine.service', machine.service); | ||
@@ -98,2 +115,4 @@ return true; | ||
var partLen = 0; | ||
var msg; | ||
var data; | ||
@@ -129,9 +148,63 @@ partLen = Math.min(machine.bodyLen - machine.bufIndex, chunk.length - machine.chunkIndex); | ||
machine.onMessage({ | ||
family: machine.family | ||
, address: machine.address | ||
, port: machine.port | ||
, data: machine.buf.slice(0, machine.bufIndex) | ||
}); | ||
machine.service = machine.service; | ||
data = machine.buf.slice(0, machine.bufIndex); | ||
//console.log('machine.service', machine.service); | ||
// | ||
// data, end, error | ||
// | ||
if ('end' === machine.service) { | ||
msg = {}; | ||
msg.family = machine.family; | ||
msg.address = machine.address; | ||
msg.port = machine.port; | ||
msg.service = 'end'; | ||
msg.data = data; | ||
if (machine.emit) { | ||
machine.emit('tunnelEnd', msg); | ||
} | ||
else { | ||
(machine.onend||machine.onmessage)(msg); | ||
} | ||
} | ||
else if ('error' === machine.service) { | ||
try { | ||
msg = JSON.parse(machine.data.toString()); | ||
} catch(e) { | ||
msg = new Error('unknown error'); | ||
} | ||
msg.family = machine.family; | ||
msg.address = machine.address; | ||
msg.port = machine.port; | ||
msg.service = 'error'; | ||
msg.data = data; | ||
if (machine.emit) { | ||
machine.emit('tunnelError', msg); | ||
} | ||
else { | ||
(machine.onerror||machine.onmessage)(msg); | ||
} | ||
} | ||
else { | ||
msg = {}; | ||
msg.family = machine.family; | ||
msg.address = machine.address; | ||
msg.port = machine.port; | ||
msg.service = machine.service; | ||
msg.data = data; | ||
if (machine.emit) { | ||
machine.emit('tunnelData', msg); | ||
} | ||
else { | ||
machine.onmessage(msg); | ||
} | ||
} | ||
machine.chunkIndex += partLen; // === chunk.length | ||
@@ -161,7 +234,20 @@ machine.buf = null; // reset to null | ||
module.exports.pack = function (address, data) { | ||
Packer.pack = function (address, data, service) { | ||
data = data || Buffer.alloc(1); | ||
if (!data.byteLength) { | ||
data = Buffer.alloc(1); | ||
} | ||
if ('error' === service) { | ||
address.service = 'error'; | ||
} | ||
else if ('end' === service) { | ||
address.service = 'end'; | ||
} | ||
var version = 1; | ||
var header = Buffer.from( | ||
/*servername + ',' +*/address.family + ',' + address.address + ',' + address.port + ',' + data.byteLength | ||
); | ||
var header = Buffer.from([ | ||
/*servername,*/ address.family, address.address, address.port, data.byteLength | ||
, (address.service || '') | ||
].join(',')); | ||
var meta = Buffer.from([ 255 - version, header.length ]); | ||
@@ -176,1 +262,116 @@ var buf = Buffer.alloc(meta.byteLength + header.byteLength + data.byteLength); | ||
}; | ||
Packer.socketToAddr = function (socket) { | ||
// TODO BUG XXX | ||
// https://github.com/nodejs/node/issues/8854 | ||
// tlsSocket.remoteAddress = remoteAddress; // causes core dump | ||
// console.log(tlsSocket.remoteAddress); | ||
return { | ||
family: | ||
socket.remoteFamily | ||
|| socket._remoteFamily | ||
|| socket._handle._parentWrap.remoteFamily | ||
|| socket._handle._parentWrap._handle.owner.stream.remoteFamily | ||
, address: | ||
socket.remoteAddress | ||
|| socket._remoteAddress | ||
|| socket._handle._parentWrap.remoteAddress | ||
|| socket._handle._parentWrap._handle.owner.stream.remoteAddress | ||
, port: | ||
socket.remotePort | ||
|| socket._remotePort | ||
|| socket._handle._parentWrap.remotePort | ||
|| socket._handle._parentWrap._handle.owner.stream.remotePort | ||
}; | ||
}; | ||
Packer.addrToId = function (address) { | ||
return address.family + ',' + address.address + ',' + address.port; | ||
}; | ||
Packer.socketToId = function (socket) { | ||
return Packer.addrToId(Packer.socketToAddr(socket)); | ||
}; | ||
/* | ||
* | ||
* Tunnel Packer | ||
* | ||
*/ | ||
var Transform = require('stream').Transform; | ||
var util = require('util'); | ||
function MyTransform(options) { | ||
if (!(this instanceof MyTransform)) { | ||
return new MyTransform(options); | ||
} | ||
this.__my_addr = options.address; | ||
this.__my_service = options.service; | ||
Transform.call(this, options); | ||
} | ||
util.inherits(MyTransform, Transform); | ||
function transform(me, data, encoding, callback) { | ||
var address = me.__my_addr; | ||
address.service = address.service || me.__my_service; | ||
me.push(Packer.pack(address, data)); | ||
callback(); | ||
} | ||
MyTransform.prototype._transform = function (data, encoding, callback) { | ||
return transform(this, data, encoding, callback); | ||
}; | ||
Packer.Stream = {}; | ||
var Dup = { | ||
write: function (chunk, encoding, cb) { | ||
//console.log('_write', chunk.byteLength); | ||
this.__my_socket.write(chunk, encoding); | ||
cb(); | ||
} | ||
, read: function (size) { | ||
//console.log('_read'); | ||
var x = this.__my_socket.read(size); | ||
if (x) { | ||
console.log('_read', size); | ||
this.push(x); | ||
} | ||
} | ||
}; | ||
Packer.Stream.create = function (socket) { | ||
// Workaround for | ||
// https://github.com/nodejs/node/issues/8854 | ||
// https://www.google.com/#q=get+socket+address+from+file+descriptor | ||
// TODO try creating a new net.Socket({ handle: socket._handle, fd: socket._handle.fd }) | ||
// from the old one and then adding back the data with | ||
// sock.push(firstChunk) | ||
var Duplex = require('stream').Duplex; | ||
var myDuplex = new Duplex(); | ||
myDuplex.__my_socket = socket; | ||
myDuplex._write = Dup.write; | ||
myDuplex._read = Dup.read; | ||
//console.log('plainSocket.*Address'); | ||
//console.log('remote:', socket.remoteAddress); | ||
//console.log('local:', socket.localAddress); | ||
//console.log('address():', socket.address()); | ||
myDuplex.remoteFamily = socket.remoteFamily; | ||
myDuplex.remoteAddress = socket.remoteAddress; | ||
myDuplex.remotePort = socket.remotePort; | ||
myDuplex.localFamily = socket.localFamily; | ||
myDuplex.localAddress = socket.localAddress; | ||
myDuplex.localPort = socket.localPort; | ||
return myDuplex; | ||
}; | ||
Packer.Transform = {}; | ||
Packer.Transform.create = function (opts) { | ||
// Note: service refers to the port that the incoming request was from, | ||
// if known (smtps, smtp, https, http, etc) | ||
// { address: '127.0.0.1', service: 'https' } | ||
return new MyTransform(opts); | ||
}; |
{ | ||
"name": "tunnel-packer", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "A strategy for packing and unpacking tunneled network messages (or any stream)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# tunnel-packer | ||
A strategy for packing and unpacking tunneled network messages (or any stream) in node.js | ||
Examples | ||
``` | ||
var Packer = require('tunnel-packer'); | ||
Packer.create({ | ||
onmessage: function (msg) { | ||
// msg = { family, address, port, service, data }; | ||
} | ||
, onend: function (msg) { | ||
// msg = { family, address, port }; | ||
} | ||
, onerror: function (err) { | ||
// err = { message, family, address, port }; | ||
} | ||
}); | ||
var chunk = Packer.pack(address, data, service); | ||
var addr = Packer.socketToAddr(socket); | ||
var id = Packer.addrToId(address); | ||
var id = Packer.socketToId(socket); | ||
var myDuplex = Packer.Stream.create(socketOrStream); | ||
var myTransform = Packer.Transform.create({ | ||
address: { | ||
family: '...' | ||
, address: '...' | ||
, port: '...' | ||
} | ||
// hint at the service to be used | ||
, service: 'https' | ||
}); | ||
``` |
13
test.js
@@ -10,4 +10,7 @@ 'use strict'; | ||
, port: 443 | ||
, service: 'foo' | ||
}; | ||
var header = address.family + ',' + address.address + ',' + address.port + ',' + hello.byteLength; | ||
var header = address.family + ',' + address.address + ',' + address.port + ',' + hello.byteLength | ||
+ ',' + (address.service || '') | ||
; | ||
var buf = Buffer.concat([ | ||
@@ -23,3 +26,3 @@ Buffer.from([ 255 - version, header.length ]) | ||
var machine = packer.create({ | ||
onMessage: function (opts) { | ||
onmessage: function (opts) { | ||
var id = opts.family + ',' + opts.address + ',' + opts.port; | ||
@@ -49,2 +52,8 @@ var service = 'https'; | ||
} | ||
, onerror: function () { | ||
throw new Error("Did not expect onerror"); | ||
} | ||
, onend: function () { | ||
throw new Error("Did not expect onend"); | ||
} | ||
}); | ||
@@ -51,0 +60,0 @@ var packed = packer.pack(address, hello); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27467
414
39