-
-
Notifications
You must be signed in to change notification settings - Fork 283
/
Copy pathbase.ts
98 lines (79 loc) · 2.42 KB
/
base.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
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
96
97
98
import type { Socket as TCPSocket } from 'net';
import type { TLSSocket } from 'tls';
import type { SocksProxyAgent } from 'socks-proxy-agent';
import type { ISocket, SocketListener } from './interface';
const TIMEOUT = 10000;
const KEEP_ALIVE = true;
type Socket = TCPSocket | TLSSocket;
export type SocketOptions = {
timeout?: number;
keepAlive?: boolean;
proxyAgent?: SocksProxyAgent;
};
type Err = Error &
Partial<{
errorno: string;
code: string;
connect: boolean;
}>;
export type SocketConfig = SocketOptions & {
host: string;
port: number;
};
export abstract class SocketBase implements ISocket {
private socket?: Socket;
protected host: string;
protected port: number;
protected timeout: number;
protected keepAlive: boolean;
constructor({ host, port, timeout, keepAlive }: SocketConfig) {
this.host = host;
this.port = port;
this.timeout = timeout !== undefined ? timeout : TIMEOUT;
this.keepAlive = keepAlive !== undefined ? keepAlive : KEEP_ALIVE;
}
async connect(listener: SocketListener) {
this.socket = await this.openSocket(listener);
}
close() {
this.socket?.end();
this.socket?.destroy();
}
send(data: string | Uint8Array) {
return this.socket?.write(data);
}
protected abstract openSocket(listener: SocketListener): Promise<Socket>;
protected configureSocket(socket: Socket) {
socket.setTimeout(this.timeout);
socket.setEncoding('utf8');
socket.setKeepAlive(this.keepAlive);
socket.setNoDelay(true);
}
protected bindSocket(socket: Socket, listener: SocketListener) {
socket.on('connect', () => {
socket.setTimeout(0);
listener.onConnect();
});
socket.on('close', e => {
listener.onClose(e);
});
socket.on('timeout', () => {
const e: Err = new Error('ETIMEDOUT');
e.errorno = 'ETIMEDOUT';
e.code = 'ETIMEDOUT';
e.connect = false;
socket.emit('error', e);
});
socket.on('data', chunk => {
socket.setTimeout(0);
listener.onReceive(chunk);
});
socket.on('end', (e: unknown) => {
socket.setTimeout(0);
listener.onEnd(e);
});
socket.on('error', e => {
listener.onError(e);
});
}
}