Skip to content

Instantly share code, notes, and snippets.

@ssafejava
Created September 17, 2013 05:05
Show Gist options
  • Save ssafejava/6590253 to your computer and use it in GitHub Desktop.
Save ssafejava/6590253 to your computer and use it in GitHub Desktop.
Wrap a socket in as many transform streams as you like, use the socket as normal.
var net = require('net');
var es = require('event-stream');
var util = require('util');
var _ = require('lodash');
var stream = require('stream');
/**
* A socketWrapper wraps a net.Socket object with any number
* of readableTransforms and writableTransforms, specified in the options object.
* @param {Object} options Options. Options not listed below are forwarded to net.Socket.
* @param {Array} options.readableTransforms An array of transforms to execute as data is read from the socket.
* @param {Array} options.writableTransforms An array of transforms to execute as data is written from the socket.
* @param {Function} cb net.Socket's callback.
*/
function SocketWrapper(options, cb) {
stream.Duplex.call(this, {objectMode: true});
this._createSocket(options, cb);
this._createThroughs(options);
return this;
}
util.inherits(SocketWrapper, stream.Duplex);
_.extend(SocketWrapper.prototype,{
_createSocket: function(options, cb) {
this.socket = net.connect(options, function() {
this._proxyStream();
cb.call(this);
}.bind(this));
},
_createThroughs: function(options) {
this.readableThrough = es.through(write, end);
this.writableThrough = es.through(write, end);
if (options.readableTransforms && options.readableTransforms.length) {
this.readableThrough = es.pipeline.apply(null, options.readableTransforms.concat([this.readableThrough]));
}
if (options.writableTransforms && options.writableTransforms.length) {
this.writableThrough = es.pipeline.apply(null, [this.writableThrough].concat(options.writableTransforms));
}
function write(data) {
this.emit('data', data);
}
function end() {
this.emit('end');
}
},
_proxyStream: function() {
this.writableThrough.pipe(this.socket);
this.socket.pipe(this.readableThrough);
},
_read: function() {
var me = this;
this.readableThrough.once('data', function(data) {
me.push(data);
});
},
write: function(chunk, encoding) {
this.writableThrough.write(chunk);
}
});
// Create a socketWrapper & test it out.
var socketWrapper = new SocketWrapper({
port: 8124,
readableTransforms: [es.parse()],
writableTransforms: [es.stringify()]
}, function() {
console.log('client connected');
this.write({message: "Herro from the client!"});
});
socketWrapper.on('data', function(data) {
console.log('from server:', JSON.stringify(data));
});
// At this point you're free to pipe this socketWrapper anywhere, as though it were just a Socket.
var net = require('net');
var es = require('event-stream');
// This is a simple server that emulates a socket receiving JSON data.
// When it receives a message, it echos it back inside stringified JSON.
var server = net.createServer(function(c){
console.log('connection received.');
c.on('end', function() { console.log('disconnect'); });
// Greeting
c.write(JSON.stringify({message: "Hello from the server!"}));
// Echo
var through = es.through(function write(data){
this.emit('data', JSON.stringify({echo: data.toString()}));
});
c.pipe(through).pipe(c);
});
server.listen(8124, function() { console.log('server started.'); });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment