@libp2p/tcp 4.0.1 → 4.1.0
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/dist/src/index.d.ts +7 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/listener.d.ts +16 -5
- package/dist/src/listener.d.ts.map +1 -1
- package/dist/src/listener.js +81 -80
- package/dist/src/listener.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +12 -5
- package/src/listener.ts +92 -92
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import net from 'net';
|
|
3
|
-
import { CreateListenerOptions, DialOptions, symbol, Transport } from '@libp2p/interface-transport';
|
|
3
|
+
import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from '@libp2p/interface-transport';
|
|
4
4
|
import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr';
|
|
5
5
|
import type { Connection } from '@libp2p/interface-connection';
|
|
6
6
|
export interface TCPOptions {
|
|
@@ -16,6 +16,11 @@ export interface TCPOptions {
|
|
|
16
16
|
* When closing a socket, wait this long for it to close gracefully before it is closed more forcibly
|
|
17
17
|
*/
|
|
18
18
|
socketCloseTimeout?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Set this property to reject connections when the server's connection count gets high.
|
|
21
|
+
* https://nodejs.org/api/net.html#servermaxconnections
|
|
22
|
+
*/
|
|
23
|
+
maxConnections?: number;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Expose a subset of net.connect options
|
|
@@ -42,7 +47,7 @@ export declare class TCP implements Transport {
|
|
|
42
47
|
* anytime a new incoming Connection has been successfully upgraded via
|
|
43
48
|
* `upgrader.upgradeInbound`.
|
|
44
49
|
*/
|
|
45
|
-
createListener(options: TCPCreateListenerOptions):
|
|
50
|
+
createListener(options: TCPCreateListenerOptions): Listener;
|
|
46
51
|
/**
|
|
47
52
|
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
|
|
48
53
|
*/
|
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;
|
|
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,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAA;AAC7G,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEtE,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;IAE3B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW,EAAE,gBAAgB;CAEpE;AAED,MAAM,WAAW,wBAAyB,SAAQ,qBAAqB,EAAE,gBAAgB;CAExF;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,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAsBlE,QAAQ,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc;IAgEtD;;;;OAIG;IACH,cAAc,CAAE,OAAO,EAAE,wBAAwB,GAAG,QAAQ;IAS5D;;OAEG;IACH,MAAM,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;CAe9C"}
|
package/dist/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as mafmt from '@multiformats/mafmt';
|
|
|
3
3
|
import errCode from 'err-code';
|
|
4
4
|
import { logger } from '@libp2p/logger';
|
|
5
5
|
import { toMultiaddrConnection } from './socket-to-conn.js';
|
|
6
|
-
import {
|
|
6
|
+
import { TCPListener } from './listener.js';
|
|
7
7
|
import { multiaddrToNetConfig } from './utils.js';
|
|
8
8
|
import { AbortError } from '@libp2p/interfaces/errors';
|
|
9
9
|
import { CODE_CIRCUIT, CODE_P2P, CODE_UNIX } from './constants.js';
|
|
@@ -92,8 +92,9 @@ export class TCP {
|
|
|
92
92
|
* `upgrader.upgradeInbound`.
|
|
93
93
|
*/
|
|
94
94
|
createListener(options) {
|
|
95
|
-
return
|
|
95
|
+
return new TCPListener({
|
|
96
96
|
...options,
|
|
97
|
+
maxConnections: this.opts.maxConnections,
|
|
97
98
|
socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
|
|
98
99
|
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
99
100
|
});
|
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,
|
|
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,15 +1,26 @@
|
|
|
1
|
+
import { EventEmitter } from '@libp2p/interfaces/events';
|
|
1
2
|
import type { Connection } from '@libp2p/interface-connection';
|
|
2
|
-
import type { Upgrader, Listener } from '@libp2p/interface-transport';
|
|
3
|
+
import type { Upgrader, Listener, ListenerEvents } from '@libp2p/interface-transport';
|
|
4
|
+
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
3
5
|
import type { TCPCreateListenerOptions } from './index.js';
|
|
4
6
|
interface Context extends TCPCreateListenerOptions {
|
|
5
7
|
handler?: (conn: Connection) => void;
|
|
6
8
|
upgrader: Upgrader;
|
|
7
9
|
socketInactivityTimeout?: number;
|
|
8
10
|
socketCloseTimeout?: number;
|
|
11
|
+
maxConnections?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class TCPListener extends EventEmitter<ListenerEvents> implements Listener {
|
|
14
|
+
private readonly context;
|
|
15
|
+
private readonly server;
|
|
16
|
+
/** Keep track of open connections to destroy in case of timeout */
|
|
17
|
+
private readonly connections;
|
|
18
|
+
private status;
|
|
19
|
+
constructor(context: Context);
|
|
20
|
+
private onSocket;
|
|
21
|
+
getAddrs(): Multiaddr[];
|
|
22
|
+
listen(ma: Multiaddr): Promise<void>;
|
|
23
|
+
close(): Promise<void>;
|
|
9
24
|
}
|
|
10
|
-
/**
|
|
11
|
-
* Create listener
|
|
12
|
-
*/
|
|
13
|
-
export declare function createListener(context: Context): Listener;
|
|
14
25
|
export {};
|
|
15
26
|
//# sourceMappingURL=listener.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAe,MAAM,2BAA2B,CAAA;AACrE,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACnF,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAe1D,UAAU,OAAQ,SAAQ,wBAAwB;IAChD,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;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAID,qBAAa,WAAY,SAAQ,YAAY,CAAC,cAAc,CAAE,YAAW,QAAQ;IAOlE,OAAO,CAAC,QAAQ,CAAC,OAAO;IANrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAE7D,OAAO,CAAC,MAAM,CAA6B;gBAEb,OAAO,EAAE,OAAO;IAoB9C,OAAO,CAAC,QAAQ;IAqDhB,QAAQ;IAgCF,MAAM,CAAE,EAAE,EAAE,SAAS;IAkBrB,KAAK;CAaZ"}
|
package/dist/src/listener.js
CHANGED
|
@@ -16,15 +16,27 @@ async function attemptClose(maConn) {
|
|
|
16
16
|
log.error('an error occurred closing the connection', err);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
export class TCPListener extends EventEmitter {
|
|
20
|
+
constructor(context) {
|
|
21
|
+
super();
|
|
22
|
+
this.context = context;
|
|
23
|
+
/** Keep track of open connections to destroy in case of timeout */
|
|
24
|
+
this.connections = new Set();
|
|
25
|
+
this.status = { started: false };
|
|
26
|
+
context.keepAlive = context.keepAlive ?? true;
|
|
27
|
+
this.server = net.createServer(context, this.onSocket.bind(this));
|
|
28
|
+
// https://nodejs.org/api/net.html#servermaxconnections
|
|
29
|
+
// If set reject connections when the server's connection count gets high
|
|
30
|
+
// Useful to prevent too resource exhaustion via many open connections on high bursts of activity
|
|
31
|
+
if (context.maxConnections !== undefined) {
|
|
32
|
+
this.server.maxConnections = context.maxConnections;
|
|
33
|
+
}
|
|
34
|
+
this.server
|
|
35
|
+
.on('listening', () => this.dispatchEvent(new CustomEvent('listening')))
|
|
36
|
+
.on('error', err => this.dispatchEvent(new CustomEvent('error', { detail: err })))
|
|
37
|
+
.on('close', () => this.dispatchEvent(new CustomEvent('close')));
|
|
38
|
+
}
|
|
39
|
+
onSocket(socket) {
|
|
28
40
|
// Avoid uncaught errors caused by unstable connections
|
|
29
41
|
socket.on('error', err => {
|
|
30
42
|
log('socket error', err);
|
|
@@ -32,9 +44,9 @@ export function createListener(context) {
|
|
|
32
44
|
let maConn;
|
|
33
45
|
try {
|
|
34
46
|
maConn = toMultiaddrConnection(socket, {
|
|
35
|
-
listeningAddr,
|
|
36
|
-
socketInactivityTimeout,
|
|
37
|
-
socketCloseTimeout
|
|
47
|
+
listeningAddr: this.status.started ? this.status.listeningAddr : undefined,
|
|
48
|
+
socketInactivityTimeout: this.context.socketInactivityTimeout,
|
|
49
|
+
socketCloseTimeout: this.context.socketCloseTimeout
|
|
38
50
|
});
|
|
39
51
|
}
|
|
40
52
|
catch (err) {
|
|
@@ -43,14 +55,17 @@ export function createListener(context) {
|
|
|
43
55
|
}
|
|
44
56
|
log('new inbound connection %s', maConn.remoteAddr);
|
|
45
57
|
try {
|
|
46
|
-
upgrader.upgradeInbound(maConn)
|
|
58
|
+
this.context.upgrader.upgradeInbound(maConn)
|
|
47
59
|
.then((conn) => {
|
|
48
60
|
log('inbound connection %s upgraded', maConn.remoteAddr);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
this.connections.add(maConn);
|
|
62
|
+
socket.once('close', () => {
|
|
63
|
+
this.connections.delete(maConn);
|
|
64
|
+
});
|
|
65
|
+
if (this.context.handler != null) {
|
|
66
|
+
this.context.handler(conn);
|
|
52
67
|
}
|
|
53
|
-
|
|
68
|
+
this.dispatchEvent(new CustomEvent('connection', { detail: conn }));
|
|
54
69
|
})
|
|
55
70
|
.catch(async (err) => {
|
|
56
71
|
log.error('inbound connection failed', err);
|
|
@@ -67,74 +82,60 @@ export function createListener(context) {
|
|
|
67
82
|
log.error('closing inbound connection failed', err);
|
|
68
83
|
});
|
|
69
84
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
else if (address.family === 'IPv6') {
|
|
91
|
-
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port));
|
|
92
|
-
}
|
|
85
|
+
}
|
|
86
|
+
getAddrs() {
|
|
87
|
+
if (!this.status.started) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
let addrs = [];
|
|
91
|
+
const address = this.server.address();
|
|
92
|
+
const { listeningAddr, peerId } = this.status;
|
|
93
|
+
if (address == null) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
if (typeof address === 'string') {
|
|
97
|
+
addrs = [listeningAddr];
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
try {
|
|
101
|
+
// Because TCP will only return the IPv6 version
|
|
102
|
+
// we need to capture from the passed multiaddr
|
|
103
|
+
if (listeningAddr.toString().startsWith('/ip4')) {
|
|
104
|
+
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port));
|
|
93
105
|
}
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
else if (address.family === 'IPv6') {
|
|
107
|
+
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port));
|
|
96
108
|
}
|
|
97
109
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
listen: async (ma) => {
|
|
101
|
-
listeningAddr = ma;
|
|
102
|
-
peerId = ma.getPeerId();
|
|
103
|
-
if (peerId == null) {
|
|
104
|
-
listeningAddr = ma.decapsulateCode(CODE_P2P);
|
|
110
|
+
catch (err) {
|
|
111
|
+
log.error('could not turn %s:%s into multiaddr', address.address, address.port, err);
|
|
105
112
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
await Promise.all(server.__connections.map(async (maConn) => await attemptClose(maConn)));
|
|
122
|
-
await new Promise((resolve, reject) => {
|
|
123
|
-
server.close(err => (err != null) ? reject(err) : resolve());
|
|
113
|
+
}
|
|
114
|
+
return addrs.map(ma => peerId != null ? ma.encapsulate(`/p2p/${peerId}`) : ma);
|
|
115
|
+
}
|
|
116
|
+
async listen(ma) {
|
|
117
|
+
const peerId = ma.getPeerId();
|
|
118
|
+
const listeningAddr = peerId == null ? ma.decapsulateCode(CODE_P2P) : ma;
|
|
119
|
+
this.status = { started: true, listeningAddr, peerId };
|
|
120
|
+
return await new Promise((resolve, reject) => {
|
|
121
|
+
const options = multiaddrToNetConfig(listeningAddr);
|
|
122
|
+
this.server.listen(options, (err) => {
|
|
123
|
+
if (err != null) {
|
|
124
|
+
return reject(err);
|
|
125
|
+
}
|
|
126
|
+
log('Listening on %s', this.server.address());
|
|
127
|
+
resolve();
|
|
124
128
|
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async close() {
|
|
132
|
+
if (!this.server.listening) {
|
|
133
|
+
return;
|
|
125
134
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return listener;
|
|
132
|
-
}
|
|
133
|
-
function trackConn(server, maConn, socket) {
|
|
134
|
-
server.__connections.push(maConn);
|
|
135
|
-
const untrackConn = () => {
|
|
136
|
-
server.__connections = server.__connections.filter(c => c !== maConn);
|
|
137
|
-
};
|
|
138
|
-
socket.once('close', untrackConn);
|
|
135
|
+
await Promise.all(Array.from(this.connections.values()).map(async (maConn) => await attemptClose(maConn)));
|
|
136
|
+
await new Promise((resolve, reject) => {
|
|
137
|
+
this.server.close(err => (err != null) ? reject(err) : resolve());
|
|
138
|
+
});
|
|
139
|
+
}
|
|
139
140
|
}
|
|
140
141
|
//# sourceMappingURL=listener.js.map
|
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;
|
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/tcp",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
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",
|
package/src/index.ts
CHANGED
|
@@ -3,11 +3,11 @@ import * as mafmt from '@multiformats/mafmt'
|
|
|
3
3
|
import errCode from 'err-code'
|
|
4
4
|
import { logger } from '@libp2p/logger'
|
|
5
5
|
import { toMultiaddrConnection } from './socket-to-conn.js'
|
|
6
|
-
import {
|
|
6
|
+
import { TCPListener } from './listener.js'
|
|
7
7
|
import { multiaddrToNetConfig } from './utils.js'
|
|
8
8
|
import { AbortError } from '@libp2p/interfaces/errors'
|
|
9
9
|
import { CODE_CIRCUIT, CODE_P2P, CODE_UNIX } from './constants.js'
|
|
10
|
-
import { CreateListenerOptions, DialOptions, symbol, Transport } from '@libp2p/interface-transport'
|
|
10
|
+
import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from '@libp2p/interface-transport'
|
|
11
11
|
import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
|
|
12
12
|
import type { Socket, IpcSocketConnectOpts, TcpSocketConnectOpts } from 'net'
|
|
13
13
|
import type { Connection } from '@libp2p/interface-connection'
|
|
@@ -29,6 +29,12 @@ export interface TCPOptions {
|
|
|
29
29
|
* When closing a socket, wait this long for it to close gracefully before it is closed more forcibly
|
|
30
30
|
*/
|
|
31
31
|
socketCloseTimeout?: number
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set this property to reject connections when the server's connection count gets high.
|
|
35
|
+
* https://nodejs.org/api/net.html#servermaxconnections
|
|
36
|
+
*/
|
|
37
|
+
maxConnections?: number
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
/**
|
|
@@ -155,9 +161,10 @@ export class TCP implements Transport {
|
|
|
155
161
|
* anytime a new incoming Connection has been successfully upgraded via
|
|
156
162
|
* `upgrader.upgradeInbound`.
|
|
157
163
|
*/
|
|
158
|
-
createListener (options: TCPCreateListenerOptions) {
|
|
159
|
-
return
|
|
164
|
+
createListener (options: TCPCreateListenerOptions): Listener {
|
|
165
|
+
return new TCPListener({
|
|
160
166
|
...options,
|
|
167
|
+
maxConnections: this.opts.maxConnections,
|
|
161
168
|
socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
|
|
162
169
|
socketCloseTimeout: this.opts.socketCloseTimeout
|
|
163
170
|
})
|
|
@@ -166,7 +173,7 @@ export class TCP implements Transport {
|
|
|
166
173
|
/**
|
|
167
174
|
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
|
|
168
175
|
*/
|
|
169
|
-
filter (multiaddrs: Multiaddr[]) {
|
|
176
|
+
filter (multiaddrs: Multiaddr[]): Multiaddr[] {
|
|
170
177
|
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
|
|
171
178
|
|
|
172
179
|
return multiaddrs.filter(ma => {
|
package/src/listener.ts
CHANGED
|
@@ -8,17 +8,12 @@ import {
|
|
|
8
8
|
} from './utils.js'
|
|
9
9
|
import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events'
|
|
10
10
|
import type { MultiaddrConnection, Connection } from '@libp2p/interface-connection'
|
|
11
|
-
import type { Upgrader, Listener } from '@libp2p/interface-transport'
|
|
12
|
-
import type { Server } from 'net'
|
|
11
|
+
import type { Upgrader, Listener, ListenerEvents } from '@libp2p/interface-transport'
|
|
13
12
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
14
13
|
import type { TCPCreateListenerOptions } from './index.js'
|
|
15
14
|
|
|
16
15
|
const log = logger('libp2p:tcp:listener')
|
|
17
16
|
|
|
18
|
-
interface ServerWithMultiaddrConnections extends Server {
|
|
19
|
-
__connections: MultiaddrConnection[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
/**
|
|
23
18
|
* Attempts to close the given maConn. If a failure occurs, it will be logged
|
|
24
19
|
*/
|
|
@@ -35,22 +30,39 @@ interface Context extends TCPCreateListenerOptions {
|
|
|
35
30
|
upgrader: Upgrader
|
|
36
31
|
socketInactivityTimeout?: number
|
|
37
32
|
socketCloseTimeout?: number
|
|
33
|
+
maxConnections?: number
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
type Status = {started: false} | {started: true, listeningAddr: Multiaddr, peerId: string | null }
|
|
37
|
+
|
|
38
|
+
export class TCPListener extends EventEmitter<ListenerEvents> implements Listener {
|
|
39
|
+
private readonly server: net.Server
|
|
40
|
+
/** Keep track of open connections to destroy in case of timeout */
|
|
41
|
+
private readonly connections = new Set<MultiaddrConnection>()
|
|
42
|
+
|
|
43
|
+
private status: Status = { started: false }
|
|
44
|
+
|
|
45
|
+
constructor (private readonly context: Context) {
|
|
46
|
+
super()
|
|
47
|
+
|
|
48
|
+
context.keepAlive = context.keepAlive ?? true
|
|
49
|
+
|
|
50
|
+
this.server = net.createServer(context, this.onSocket.bind(this))
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
// https://nodejs.org/api/net.html#servermaxconnections
|
|
53
|
+
// If set reject connections when the server's connection count gets high
|
|
54
|
+
// Useful to prevent too resource exhaustion via many open connections on high bursts of activity
|
|
55
|
+
if (context.maxConnections !== undefined) {
|
|
56
|
+
this.server.maxConnections = context.maxConnections
|
|
57
|
+
}
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
this.server
|
|
60
|
+
.on('listening', () => this.dispatchEvent(new CustomEvent('listening')))
|
|
61
|
+
.on('error', err => this.dispatchEvent(new CustomEvent<Error>('error', { detail: err })))
|
|
62
|
+
.on('close', () => this.dispatchEvent(new CustomEvent('close')))
|
|
63
|
+
}
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
private onSocket (socket: net.Socket) {
|
|
54
66
|
// Avoid uncaught errors caused by unstable connections
|
|
55
67
|
socket.on('error', err => {
|
|
56
68
|
log('socket error', err)
|
|
@@ -59,9 +71,9 @@ export function createListener (context: Context) {
|
|
|
59
71
|
let maConn: MultiaddrConnection
|
|
60
72
|
try {
|
|
61
73
|
maConn = toMultiaddrConnection(socket, {
|
|
62
|
-
listeningAddr,
|
|
63
|
-
socketInactivityTimeout,
|
|
64
|
-
socketCloseTimeout
|
|
74
|
+
listeningAddr: this.status.started ? this.status.listeningAddr : undefined,
|
|
75
|
+
socketInactivityTimeout: this.context.socketInactivityTimeout,
|
|
76
|
+
socketCloseTimeout: this.context.socketCloseTimeout
|
|
65
77
|
})
|
|
66
78
|
} catch (err) {
|
|
67
79
|
log.error('inbound connection failed', err)
|
|
@@ -70,16 +82,20 @@ export function createListener (context: Context) {
|
|
|
70
82
|
|
|
71
83
|
log('new inbound connection %s', maConn.remoteAddr)
|
|
72
84
|
try {
|
|
73
|
-
upgrader.upgradeInbound(maConn)
|
|
85
|
+
this.context.upgrader.upgradeInbound(maConn)
|
|
74
86
|
.then((conn) => {
|
|
75
87
|
log('inbound connection %s upgraded', maConn.remoteAddr)
|
|
76
|
-
|
|
88
|
+
this.connections.add(maConn)
|
|
89
|
+
|
|
90
|
+
socket.once('close', () => {
|
|
91
|
+
this.connections.delete(maConn)
|
|
92
|
+
})
|
|
77
93
|
|
|
78
|
-
if (handler != null) {
|
|
79
|
-
handler(conn)
|
|
94
|
+
if (this.context.handler != null) {
|
|
95
|
+
this.context.handler(conn)
|
|
80
96
|
}
|
|
81
97
|
|
|
82
|
-
|
|
98
|
+
this.dispatchEvent(new CustomEvent<Connection>('connection', { detail: conn }))
|
|
83
99
|
})
|
|
84
100
|
.catch(async err => {
|
|
85
101
|
log.error('inbound connection failed', err)
|
|
@@ -97,85 +113,69 @@ export function createListener (context: Context) {
|
|
|
97
113
|
log.error('closing inbound connection failed', err)
|
|
98
114
|
})
|
|
99
115
|
}
|
|
100
|
-
}
|
|
101
|
-
// Keep track of open connections to destroy in case of timeout
|
|
102
|
-
{ __connections: [] })
|
|
116
|
+
}
|
|
103
117
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
getAddrs () {
|
|
119
|
+
if (!this.status.started) {
|
|
120
|
+
return []
|
|
121
|
+
}
|
|
108
122
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
let addrs: Multiaddr[] = []
|
|
124
|
+
const address = this.server.address()
|
|
125
|
+
const { listeningAddr, peerId } = this.status
|
|
112
126
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
if (address == null) {
|
|
128
|
+
return []
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (typeof address === 'string') {
|
|
132
|
+
addrs = [listeningAddr]
|
|
133
|
+
} else {
|
|
134
|
+
try {
|
|
135
|
+
// Because TCP will only return the IPv6 version
|
|
136
|
+
// we need to capture from the passed multiaddr
|
|
137
|
+
if (listeningAddr.toString().startsWith('/ip4')) {
|
|
138
|
+
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port))
|
|
139
|
+
} else if (address.family === 'IPv6') {
|
|
140
|
+
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port))
|
|
126
141
|
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
log.error('could not turn %s:%s into multiaddr', address.address, address.port, err)
|
|
127
144
|
}
|
|
145
|
+
}
|
|
128
146
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
listen: async (ma: Multiaddr) => {
|
|
132
|
-
listeningAddr = ma
|
|
133
|
-
peerId = ma.getPeerId()
|
|
147
|
+
return addrs.map(ma => peerId != null ? ma.encapsulate(`/p2p/${peerId}`) : ma)
|
|
148
|
+
}
|
|
134
149
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
150
|
+
async listen (ma: Multiaddr) {
|
|
151
|
+
const peerId = ma.getPeerId()
|
|
152
|
+
const listeningAddr = peerId == null ? ma.decapsulateCode(CODE_P2P) : ma
|
|
138
153
|
|
|
139
|
-
|
|
140
|
-
const options = multiaddrToNetConfig(listeningAddr)
|
|
141
|
-
server.listen(options, (err?: any) => {
|
|
142
|
-
if (err != null) {
|
|
143
|
-
return reject(err)
|
|
144
|
-
}
|
|
145
|
-
log('Listening on %s', server.address())
|
|
146
|
-
resolve()
|
|
147
|
-
})
|
|
148
|
-
})
|
|
149
|
-
},
|
|
150
|
-
close: async () => {
|
|
151
|
-
if (!server.listening) {
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
+
this.status = { started: true, listeningAddr, peerId }
|
|
154
155
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
156
|
+
return await new Promise<void>((resolve, reject) => {
|
|
157
|
+
const options = multiaddrToNetConfig(listeningAddr)
|
|
158
|
+
this.server.listen(options, (err?: any) => {
|
|
159
|
+
if (err != null) {
|
|
160
|
+
return reject(err)
|
|
161
|
+
}
|
|
162
|
+
log('Listening on %s', this.server.address())
|
|
163
|
+
resolve()
|
|
161
164
|
})
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
server
|
|
166
|
-
.on('listening', () => listener.dispatchEvent(new CustomEvent('listening')))
|
|
167
|
-
.on('error', err => listener.dispatchEvent(new CustomEvent<Error>('error', { detail: err })))
|
|
168
|
-
.on('close', () => listener.dispatchEvent(new CustomEvent('close')))
|
|
165
|
+
})
|
|
166
|
+
}
|
|
169
167
|
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
async close () {
|
|
169
|
+
if (!this.server.listening) {
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
await Promise.all(
|
|
174
|
+
Array.from(this.connections.values()).map(async maConn => await attemptClose(maConn))
|
|
175
|
+
)
|
|
175
176
|
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
await new Promise<void>((resolve, reject) => {
|
|
178
|
+
this.server.close(err => (err != null) ? reject(err) : resolve())
|
|
179
|
+
})
|
|
178
180
|
}
|
|
179
|
-
|
|
180
|
-
socket.once('close', untrackConn)
|
|
181
181
|
}
|