Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save will118/3e3717dcd5e3573b9295f3bc73279df4 to your computer and use it in GitHub Desktop.
Save will118/3e3717dcd5e3573b9295f3bc73279df4 to your computer and use it in GitHub Desktop.
const net = require('net');
const readline = require('readline');
const COLUMN_WIDTH = 13;
const COLORS = {
red: '31',
green: '32',
cyan: '36',
};
const TIMEOUT = 60 * 1000;
const PORT = 14000;
const LOCALHOST = '172.16.88.19';
const pipes = {
1: {
port: 64000,
server: null
},
}
const ts = () => Math.floor(new Date() / 1000)
// TUI
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
readline.cursorTo(process.stdout, 0, 0);
readline.clearScreenDown(process.stdout);
rl.setPrompt('\npipes> ');
rl.prompt();
const lastActivity = server => {
return `${ts() - server.lastActivity} seconds ago`
}
const printStatus = (done) => {
Object.entries(pipes).forEach(([i, pipe], index) => {
const log = (status, color) => {
const padded = status.padEnd(COLUMN_WIDTH)
console.log(
`\x1b[${color}m%s\x1b[0m`,
`[${i}]: ${pipe.port} => ${PORT} | ${padded} | ${lastActivity(pipe.server)}`
)
}
if (pipe.server) {
pipe.server.getConnections((err, count) => {
const isListening = pipe.server.listening;
log(
isListening ? `${count} connection${count === 1 ? '' : 's'}` : 'closed',
isListening ? (count === 0 ? COLORS.cyan : COLORS.green) : COLORS.red
)
if (index === Object.keys(pipes).length - 1) {
done()
}
});
} else if (pipe.server === null) {
log('uninitialized', COLORS.red)
done()
} else {
log('unknown', COLORS.red)
done()
}
});
}
rl.on('line', line => {
const cmd = line.trim();
const matchPipeNumber = startOrStop => {
const match = cmd.match(new RegExp(`^${startOrStop}\\s?(\\d)$`));
if (match) {
return match[1];
}
return null;
}
const startPipeNumber = matchPipeNumber('start');
const stopPipeNumber = matchPipeNumber('stop');
if (cmd === 'status') {
printStatus(() => rl.prompt());
} else if (startPipeNumber) {
const pipe = pipes[startPipeNumber];
if (!pipe) {
console.log('Pipe not found');
rl.prompt();
return;
}
const { server, port } = pipe
server.listen(port);
printStatus(() => rl.prompt());
} else if (stopPipeNumber) {
const pipe = pipes[stopPipeNumber];
if (!pipe) {
console.log('Pipe not found');
rl.prompt();
return;
}
const { server, port } = pipe
if (server) {
server.destroy();
} else {
console.log(`No pipe open: ${port}`)
rl.prompt();
}
} else {
console.log('Invalid command')
rl.prompt();
}
}).on('close', () => {
console.log('\n\nBye!');
// This will kill the connections/servers anyway
process.exit(0);
});
const statusUpdate = (msg) => {
console.log(msg || '');
printStatus(() => {
console.log('');
rl.prompt()
});
}
const createServer = port => {
const server = net.createServer(socket => {
const client = new net.Socket();
client.connect(PORT, LOCALHOST, () => {
socket.pipe(client);
client.pipe(socket);
});
client.on('data', () => {
server.lastActivity = ts();
});
socket.on('error', e => {
if (e.code === 'ECONNRESET' && e.syscall === 'read') {
statusUpdate();
} else {
throw e;
}
});
socket.setTimeout(TIMEOUT, () => {
statusUpdate();
socket.end();
});
});
const connections = {}
server.on('connection', c => {
const { remoteAddress, remotePort } = c;
const key = `${remoteAddress}:${remotePort}`;
connections[key] = c;
statusUpdate();
c.on('close', () => {
delete connections[key];
statusUpdate();
});
});
server.destroy = (cb) => {
for (const key in connections) {
connections[key].destroy();
}
server.close(cb);
statusUpdate();
};
server.listen(port);
return server;
}
for (const key in pipes) {
const pipe = pipes[key]
pipe.server = createServer(pipe.port)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment