robertklep / node-port-mux

TCP port multiplexer: run multiple services through the same port
14 stars 4 forks source link

Supporting protocols where server is supposed to start conversation #1

Open rrva opened 8 years ago

rrva commented 8 years ago

In the nodejs debug protocol, the server starts the conversation, not the client.

Server banner upon connect will be:

Type: connect
V8-Version: 5.1.281.81
Protocol-Version: 1
Embedding-Host: node v6.5.0
Content-Length: 0

How to support muxing this and HTTP on the same port?

I was thinking that, after connect, start a timer. If a client request has not been received within a timeframe of for example 1000ms, respond with a static banner.

robertklep commented 8 years ago

I'm not sure if I entirely understand what you're trying to do, but does it mean that the client code (that you want to debug) is running an HTTP server on port X, you start that client with --inspect=X, and you want both the debugger and the HTTP server to work through that same port?

Or does it mean: HTTP on port X, debugger on port Y, and you want to be able to access they both through a (multiplexed) port Z?

rrva commented 8 years ago

I got it to work as intended, but of course the client code I want to debug has to be running in a separate process.

I made an ugly proof of concept based on your code:

https://gist.github.com/rrva/22de896bda8a0dd55e360d20fad3b39c

I then use it something like this (in webapp.js I have a webapp I want to debug, which listens on port 8888 for HTTP and port 9999 for remote debugging). I then mux that over port 3000 based on if the connecting client first connects and then says nothing for a while. Then I assume it should be connected to services[0] and do not select the handler based on what the client says (Very hacky).

var Muxer = require('./port-mux');
const fork = require('child_process').fork;

var port = process.env.PORT;
if (typeof(port) === 'undefined') {
    port = 3000;
}

const webPort = 8888;
const debugPort = 9999;

Muxer()
    .addRule(/^Content-Length/, debugPort)
    .addRule('GET ', webPort)
    .listen(port);

fork(__dirname + '/webapp.js', [], {
    execArgv: ["--debug=9999"]
});
robertklep commented 8 years ago

Right, I see now. It's a pretty difficult protocol to proxy for, since the client doesn't announce itself so you don't know what type of client it is (HTTP or debugger).

Perhaps I should consider allowing async rules, so you would be able to use something like this:

.addRule(dataPromise => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
    dataPromise.then(reject);
  });
}, debugPort);

So you'd get a dataPromise, which would get resolved once some data is read from the client. If that happens before the timeout, the client isn't "silent" and most likely not a debugger, so the rule gets rejected (meaning that it doesn't match). Otherwise, if the timeout triggers, the rule is accepted and passed to debugPort.

rrva commented 8 years ago

That sounds great. I will try to put my adaptation to use, but a catch 22 is of course that you cannot debug the proxying process whilst it being responsible for transporting the debug protocol, hence I used fork.

My use case is a cloud computing platform which only allows a single port to be open, so I wanted to test how to debug a nodejs app that way. Not sure it will be put to frequent use though, as this need is pretty rare.

On Fri, Sep 23, 2016 at 9:43 AM, Robert Klep notifications@github.com wrote:

Right, I see now. It's a pretty difficult protocol to proxy for, since the client doesn't announce itself so you don't know what type of client it is (HTTP or debugger).

Perhaps I should consider allowing async rules, so you would be able to use something like this:

.addRule(dataPromise => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); dataPromise.then(reject); }); }, debugPort);

So you'd get a dataPromise, which would get resolved once some data is read from the client. If that happens before the timeout, the client isn't "silent" and most likely not a debugger, so the rule gets rejected (meaning that it doesn't match). Otherwise, if the timeout triggers, the rule is accepted and passed to debugPort.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/robertklep/node-port-mux/issues/1#issuecomment-249124558, or mute the thread https://github.com/notifications/unsubscribe-auth/AA2JXNyYbxG4eY-VXyhFB3SDtHbHs7byks5qs4MwgaJpZM4KEEqc .