Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue #15 #16

Merged
merged 2 commits into from
Jan 14, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 86 additions & 46 deletions lib/proxywrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,67 @@ exports.defaults = {
overrideRemote: true,
};

function defineRemoteAddress(socket, header){
Object.defineProperty(socket, 'remoteAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[2];
}
});
}

function defineRemotePort(socket, header){
Object.defineProperty(socket, 'remotePort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[4], 10);
}
});
}

function defineClientAddress(socket, header){
Object.defineProperty(socket, 'clientAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[2];
}
});
}

function defineClientPort(socket, header){
Object.defineProperty(socket, 'clientPort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[4], 10);
}
});
}

function defineProxyAddress(socket, header){
Object.defineProperty(socket, 'proxyAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[3];
}
});
}

function defineProxyPort(socket, header){
Object.defineProperty(socket, 'proxyPort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[5], 10);
}
});
}


// Wraps the given module (ie, http, https, net, tls, etc) interface so that
// `socket.remoteAddress` and `remotePort` work correctly when used with the
// PROXY protocol (http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt)
Expand Down Expand Up @@ -138,7 +199,21 @@ exports.proxy = function(iface, options) {

function onReadable() {
var chunk;
while (null != (chunk = socket.read())) {
chunk = socket.read();

if(null === chunk && header.length === 0){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add here a non-strict condition filter?
! options.strict && null === chunk && header.length === 0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also run your tests to check if this affects somehow your fix? Cheers

// unshifting will fire the readable event
socket.emit = realEmit;
//socket.unshift(buf.slice(protocolError ? 0 : crlf+2));

self.emit('proxiedConnection', socket);

//restore();

return;
}

while (null !== chunk) {
buf = Buffer.concat([buf, chunk]);
header += chunk.toString('ascii');

Expand Down Expand Up @@ -169,54 +244,16 @@ exports.proxy = function(iface, options) {

if( options.overrideRemote ) {

Object.defineProperty(socket, 'remoteAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[2];
}
});
Object.defineProperty(socket, 'remotePort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[4], 10);
}
});
defineRemoteAddress(socket, header);
defineRemotePort(socket, header);

}

// Source properties of TCP connection
Object.defineProperty(socket, 'clientAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[2];
}
});
Object.defineProperty(socket, 'clientPort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[4], 10);
}
});

// Destination properties of TCP connection
Object.defineProperty(socket, 'proxyAddress', {
enumerable: false,
configurable: true,
get: function() {
return header[3];
}
});
Object.defineProperty(socket, 'proxyPort', {
enumerable: false,
configurable: true,
get: function() {
return parseInt(header[5], 10);
}
});
defineClientAddress(socket, header);
defineClientPort(socket, header);
defineProxyAddress(socket, header);
defineProxyPort(socket, header);
}

// unshifting will fire the readable event
Expand All @@ -235,12 +272,15 @@ exports.proxy = function(iface, options) {
}
}

break;
return;

} else if ( header.length > 107 ) {
return destroy('PROXY header too long');
}

chunk = socket.read();
}

}

}
Expand Down
53 changes: 53 additions & 0 deletions test/issue-15.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';
/* related to issue https://github.com/findhit/proxywrap/issues/15 */
var http = require('http'),
assert = require('assert'),
net = require('net'),
exec = require('child_process').exec,
child,
proxiedHttp = require('..').proxy(http, {
strict: false
});

function findCloseWaitConnections(port, callback) {
var child = exec('netstat -tonp | grep 8000 | grep CLOSE_WAIT',
function (err, stdout, stderr) {
if (err) {
return callback(err);
}
return callback(null, stdout);
});
}

describe('Sockets closed before any write #15', function () {
var port, server;

before(function (done) {
var socket;
server = proxiedHttp.createServer(function handler(req, res) {
throw new Error('For this test socket should not call #write()');
}).listen(function (err) {
if (err) {
return done(err);
}
port = this.address().port;
socket = net.connect({
port: port
}, function () {
socket.end();
});
socket.on('end', function () {
done();
});
});
});
after(function () {
server.close();
});
it('should be restored', function (done) {
findCloseWaitConnections(port, function (err, stdout) {
assert.deepEqual(null, stdout);
return done();
});
});
});