forked from Eugeny/tabby
-
Notifications
You must be signed in to change notification settings - Fork 0
/
forwards.ts
65 lines (59 loc) · 2.45 KB
/
forwards.ts
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
import socksv5 from 'socksv5'
import { Server, Socket, createServer } from 'net'
import { ForwardedPortConfig, PortForwardType } from '../api'
export class ForwardedPort implements ForwardedPortConfig {
type: PortForwardType
host = '127.0.0.1'
port: number
targetAddress: string
targetPort: number
description: string
private listener: Server|null = null
async startLocalListener (callback: (accept: () => Socket, reject: () => void, sourceAddress: string|null, sourcePort: number|null, targetAddress: string, targetPort: number) => void): Promise<void> {
if (this.type === PortForwardType.Local) {
const listener = this.listener = createServer(s => callback(
() => s,
() => s.destroy(),
s.remoteAddress ?? null,
s.remotePort ?? null,
this.targetAddress,
this.targetPort,
))
return new Promise((resolve, reject) => {
listener.listen(this.port, this.host)
listener.on('error', reject)
listener.on('listening', resolve)
})
} else if (this.type === PortForwardType.Dynamic) {
return new Promise((resolve, reject) => {
this.listener = socksv5.createServer((info, acceptConnection, rejectConnection) => {
callback(
() => acceptConnection(true),
() => rejectConnection(),
null,
null,
info.dstAddr,
info.dstPort,
)
}) as Server
this.listener.on('error', reject)
this.listener.listen(this.port, this.host, resolve)
this.listener['useAuth'](socksv5.auth.None())
})
} else {
throw new Error('Invalid forward type for a local listener')
}
}
stopLocalListener (): void {
this.listener?.close()
}
toString (): string {
if (this.type === PortForwardType.Local) {
return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}`
} if (this.type === PortForwardType.Remote) {
return `(remote) ${this.host}:${this.port} → (local) ${this.targetAddress}:${this.targetPort}`
} else {
return `(dynamic) ${this.host}:${this.port}`
}
}
}