aboutsummaryrefslogtreecommitdiff
path: root/websockets/server_proxy.js
diff options
context:
space:
mode:
Diffstat (limited to 'websockets/server_proxy.js')
-rwxr-xr-xwebsockets/server_proxy.js103
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}`);
+ }
+});