Skip to content

Instantly share code, notes, and snippets.

@mStirner
Created April 26, 2022 19:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mStirner/223bf0902aafde2da16fac6f9757975f to your computer and use it in GitHub Desktop.
Save mStirner/223bf0902aafde2da16fac6f9757975f to your computer and use it in GitHub Desktop.
WebSocket l4 adapter minimal reproducible example
const { Transform } = require("stream");
module.exports = () => {
let encode = new Transform({
transform(chunk, encoding, cb) {
console.log("[encode]", chunk);
cb(null, chunk);
},
});
let decode = new Transform({
transform(chunk, encoding, cb) {
console.log("[decode]", chunk);
cb(null, chunk);
},
});
return {
encode,
decode
};
};
#!/usr/bin/env node
const child_process = require("child_process");
const WebSocket = require("ws");
// http://127.0.0.1:8080/api/devices/6042785432c51e3e98e7acc0/interfaces/6042785432c51e3e98e7acc1
function bridge(ws, host, port) {
// create stream from websocket
const stream = WebSocket.createWebSocketStream(ws);
/*
ws.on("message", (message) => {
console.log("Send to device", message)
});
*/
ws.on("close", () => {
console.error("Disconnected from WebSocket: %s", ws.url);
process.exit(0);
});
ws.on("open", () => {
console.log(`Connected to WebSocket: "%s"`, ws.url);
let nc = child_process.spawn("nc", [host, port]);
nc.on("error", () => {
console.log("netcat error");
});
nc.on("close", () => {
console.log("netcat closed");
});
nc.on("spawn", () => {
console.log("netcat spawend");
});
nc.stderr.pipe(process.stderr);
stream.pipe(nc.stdin);
nc.stdout.pipe(stream);
});
}
const ws = new WebSocket("ws://127.0.0.1:8080");
// 192.168.2.100:8001
bridge(ws, "192.168.2.4", 443);
//bridge(ws, "192.168.2.100", 8001);
//bridge(ws, "127.0.0.1", 8081);
const { Agent } = require("http");
const WebSocket = require("ws");
module.exports = (upstream) => {
let agent = new Agent();
agent.createConnection = (options, cb) => {
upstream.setTimeout = () => { };
upstream.setNoDelay = () => { };
return upstream;
};
let client = new WebSocket("ws://licht.lan:443", {
agent
});
client.on("ping", () => {
console.log("[client] ping received");
});
client.on("pong", () => {
console.log("[client] pong received");
});
/*
setInterval(() => {
client.ping();
}, 2000);
setTimeout(() => {
client.close();
}, 5000);
*/
client.on("message", (msg) => {
console.log(msg.toString());
});
client.on("close", (code, reason) => {
console.log("Client connection closed", code, reason)
});
}
const WebSocket = require("ws");
const { Duplex, PassThrough } = require("stream");
console.clear();
const wss = new WebSocket.Server({
port: 8080
});
wss.on("listening", (err) => {
console.log(err || "listneing");
});
function heartbeat() {
this.isAlive = true;
}
const interval = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, 10000);
wss.on('close', function close() {
clearInterval(interval);
});
wss.on("connection", (ws) => {
console.log("client connected");
ws.on("ping", () => {
console.log("[server] ping received");
});
ws.on("pong", () => {
console.log("[server] pong received");
});
ws.isAlive = true;
ws.on('pong', heartbeat);
let upstream = WebSocket.createWebSocketStream(ws, {
// duplex stream options
//emitClose: false,
//objectMode: true,
//decodeStrings: false
//allowHalfOpen: true
});
let readable = new PassThrough();
let writable = new PassThrough();
let duplex = Duplex.from({
readable,
writable
});
let { encode, decode } = require("./adapter.js")();
//upstream.pipe(decode).pipe(readable);
//duplex.pipe(encode).pipe(upstream);
upstream.pipe(decode).pipe(readable);
writable.pipe(encode).pipe(upstream);
require("./client")(duplex);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment