forked from coder/code-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.ts
More file actions
53 lines (49 loc) · 1.46 KB
/
Copy pathserver.ts
File metadata and controls
53 lines (49 loc) · 1.46 KB
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
import * as net from "net";
import { TunnelCloseCode } from "./common";
export interface WS {
addEventListener(event: "message", cb: (event: {
// tslint:disable-next-line:no-any
readonly data: any;
}) => void): void;
addEventListener(event: "close", cb: () => void): void;
binaryType: string;
close(code: number, reason?: string): void;
// tslint:disable-next-line:no-any
send(data: any): void;
}
export const handle = async (socket: WS, port: number): Promise<void> => {
const hosts = [
"127.0.0.1",
"::", // localhost
];
let localSocket: net.Socket | undefined;
for (let i = 0; i < hosts.length; i++) {
if (localSocket) {
break;
}
localSocket = await new Promise((resolve, reject): void => {
const socket = net.connect({
host: hosts[i],
port,
}, () => {
// Connected
resolve(socket);
});
socket.on("error", (err: Error & { readonly code: string }) => {
if (err.code === "ECONNREFUSED") {
resolve(undefined);
}
});
});
}
if (!localSocket) {
socket.close(TunnelCloseCode.ConnectionRefused);
return;
}
socket.binaryType = "arraybuffer";
socket.addEventListener("message", (event) => localSocket!.write(Buffer.from(event.data)));
socket.addEventListener("close", () => localSocket!.end());
localSocket.on("data", (data) => socket.send(data));
localSocket.on("error", (err) => socket.close(TunnelCloseCode.Error, err.toString()));
localSocket.on("close", () => socket.close(TunnelCloseCode.Normal));
};