@libp2p/tcp 3.0.4 → 3.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +2 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +15 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/listener.d.ts +2 -0
- package/dist/src/listener.d.ts.map +1 -1
- package/dist/src/listener.js +19 -11
- package/dist/src/listener.js.map +1 -1
- package/dist/src/socket-to-conn.d.ts +2 -0
- package/dist/src/socket-to-conn.d.ts.map +1 -1
- package/dist/src/socket-to-conn.js +85 -31
- package/dist/src/socket-to-conn.js.map +1 -1
- package/package.json +2 -1
- package/src/constants.ts +3 -0
- package/src/index.ts +35 -2
- package/src/listener.ts +22 -10
- package/src/socket-to-conn.ts +104 -39
package/README.md
CHANGED
|
@@ -47,9 +47,10 @@ const upgrader = {
|
|
|
47
47
|
upgradeOutbound: maConn => maConn
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const tcp = new TCP(
|
|
50
|
+
const tcp = new TCP()
|
|
51
51
|
|
|
52
52
|
const listener = tcp.createListener({
|
|
53
|
+
upgrader,
|
|
53
54
|
handler: (socket) => {
|
|
54
55
|
console.log('new connection opened')
|
|
55
56
|
pipe(
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,QAAQ,MAAM,CAAA;AAC3B,eAAO,MAAM,YAAY,MAAM,CAAA;AAG/B,eAAO,MAAM,aAAa,OAAO,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,QAAQ,MAAM,CAAA;AAC3B,eAAO,MAAM,YAAY,MAAM,CAAA;AAG/B,eAAO,MAAM,aAAa,OAAO,CAAA;AAGjC,eAAO,MAAM,cAAc,QAAQ,CAAA"}
|
package/dist/src/constants.js
CHANGED
|
@@ -3,4 +3,6 @@ export const CODE_P2P = 421;
|
|
|
3
3
|
export const CODE_CIRCUIT = 290;
|
|
4
4
|
// Time to wait for a connection to close gracefully before destroying it manually
|
|
5
5
|
export const CLOSE_TIMEOUT = 2000;
|
|
6
|
+
// Close the socket if there is no activity after this long in ms
|
|
7
|
+
export const SOCKET_TIMEOUT = 30000;
|
|
6
8
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAC3B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;AAE/B,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAC3B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;AAE/B,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAA;AAEjC,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAA"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -4,7 +4,23 @@ import { CreateListenerOptions, DialOptions, symbol, Transport } from '@libp2p/i
|
|
|
4
4
|
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
5
5
|
import type { AbortOptions } from '@libp2p/interfaces';
|
|
6
6
|
import type { Connection } from '@libp2p/interface-connection';
|
|
7
|
+
export interface TCPOptions {
|
|
8
|
+
/**
|
|
9
|
+
* An optional number in ms that is used as an inactivity timeout after which the socket will be closed
|
|
10
|
+
*/
|
|
11
|
+
inboundSocketInactivityTimeout?: number;
|
|
12
|
+
/**
|
|
13
|
+
* An optional number in ms that is used as an inactivity timeout after which the socket will be closed
|
|
14
|
+
*/
|
|
15
|
+
outboundSocketInactivityTimeout?: number;
|
|
16
|
+
/**
|
|
17
|
+
* When closing a socket, wait this long for it to close gracefully before it is closed more forcibly
|
|
18
|
+
*/
|
|
19
|
+
socketCloseTimeout?: number;
|
|
20
|
+
}
|
|
7
21
|
export declare class TCP implements Transport {
|
|
22
|
+
private readonly opts;
|
|
23
|
+
constructor(options?: TCPOptions);
|
|
8
24
|
get [symbol](): true;
|
|
9
25
|
get [Symbol.toStringTag](): string;
|
|
10
26
|
dial(ma: Multiaddr, options: DialOptions): Promise<Connection>;
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AASrB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAA;AACnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAI9D,qBAAa,GAAI,YAAW,SAAS;IACnC,IAAI,CAAC,MAAM,CAAC,IAAK,IAAI,CAEpB;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;IAEK,IAAI,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AASrB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAA;AACnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAI9D,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,8BAA8B,CAAC,EAAE,MAAM,CAAA;IAEvC;;OAEG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAA;IAExC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,qBAAa,GAAI,YAAW,SAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;gBAEpB,OAAO,GAAE,UAAe;IAIrC,IAAI,CAAC,MAAM,CAAC,IAAK,IAAI,CAEpB;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;IAEK,IAAI,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAqB/D,QAAQ,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,YAAiB;IA+DzD;;;;OAIG;IACH,cAAc,CAAE,OAAO,EAAE,qBAAqB;IAQ9C;;OAEG;IACH,MAAM,CAAE,UAAU,EAAE,SAAS,EAAE;CAWhC"}
|
package/dist/src/index.js
CHANGED
|
@@ -10,6 +10,9 @@ import { CODE_CIRCUIT, CODE_P2P } from './constants.js';
|
|
|
10
10
|
import { symbol } from '@libp2p/interface-transport';
|
|
11
11
|
const log = logger('libp2p:tcp');
|
|
12
12
|
export class TCP {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.opts = options;
|
|
15
|
+
}
|
|
13
16
|
get [symbol]() {
|
|
14
17
|
return true;
|
|
15
18
|
}
|
|
@@ -18,11 +21,17 @@ export class TCP {
|
|
|
18
21
|
}
|
|
19
22
|
async dial(ma, options) {
|
|
20
23
|
const socket = await this._connect(ma, options);
|
|
24
|
+
socket.setKeepAlive(true);
|
|
21
25
|
// Avoid uncaught errors caused by unstable connections
|
|
22
26
|
socket.on('error', err => {
|
|
23
27
|
log('socket error', err);
|
|
24
28
|
});
|
|
25
|
-
const maConn = toMultiaddrConnection(socket, {
|
|
29
|
+
const maConn = toMultiaddrConnection(socket, {
|
|
30
|
+
remoteAddr: ma,
|
|
31
|
+
signal: options.signal,
|
|
32
|
+
socketInactivityTimeout: this.opts.outboundSocketInactivityTimeout,
|
|
33
|
+
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
34
|
+
});
|
|
26
35
|
log('new outbound connection %s', maConn.remoteAddr);
|
|
27
36
|
const conn = await options.upgrader.upgradeOutbound(maConn);
|
|
28
37
|
log('outbound connection %s upgraded', maConn.remoteAddr);
|
|
@@ -82,7 +91,11 @@ export class TCP {
|
|
|
82
91
|
* `upgrader.upgradeInbound`.
|
|
83
92
|
*/
|
|
84
93
|
createListener(options) {
|
|
85
|
-
return createListener(
|
|
94
|
+
return createListener({
|
|
95
|
+
...options,
|
|
96
|
+
socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
|
|
97
|
+
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
98
|
+
});
|
|
86
99
|
}
|
|
87
100
|
/**
|
|
88
101
|
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,KAAK,KAAK,MAAM,qBAAqB,CAAA;AAC5C,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAsC,MAAM,EAAa,MAAM,6BAA6B,CAAA;AAMnG,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/listener.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACnF,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAqBrE,UAAU,OAAO;IACf,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,QAAQ,EAAE,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACnF,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAqBrE,UAAU,OAAO;IACf,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,QAAQ,EAAE,QAAQ,CAAA;IAClB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAE,OAAO,EAAE,OAAO,YAgI/C"}
|
package/dist/src/listener.js
CHANGED
|
@@ -20,17 +20,22 @@ async function attemptClose(maConn) {
|
|
|
20
20
|
* Create listener
|
|
21
21
|
*/
|
|
22
22
|
export function createListener(context) {
|
|
23
|
-
const { handler, upgrader } = context;
|
|
23
|
+
const { handler, upgrader, socketInactivityTimeout, socketCloseTimeout } = context;
|
|
24
24
|
let peerId;
|
|
25
25
|
let listeningAddr;
|
|
26
26
|
const server = Object.assign(net.createServer(socket => {
|
|
27
|
+
socket.setKeepAlive(true);
|
|
27
28
|
// Avoid uncaught errors caused by unstable connections
|
|
28
29
|
socket.on('error', err => {
|
|
29
30
|
log('socket error', err);
|
|
30
31
|
});
|
|
31
32
|
let maConn;
|
|
32
33
|
try {
|
|
33
|
-
maConn = toMultiaddrConnection(socket, {
|
|
34
|
+
maConn = toMultiaddrConnection(socket, {
|
|
35
|
+
listeningAddr,
|
|
36
|
+
socketInactivityTimeout,
|
|
37
|
+
socketCloseTimeout
|
|
38
|
+
});
|
|
34
39
|
}
|
|
35
40
|
catch (err) {
|
|
36
41
|
log.error('inbound connection failed', err);
|
|
@@ -75,13 +80,18 @@ export function createListener(context) {
|
|
|
75
80
|
if (typeof address === 'string') {
|
|
76
81
|
throw new Error('Incorrect server address type');
|
|
77
82
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
try {
|
|
84
|
+
// Because TCP will only return the IPv6 version
|
|
85
|
+
// we need to capture from the passed multiaddr
|
|
86
|
+
if (listeningAddr.toString().startsWith('/ip4')) {
|
|
87
|
+
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port));
|
|
88
|
+
}
|
|
89
|
+
else if (address.family === 'IPv6') {
|
|
90
|
+
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port));
|
|
91
|
+
}
|
|
82
92
|
}
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
catch (err) {
|
|
94
|
+
log.error('could not turn %s:%s into multiaddr', address.address, address.port, err);
|
|
85
95
|
}
|
|
86
96
|
return addrs.map(ma => peerId != null ? ma.encapsulate(`/p2p/${peerId}`) : ma);
|
|
87
97
|
},
|
|
@@ -106,9 +116,7 @@ export function createListener(context) {
|
|
|
106
116
|
if (!server.listening) {
|
|
107
117
|
return;
|
|
108
118
|
}
|
|
109
|
-
await Promise.all(
|
|
110
|
-
server.__connections.map(async (maConn) => await attemptClose(maConn))
|
|
111
|
-
]);
|
|
119
|
+
await Promise.all(server.__connections.map(async (maConn) => await attemptClose(maConn)));
|
|
112
120
|
await new Promise((resolve, reject) => {
|
|
113
121
|
server.close(err => (err != null) ? reject(err) : resolve());
|
|
114
122
|
});
|
package/dist/src/listener.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EACL,aAAa,EACb,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAMrE,MAAM,GAAG,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAMzC;;GAEG;AACH,KAAK,UAAU,YAAY,CAAE,MAA2B;IACtD,IAAI;QACF,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;KACrB;IAAC,OAAO,GAAG,EAAE;QACZ,GAAG,CAAC,KAAK,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAA;KAC3D;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EACL,aAAa,EACb,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAMrE,MAAM,GAAG,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAMzC;;GAEG;AACH,KAAK,UAAU,YAAY,CAAE,MAA2B;IACtD,IAAI;QACF,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;KACrB;IAAC,OAAO,GAAG,EAAE;QACZ,GAAG,CAAC,KAAK,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAA;KAC3D;AACH,CAAC;AASD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAE,OAAgB;IAC9C,MAAM,EACJ,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,kBAAkB,EAC/D,GAAG,OAAO,CAAA;IAEX,IAAI,MAAqB,CAAA;IACzB,IAAI,aAAwB,CAAA;IAE5B,MAAM,MAAM,GAAmC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;QACrF,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;QAEzB,uDAAuD;QACvD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YACvB,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QAC1B,CAAC,CAAC,CAAA;QAEF,IAAI,MAA2B,CAAA;QAC/B,IAAI;YACF,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE;gBACrC,aAAa;gBACb,uBAAuB;gBACvB,kBAAkB;aACnB,CAAC,CAAA;SACH;QAAC,OAAO,GAAG,EAAE;YACZ,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAA;YAC3C,OAAM;SACP;QAED,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;QACnD,IAAI;YACF,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC;iBAC5B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;gBACxD,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;gBAEjC,IAAI,OAAO,IAAI,IAAI,EAAE;oBACnB,OAAO,CAAC,IAAI,CAAC,CAAA;iBACd;gBAED,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAa,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;YACrF,CAAC,CAAC;iBACD,KAAK,CAAC,KAAK,EAAC,GAAG,EAAC,EAAE;gBACjB,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAA;gBAE3C,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;YAC5B,CAAC,CAAC;iBACD,KAAK,CAAC,GAAG,CAAC,EAAE;gBACX,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;YACrD,CAAC,CAAC,CAAA;SACL;QAAC,OAAO,GAAG,EAAE;YACZ,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAA;YAE3C,YAAY,CAAC,MAAM,CAAC;iBACjB,KAAK,CAAC,GAAG,CAAC,EAAE;gBACX,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;YACrD,CAAC,CAAC,CAAA;SACL;IACH,CAAC,CAAC;IACF,+DAA+D;IAC/D,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAA;IAEtB,MAAM,QAAQ,GAAa,MAAM,CAAC,MAAM,CAAC,IAAI,YAAY,EAAE,EAAE;QAC3D,QAAQ,EAAE,GAAG,EAAE;YACb,IAAI,KAAK,GAAgB,EAAE,CAAA;YAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;YAEhC,IAAI,OAAO,IAAI,IAAI,EAAE;gBACnB,OAAO,EAAE,CAAA;aACV;YAED,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;gBAC/B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;aACjD;YAED,IAAI;gBACF,gDAAgD;gBAChD,+CAA+C;gBAC/C,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;oBAC/C,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;iBAC1E;qBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;oBACpC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;iBAC1E;aACF;YAAC,OAAO,GAAG,EAAE;gBACZ,GAAG,CAAC,KAAK,CAAC,qCAAqC,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;aACrF;YAED,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAChF,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,EAAa,EAAE,EAAE;YAC9B,aAAa,GAAG,EAAE,CAAA;YAClB,MAAM,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;YAEvB,IAAI,MAAM,IAAI,IAAI,EAAE;gBAClB,aAAa,GAAG,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;aAC7C;YAED,OAAO,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACjD,MAAM,OAAO,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAA;gBACnD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,GAAS,EAAE,EAAE;oBACnC,IAAI,GAAG,IAAI,IAAI,EAAE;wBACf,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;qBACnB;oBACD,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;oBACxC,OAAO,EAAE,CAAA;gBACX,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;gBACrB,OAAM;aACP;YAED,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CACrE,CAAA;YAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;YAC9D,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IAEF,MAAM;SACH,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;SAC3E,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAQ,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;SAC5F,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAEtE,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,SAAS,CAAE,MAAsC,EAAE,MAA2B,EAAE,MAAkB;IACzG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEjC,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAA;IACvE,CAAC,CAAA;IAED,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;AACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-to-conn.d.ts","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"socket-to-conn.d.ts","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAIvE,UAAU,mBAAmB;IAC3B,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,WAAY,MAAM,YAAY,mBAAmB,wBAiKlF,CAAA"}
|
|
@@ -3,7 +3,8 @@ import { logger } from '@libp2p/logger';
|
|
|
3
3
|
// @ts-expect-error no types
|
|
4
4
|
import toIterable from 'stream-to-it';
|
|
5
5
|
import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr';
|
|
6
|
-
import { CLOSE_TIMEOUT } from './constants.js';
|
|
6
|
+
import { CLOSE_TIMEOUT, SOCKET_TIMEOUT } from './constants.js';
|
|
7
|
+
import errCode from 'err-code';
|
|
7
8
|
const log = logger('libp2p:tcp:socket');
|
|
8
9
|
/**
|
|
9
10
|
* Convert a socket into a MultiaddrConnection
|
|
@@ -11,6 +12,8 @@ const log = logger('libp2p:tcp:socket');
|
|
|
11
12
|
*/
|
|
12
13
|
export const toMultiaddrConnection = (socket, options) => {
|
|
13
14
|
options = options ?? {};
|
|
15
|
+
const inactivityTimeout = options.socketInactivityTimeout ?? SOCKET_TIMEOUT;
|
|
16
|
+
const closeTimeout = options.socketCloseTimeout ?? CLOSE_TIMEOUT;
|
|
14
17
|
// Check if we are connected on a unix path
|
|
15
18
|
if (options.listeningAddr?.getPath() != null) {
|
|
16
19
|
options.remoteAddr = options.listeningAddr;
|
|
@@ -18,20 +21,54 @@ export const toMultiaddrConnection = (socket, options) => {
|
|
|
18
21
|
if (options.remoteAddr?.getPath() != null) {
|
|
19
22
|
options.localAddr = options.remoteAddr;
|
|
20
23
|
}
|
|
24
|
+
let remoteAddr;
|
|
25
|
+
if (options.remoteAddr != null) {
|
|
26
|
+
remoteAddr = options.remoteAddr;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
if (socket.remoteAddress == null || socket.remotePort == null) {
|
|
30
|
+
// this can be undefined if the socket is destroyed (for example, if the client disconnected)
|
|
31
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketremoteaddress
|
|
32
|
+
throw errCode(new Error('Could not determine remote address or port'), 'ERR_NO_REMOTE_ADDRESS');
|
|
33
|
+
}
|
|
34
|
+
remoteAddr = toMultiaddr(socket.remoteAddress, socket.remotePort);
|
|
35
|
+
}
|
|
36
|
+
const { host, port } = remoteAddr.toOptions();
|
|
21
37
|
const { sink, source } = toIterable.duplex(socket);
|
|
38
|
+
// by default there is no timeout
|
|
39
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketsettimeouttimeout-callback
|
|
40
|
+
socket.setTimeout(inactivityTimeout, () => {
|
|
41
|
+
log('%s:%s socket read timeout', host, port);
|
|
42
|
+
// only destroy with an error if the remote has not sent the FIN message
|
|
43
|
+
let err;
|
|
44
|
+
if (socket.readable) {
|
|
45
|
+
err = errCode(new Error('Socket read timeout'), 'ERR_SOCKET_READ_TIMEOUT');
|
|
46
|
+
}
|
|
47
|
+
// if the socket times out due to inactivity we must manually close the connection
|
|
48
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-timeout
|
|
49
|
+
socket.destroy(err);
|
|
50
|
+
});
|
|
51
|
+
socket.once('close', () => {
|
|
52
|
+
log('%s:%s socket closed', host, port);
|
|
53
|
+
// In instances where `close` was not explicitly called,
|
|
54
|
+
// such as an iterable stream ending, ensure we have set the close
|
|
55
|
+
// timeline
|
|
56
|
+
if (maConn.timeline.close == null) {
|
|
57
|
+
maConn.timeline.close = Date.now();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
socket.once('end', () => {
|
|
61
|
+
// the remote sent a FIN packet which means no more data will be sent
|
|
62
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-end
|
|
63
|
+
log('socket ended', maConn.remoteAddr.toString());
|
|
64
|
+
});
|
|
22
65
|
const maConn = {
|
|
23
66
|
async sink(source) {
|
|
24
67
|
if ((options?.signal) != null) {
|
|
25
68
|
source = abortableSource(source, options.signal);
|
|
26
69
|
}
|
|
27
70
|
try {
|
|
28
|
-
await sink(
|
|
29
|
-
for await (const chunk of source) {
|
|
30
|
-
// Convert BufferList to Buffer
|
|
31
|
-
// Sink in StreamMuxer define argument as Uint8Array so chunk type infers as number which can't be sliced
|
|
32
|
-
yield Buffer.isBuffer(chunk) ? chunk : chunk.slice();
|
|
33
|
-
}
|
|
34
|
-
})());
|
|
71
|
+
await sink(source);
|
|
35
72
|
}
|
|
36
73
|
catch (err) {
|
|
37
74
|
// If aborted we can safely ignore
|
|
@@ -42,53 +79,70 @@ export const toMultiaddrConnection = (socket, options) => {
|
|
|
42
79
|
log(err);
|
|
43
80
|
}
|
|
44
81
|
}
|
|
82
|
+
// we have finished writing, send the FIN message
|
|
83
|
+
socket.end();
|
|
45
84
|
},
|
|
46
|
-
// Missing Type for "abortable"
|
|
47
85
|
source: (options.signal != null) ? abortableSource(source, options.signal) : source,
|
|
48
86
|
// If the remote address was passed, use it - it may have the peer ID encapsulated
|
|
49
|
-
remoteAddr
|
|
87
|
+
remoteAddr,
|
|
50
88
|
timeline: { open: Date.now() },
|
|
51
89
|
async close() {
|
|
52
|
-
if (socket.destroyed)
|
|
90
|
+
if (socket.destroyed) {
|
|
91
|
+
log('%s:%s socket was already destroyed when trying to close', host, port);
|
|
53
92
|
return;
|
|
54
|
-
|
|
93
|
+
}
|
|
94
|
+
log('%s:%s closing socket', host, port);
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
55
96
|
const start = Date.now();
|
|
56
97
|
// Attempt to end the socket. If it takes longer to close than the
|
|
57
98
|
// timeout, destroy it manually.
|
|
58
99
|
const timeout = setTimeout(() => {
|
|
59
|
-
const { host, port } = maConn.remoteAddr.toOptions();
|
|
60
|
-
log('timeout closing socket to %s:%s after %dms, destroying it manually', host, port, Date.now() - start);
|
|
61
100
|
if (socket.destroyed) {
|
|
62
101
|
log('%s:%s is already destroyed', host, port);
|
|
102
|
+
resolve();
|
|
63
103
|
}
|
|
64
104
|
else {
|
|
65
|
-
socket.
|
|
105
|
+
log('%s:%s socket close timeout after %dms, destroying it manually', host, port, Date.now() - start);
|
|
106
|
+
// will trigger 'error' and 'close' events that resolves promise
|
|
107
|
+
socket.destroy(errCode(new Error('Socket close timeout'), 'ERR_SOCKET_CLOSE_TIMEOUT'));
|
|
66
108
|
}
|
|
67
|
-
|
|
68
|
-
}, CLOSE_TIMEOUT).unref();
|
|
109
|
+
}, closeTimeout).unref();
|
|
69
110
|
socket.once('close', () => {
|
|
111
|
+
log('%s:%s socket closed', host, port);
|
|
112
|
+
// socket completely closed
|
|
70
113
|
clearTimeout(timeout);
|
|
71
114
|
resolve();
|
|
72
115
|
});
|
|
73
|
-
socket.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
|
|
116
|
+
socket.once('error', (err) => {
|
|
117
|
+
log('%s:%s socket error', host, port, err);
|
|
118
|
+
// error closing socket
|
|
119
|
+
if (maConn.timeline.close == null) {
|
|
120
|
+
maConn.timeline.close = Date.now();
|
|
78
121
|
}
|
|
79
|
-
|
|
122
|
+
if (socket.destroyed) {
|
|
123
|
+
clearTimeout(timeout);
|
|
124
|
+
}
|
|
125
|
+
reject(err);
|
|
80
126
|
});
|
|
127
|
+
// shorten inactivity timeout
|
|
128
|
+
socket.setTimeout(closeTimeout);
|
|
129
|
+
// close writable end of the socket
|
|
130
|
+
socket.end();
|
|
131
|
+
if (socket.writableLength > 0) {
|
|
132
|
+
// there are outgoing bytes waiting to be sent
|
|
133
|
+
socket.once('drain', () => {
|
|
134
|
+
log('%s:%s socket drained', host, port);
|
|
135
|
+
// all bytes have been sent we can destroy the socket (maybe) before the timeout
|
|
136
|
+
socket.destroy();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// nothing to send, destroy immediately
|
|
141
|
+
socket.destroy();
|
|
142
|
+
}
|
|
81
143
|
});
|
|
82
144
|
}
|
|
83
145
|
};
|
|
84
|
-
socket.once('close', () => {
|
|
85
|
-
// In instances where `close` was not explicitly called,
|
|
86
|
-
// such as an iterable stream ending, ensure we have set the close
|
|
87
|
-
// timeline
|
|
88
|
-
if (maConn.timeline.close == null) {
|
|
89
|
-
maConn.timeline.close = Date.now();
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
146
|
return maConn;
|
|
93
147
|
};
|
|
94
148
|
//# sourceMappingURL=socket-to-conn.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket-to-conn.js","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,4BAA4B;AAC5B,OAAO,UAAU,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,iBAAiB,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"socket-to-conn.js","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/tcp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.7",
|
|
4
4
|
"description": "Node.js implementation of the TCP module that libp2p uses, which implements the interface-connection and interface-transport interfaces",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p-tcp#readme",
|
|
@@ -153,6 +153,7 @@
|
|
|
153
153
|
"aegir": "^37.0.4",
|
|
154
154
|
"it-all": "^1.0.6",
|
|
155
155
|
"it-pipe": "^2.0.3",
|
|
156
|
+
"p-defer": "^4.0.0",
|
|
156
157
|
"sinon": "^14.0.0",
|
|
157
158
|
"uint8arrays": "^3.0.0"
|
|
158
159
|
}
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -15,7 +15,30 @@ import type { Connection } from '@libp2p/interface-connection'
|
|
|
15
15
|
|
|
16
16
|
const log = logger('libp2p:tcp')
|
|
17
17
|
|
|
18
|
+
export interface TCPOptions {
|
|
19
|
+
/**
|
|
20
|
+
* An optional number in ms that is used as an inactivity timeout after which the socket will be closed
|
|
21
|
+
*/
|
|
22
|
+
inboundSocketInactivityTimeout?: number
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* An optional number in ms that is used as an inactivity timeout after which the socket will be closed
|
|
26
|
+
*/
|
|
27
|
+
outboundSocketInactivityTimeout?: number
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* When closing a socket, wait this long for it to close gracefully before it is closed more forcibly
|
|
31
|
+
*/
|
|
32
|
+
socketCloseTimeout?: number
|
|
33
|
+
}
|
|
34
|
+
|
|
18
35
|
export class TCP implements Transport {
|
|
36
|
+
private readonly opts: TCPOptions
|
|
37
|
+
|
|
38
|
+
constructor (options: TCPOptions = {}) {
|
|
39
|
+
this.opts = options
|
|
40
|
+
}
|
|
41
|
+
|
|
19
42
|
get [symbol] (): true {
|
|
20
43
|
return true
|
|
21
44
|
}
|
|
@@ -26,13 +49,19 @@ export class TCP implements Transport {
|
|
|
26
49
|
|
|
27
50
|
async dial (ma: Multiaddr, options: DialOptions): Promise<Connection> {
|
|
28
51
|
const socket = await this._connect(ma, options)
|
|
52
|
+
socket.setKeepAlive(true)
|
|
29
53
|
|
|
30
54
|
// Avoid uncaught errors caused by unstable connections
|
|
31
55
|
socket.on('error', err => {
|
|
32
56
|
log('socket error', err)
|
|
33
57
|
})
|
|
34
58
|
|
|
35
|
-
const maConn = toMultiaddrConnection(socket, {
|
|
59
|
+
const maConn = toMultiaddrConnection(socket, {
|
|
60
|
+
remoteAddr: ma,
|
|
61
|
+
signal: options.signal,
|
|
62
|
+
socketInactivityTimeout: this.opts.outboundSocketInactivityTimeout,
|
|
63
|
+
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
64
|
+
})
|
|
36
65
|
log('new outbound connection %s', maConn.remoteAddr)
|
|
37
66
|
const conn = await options.upgrader.upgradeOutbound(maConn)
|
|
38
67
|
log('outbound connection %s upgraded', maConn.remoteAddr)
|
|
@@ -108,7 +137,11 @@ export class TCP implements Transport {
|
|
|
108
137
|
* `upgrader.upgradeInbound`.
|
|
109
138
|
*/
|
|
110
139
|
createListener (options: CreateListenerOptions) {
|
|
111
|
-
return createListener(
|
|
140
|
+
return createListener({
|
|
141
|
+
...options,
|
|
142
|
+
socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
|
|
143
|
+
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
144
|
+
})
|
|
112
145
|
}
|
|
113
146
|
|
|
114
147
|
/**
|
package/src/listener.ts
CHANGED
|
@@ -32,6 +32,8 @@ async function attemptClose (maConn: MultiaddrConnection) {
|
|
|
32
32
|
interface Context {
|
|
33
33
|
handler?: (conn: Connection) => void
|
|
34
34
|
upgrader: Upgrader
|
|
35
|
+
socketInactivityTimeout?: number
|
|
36
|
+
socketCloseTimeout?: number
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/**
|
|
@@ -39,13 +41,15 @@ interface Context {
|
|
|
39
41
|
*/
|
|
40
42
|
export function createListener (context: Context) {
|
|
41
43
|
const {
|
|
42
|
-
handler, upgrader
|
|
44
|
+
handler, upgrader, socketInactivityTimeout, socketCloseTimeout
|
|
43
45
|
} = context
|
|
44
46
|
|
|
45
47
|
let peerId: string | null
|
|
46
48
|
let listeningAddr: Multiaddr
|
|
47
49
|
|
|
48
50
|
const server: ServerWithMultiaddrConnections = Object.assign(net.createServer(socket => {
|
|
51
|
+
socket.setKeepAlive(true)
|
|
52
|
+
|
|
49
53
|
// Avoid uncaught errors caused by unstable connections
|
|
50
54
|
socket.on('error', err => {
|
|
51
55
|
log('socket error', err)
|
|
@@ -53,7 +57,11 @@ export function createListener (context: Context) {
|
|
|
53
57
|
|
|
54
58
|
let maConn: MultiaddrConnection
|
|
55
59
|
try {
|
|
56
|
-
maConn = toMultiaddrConnection(socket, {
|
|
60
|
+
maConn = toMultiaddrConnection(socket, {
|
|
61
|
+
listeningAddr,
|
|
62
|
+
socketInactivityTimeout,
|
|
63
|
+
socketCloseTimeout
|
|
64
|
+
})
|
|
57
65
|
} catch (err) {
|
|
58
66
|
log.error('inbound connection failed', err)
|
|
59
67
|
return
|
|
@@ -105,12 +113,16 @@ export function createListener (context: Context) {
|
|
|
105
113
|
throw new Error('Incorrect server address type')
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
try {
|
|
117
|
+
// Because TCP will only return the IPv6 version
|
|
118
|
+
// we need to capture from the passed multiaddr
|
|
119
|
+
if (listeningAddr.toString().startsWith('/ip4')) {
|
|
120
|
+
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port))
|
|
121
|
+
} else if (address.family === 'IPv6') {
|
|
122
|
+
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port))
|
|
123
|
+
}
|
|
124
|
+
} catch (err) {
|
|
125
|
+
log.error('could not turn %s:%s into multiaddr', address.address, address.port, err)
|
|
114
126
|
}
|
|
115
127
|
|
|
116
128
|
return addrs.map(ma => peerId != null ? ma.encapsulate(`/p2p/${peerId}`) : ma)
|
|
@@ -139,9 +151,9 @@ export function createListener (context: Context) {
|
|
|
139
151
|
return
|
|
140
152
|
}
|
|
141
153
|
|
|
142
|
-
await Promise.all(
|
|
154
|
+
await Promise.all(
|
|
143
155
|
server.__connections.map(async maConn => await attemptClose(maConn))
|
|
144
|
-
|
|
156
|
+
)
|
|
145
157
|
|
|
146
158
|
await new Promise<void>((resolve, reject) => {
|
|
147
159
|
server.close(err => (err != null) ? reject(err) : resolve())
|
package/src/socket-to-conn.ts
CHANGED
|
@@ -3,7 +3,8 @@ import { logger } from '@libp2p/logger'
|
|
|
3
3
|
// @ts-expect-error no types
|
|
4
4
|
import toIterable from 'stream-to-it'
|
|
5
5
|
import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr'
|
|
6
|
-
import { CLOSE_TIMEOUT } from './constants.js'
|
|
6
|
+
import { CLOSE_TIMEOUT, SOCKET_TIMEOUT } from './constants.js'
|
|
7
|
+
import errCode from 'err-code'
|
|
7
8
|
import type { Socket } from 'net'
|
|
8
9
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
9
10
|
import type { MultiaddrConnection } from '@libp2p/interface-connection'
|
|
@@ -15,6 +16,8 @@ interface ToConnectionOptions {
|
|
|
15
16
|
remoteAddr?: Multiaddr
|
|
16
17
|
localAddr?: Multiaddr
|
|
17
18
|
signal?: AbortSignal
|
|
19
|
+
socketInactivityTimeout?: number
|
|
20
|
+
socketCloseTimeout?: number
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/**
|
|
@@ -23,6 +26,8 @@ interface ToConnectionOptions {
|
|
|
23
26
|
*/
|
|
24
27
|
export const toMultiaddrConnection = (socket: Socket, options?: ToConnectionOptions) => {
|
|
25
28
|
options = options ?? {}
|
|
29
|
+
const inactivityTimeout = options.socketInactivityTimeout ?? SOCKET_TIMEOUT
|
|
30
|
+
const closeTimeout = options.socketCloseTimeout ?? CLOSE_TIMEOUT
|
|
26
31
|
|
|
27
32
|
// Check if we are connected on a unix path
|
|
28
33
|
if (options.listeningAddr?.getPath() != null) {
|
|
@@ -33,8 +38,56 @@ export const toMultiaddrConnection = (socket: Socket, options?: ToConnectionOpti
|
|
|
33
38
|
options.localAddr = options.remoteAddr
|
|
34
39
|
}
|
|
35
40
|
|
|
41
|
+
let remoteAddr: Multiaddr
|
|
42
|
+
|
|
43
|
+
if (options.remoteAddr != null) {
|
|
44
|
+
remoteAddr = options.remoteAddr
|
|
45
|
+
} else {
|
|
46
|
+
if (socket.remoteAddress == null || socket.remotePort == null) {
|
|
47
|
+
// this can be undefined if the socket is destroyed (for example, if the client disconnected)
|
|
48
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketremoteaddress
|
|
49
|
+
throw errCode(new Error('Could not determine remote address or port'), 'ERR_NO_REMOTE_ADDRESS')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
remoteAddr = toMultiaddr(socket.remoteAddress, socket.remotePort)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { host, port } = remoteAddr.toOptions()
|
|
36
56
|
const { sink, source } = toIterable.duplex(socket)
|
|
37
57
|
|
|
58
|
+
// by default there is no timeout
|
|
59
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketsettimeouttimeout-callback
|
|
60
|
+
socket.setTimeout(inactivityTimeout, () => {
|
|
61
|
+
log('%s:%s socket read timeout', host, port)
|
|
62
|
+
|
|
63
|
+
// only destroy with an error if the remote has not sent the FIN message
|
|
64
|
+
let err: Error | undefined
|
|
65
|
+
if (socket.readable) {
|
|
66
|
+
err = errCode(new Error('Socket read timeout'), 'ERR_SOCKET_READ_TIMEOUT')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// if the socket times out due to inactivity we must manually close the connection
|
|
70
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-timeout
|
|
71
|
+
socket.destroy(err)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
socket.once('close', () => {
|
|
75
|
+
log('%s:%s socket closed', host, port)
|
|
76
|
+
|
|
77
|
+
// In instances where `close` was not explicitly called,
|
|
78
|
+
// such as an iterable stream ending, ensure we have set the close
|
|
79
|
+
// timeline
|
|
80
|
+
if (maConn.timeline.close == null) {
|
|
81
|
+
maConn.timeline.close = Date.now()
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
socket.once('end', () => {
|
|
86
|
+
// the remote sent a FIN packet which means no more data will be sent
|
|
87
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-end
|
|
88
|
+
log('socket ended', maConn.remoteAddr.toString())
|
|
89
|
+
})
|
|
90
|
+
|
|
38
91
|
const maConn: MultiaddrConnection = {
|
|
39
92
|
async sink (source) {
|
|
40
93
|
if ((options?.signal) != null) {
|
|
@@ -42,13 +95,7 @@ export const toMultiaddrConnection = (socket: Socket, options?: ToConnectionOpti
|
|
|
42
95
|
}
|
|
43
96
|
|
|
44
97
|
try {
|
|
45
|
-
await sink(
|
|
46
|
-
for await (const chunk of source) {
|
|
47
|
-
// Convert BufferList to Buffer
|
|
48
|
-
// Sink in StreamMuxer define argument as Uint8Array so chunk type infers as number which can't be sliced
|
|
49
|
-
yield Buffer.isBuffer(chunk) ? chunk : chunk.slice()
|
|
50
|
-
}
|
|
51
|
-
})())
|
|
98
|
+
await sink(source)
|
|
52
99
|
} catch (err: any) {
|
|
53
100
|
// If aborted we can safely ignore
|
|
54
101
|
if (err.type !== 'aborted') {
|
|
@@ -58,66 +105,84 @@ export const toMultiaddrConnection = (socket: Socket, options?: ToConnectionOpti
|
|
|
58
105
|
log(err)
|
|
59
106
|
}
|
|
60
107
|
}
|
|
108
|
+
|
|
109
|
+
// we have finished writing, send the FIN message
|
|
110
|
+
socket.end()
|
|
61
111
|
},
|
|
62
112
|
|
|
63
|
-
// Missing Type for "abortable"
|
|
64
113
|
source: (options.signal != null) ? abortableSource(source, options.signal) : source,
|
|
65
114
|
|
|
66
115
|
// If the remote address was passed, use it - it may have the peer ID encapsulated
|
|
67
|
-
remoteAddr
|
|
116
|
+
remoteAddr,
|
|
68
117
|
|
|
69
118
|
timeline: { open: Date.now() },
|
|
70
119
|
|
|
71
120
|
async close () {
|
|
72
|
-
if (socket.destroyed)
|
|
121
|
+
if (socket.destroyed) {
|
|
122
|
+
log('%s:%s socket was already destroyed when trying to close', host, port)
|
|
123
|
+
return
|
|
124
|
+
}
|
|
73
125
|
|
|
74
|
-
|
|
126
|
+
log('%s:%s closing socket', host, port)
|
|
127
|
+
await new Promise<void>((resolve, reject) => {
|
|
75
128
|
const start = Date.now()
|
|
76
129
|
|
|
77
130
|
// Attempt to end the socket. If it takes longer to close than the
|
|
78
131
|
// timeout, destroy it manually.
|
|
79
132
|
const timeout = setTimeout(() => {
|
|
80
|
-
const { host, port } = maConn.remoteAddr.toOptions()
|
|
81
|
-
log(
|
|
82
|
-
'timeout closing socket to %s:%s after %dms, destroying it manually',
|
|
83
|
-
host,
|
|
84
|
-
port,
|
|
85
|
-
Date.now() - start
|
|
86
|
-
)
|
|
87
|
-
|
|
88
133
|
if (socket.destroyed) {
|
|
89
134
|
log('%s:%s is already destroyed', host, port)
|
|
135
|
+
resolve()
|
|
90
136
|
} else {
|
|
91
|
-
socket.
|
|
92
|
-
}
|
|
137
|
+
log('%s:%s socket close timeout after %dms, destroying it manually', host, port, Date.now() - start)
|
|
93
138
|
|
|
94
|
-
|
|
95
|
-
|
|
139
|
+
// will trigger 'error' and 'close' events that resolves promise
|
|
140
|
+
socket.destroy(errCode(new Error('Socket close timeout'), 'ERR_SOCKET_CLOSE_TIMEOUT'))
|
|
141
|
+
}
|
|
142
|
+
}, closeTimeout).unref()
|
|
96
143
|
|
|
97
144
|
socket.once('close', () => {
|
|
145
|
+
log('%s:%s socket closed', host, port)
|
|
146
|
+
// socket completely closed
|
|
98
147
|
clearTimeout(timeout)
|
|
99
148
|
resolve()
|
|
100
149
|
})
|
|
101
|
-
socket.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
150
|
+
socket.once('error', (err: Error) => {
|
|
151
|
+
log('%s:%s socket error', host, port, err)
|
|
152
|
+
|
|
153
|
+
// error closing socket
|
|
154
|
+
if (maConn.timeline.close == null) {
|
|
155
|
+
maConn.timeline.close = Date.now()
|
|
106
156
|
}
|
|
107
|
-
|
|
157
|
+
|
|
158
|
+
if (socket.destroyed) {
|
|
159
|
+
clearTimeout(timeout)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
reject(err)
|
|
108
163
|
})
|
|
164
|
+
|
|
165
|
+
// shorten inactivity timeout
|
|
166
|
+
socket.setTimeout(closeTimeout)
|
|
167
|
+
|
|
168
|
+
// close writable end of the socket
|
|
169
|
+
socket.end()
|
|
170
|
+
|
|
171
|
+
if (socket.writableLength > 0) {
|
|
172
|
+
// there are outgoing bytes waiting to be sent
|
|
173
|
+
socket.once('drain', () => {
|
|
174
|
+
log('%s:%s socket drained', host, port)
|
|
175
|
+
|
|
176
|
+
// all bytes have been sent we can destroy the socket (maybe) before the timeout
|
|
177
|
+
socket.destroy()
|
|
178
|
+
})
|
|
179
|
+
} else {
|
|
180
|
+
// nothing to send, destroy immediately
|
|
181
|
+
socket.destroy()
|
|
182
|
+
}
|
|
109
183
|
})
|
|
110
184
|
}
|
|
111
185
|
}
|
|
112
186
|
|
|
113
|
-
socket.once('close', () => {
|
|
114
|
-
// In instances where `close` was not explicitly called,
|
|
115
|
-
// such as an iterable stream ending, ensure we have set the close
|
|
116
|
-
// timeline
|
|
117
|
-
if (maConn.timeline.close == null) {
|
|
118
|
-
maConn.timeline.close = Date.now()
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
|
|
122
187
|
return maConn
|
|
123
188
|
}
|