diff options
Diffstat (limited to 'websockets/server_proxy.js')
-rwxr-xr-x | websockets/server_proxy.js | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/websockets/server_proxy.js b/websockets/server_proxy.js new file mode 100755 index 0000000..5f4ea17 --- /dev/null +++ b/websockets/server_proxy.js @@ -0,0 +1,103 @@ +#!/usr/bin/env node +const fs=require("fs"); +const net=require("net"); +const https=require("https"); +const WebSocket=require("uWebSockets.js"); + +let listenport=null; + +let upstream=null; + +function parseUpstream(arg){ + const [host, port]=arg.split(":"); + return {host, port}; +} + + +let httpsConfig=null; +if(process.argv.length==6){ + upstream=parseUpstream(process.argv[2]); + listenport=+process.argv[3]; + console.log("Reading keys for https"); + httpsConfig={ + key_file_name: process.argv[4], + cert_file_name: process.argv[5], + }; +} else if(process.argv.length==4){ + upstream=parseUpstream(process.argv[2]); + listenport=+process.argv[3]; + console.log("WARNING: Running without SSL!"); +} else { + console.error("Usage: ./server.js <host:port> <port> # proxy without SSL"); + console.error(" ./server.js <host:port> <port> <key.pem> <cert.pem> # proxy with SSL"); + console.error("'<host:port>' indicates the plain-tcp tomsg server to proxy to."); + console.error("'<port>' indicates the port to listen for websocket connections on."); + process.exit(1); +} + +if(process.getuid()==0){ + console.log(`Old uid: ${process.getuid()}, old gid: ${process.getgid()}; setting to nobody...`); + process.setgid("nobody"); + process.setuid("nobody"); + console.log(`New uid: ${process.getuid()}, new gid: ${process.getgid()}`); +} + + +let wsServer; +if(httpsConfig){ + wsServer=WebSocket.SSLApp(httpsConfig); +} else { + wsServer=WebSocket.App(); +} + +wsServer=wsServer.ws("/*",{ + open: sock=>{ + const stateobj={netconn: null, buffer: [], sock_closed: false}; + sock["tomsgdata"]=stateobj; + let linebuf=""; + + stateobj.netconn=net.connect(upstream.port,upstream.host,()=>{ + for(const item of stateobj.buffer){ + stateobj.netconn.write(item); + stateobj.netconn.write("\n"); + } + stateobj.buffer=[]; + }); + stateobj.netconn.on("close",()=>{ + if(!stateobj.sock_closed)sock.close(); + }); + stateobj.netconn.on("data",(data)=>{ + linebuf+=data; + let idx; + while((idx=linebuf.indexOf("\n"))!=-1){ + sock.send(linebuf.slice(0,idx)); + linebuf=linebuf.slice(idx+1); + } + }); + stateobj.netconn.on("error",()=>{ + if(!stateobj.sock_closed)sock.close(); + }); + }, + message: (sock,data,isBinary)=>{ + const stateobj=sock["tomsgdata"]; + data=new Uint8Array(data); + if(stateobj.netconn.connecting){ + stateobj.buffer.push(data); + } else { + stateobj.netconn.write(data); + stateobj.netconn.write("\n"); + } + }, + close: sock=>{ + const stateobj=sock["tomsgdata"]; + stateobj.sock_closed=true; + try {stateobj.netconn.end();} + catch (e) {} + } +}); + +wsServer=wsServer.listen(listenport,listenSocket=>{ + if(listenSocket){ + console.log(`Websocket server${httpsConfig?" (SSL)":""} bound on port ${listenport}`); + } +}); |