aboutsummaryrefslogtreecommitdiff
path: root/websockets/server.js
blob: 763b343354e25d0e4ed7ec54083721d601730a58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env node
const fs=require("fs");
const net=require("net");
const https=require("https");
const WebSocket=require("uWebSockets.js");

const PORT=29546;

const upstream={
	host: "localhost",
	port: 29536
};


let httpsConfig=null;
if(process.argv.length==4){
	console.log("Reading keys for https");
	httpsConfig={
		key_file_name: process.argv[2],
		cert_file_name: process.argv[3],
	};
} else if(process.argv.length==2){
	console.log("WARNING: Running without SSL!");
} else {
	console.error("Usage: ./server.js                        # proxy without SSL");
	console.error("       ./server.js <key.pem> <cert.pem>   # proxy with SSL");
	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(PORT,listenSocket=>{
	if(listenSocket){
		console.log(`Websocket server${httpsConfig?" (SSL)":""} bound on port ${PORT}`);
	}
});