@libp2p/tcp 0.0.0 → 1.0.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/.aegir.cjs +8 -0
- package/.github/workflows/main.yml +125 -0
- package/CHANGELOG.md +453 -0
- package/LICENSE +2 -0
- package/LICENSE-APACHE +5 -0
- package/LICENSE-MIT +19 -0
- package/README.md +114 -0
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +6 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +100 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/listener.d.ts +12 -0
- package/dist/src/listener.d.ts.map +1 -0
- package/dist/src/listener.js +131 -0
- package/dist/src/listener.js.map +1 -0
- package/dist/src/socket-to-conn.d.ts +16 -0
- package/dist/src/socket-to-conn.d.ts.map +1 -0
- package/dist/src/socket-to-conn.js +96 -0
- package/dist/src/socket-to-conn.js.map +1 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +35 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +83 -4
- package/src/constants.ts +6 -0
- package/src/index.ts +147 -0
- package/src/listener.ts +172 -0
- package/src/socket-to-conn.ts +127 -0
- package/src/utils.ts +44 -0
- package/tsconfig.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# js-libp2p-tcp <!-- omit in toc -->
|
|
2
|
+
|
|
3
|
+
[](http://protocol.ai)
|
|
4
|
+
[](http://libp2p.io/)
|
|
5
|
+
[](http://webchat.freenode.net/?channels=%23libp2p)
|
|
6
|
+
[](https://discuss.libp2p.io)
|
|
7
|
+
[](https://codecov.io/gh/libp2p/js-libp2p-tcp)
|
|
8
|
+
[](https://travis-ci.com/libp2p/js-libp2p-tcp)
|
|
9
|
+
[](https://david-dm.org/libp2p/js-libp2p-tcp)
|
|
10
|
+
[](https://github.com/feross/standard)
|
|
11
|
+
|
|
12
|
+
[](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/transport)
|
|
13
|
+
[](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/connection)
|
|
14
|
+
|
|
15
|
+
> JavaScript implementation of the TCP module for libp2p. It exposes the [interface-transport](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/transport) for dial/listen. `libp2p-tcp` is a very thin shim that adds support for dialing to a `multiaddr`. This small shim will enable libp2p to use other transports.
|
|
16
|
+
|
|
17
|
+
## Table of Contents <!-- omit in toc -->
|
|
18
|
+
|
|
19
|
+
- [Install](#install)
|
|
20
|
+
- [npm](#npm)
|
|
21
|
+
- [Usage](#usage)
|
|
22
|
+
- [API](#api)
|
|
23
|
+
- [Transport](#transport)
|
|
24
|
+
- [Connection](#connection)
|
|
25
|
+
- [Contribute](#contribute)
|
|
26
|
+
- [License](#license)
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
### npm
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
> npm install @libp2p/tcp
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
import { TCP } from '@libp2p/tcp'
|
|
40
|
+
import { Multiaddr } from '@multiformats/multiaddr'
|
|
41
|
+
import pipe from 'it-pipe'
|
|
42
|
+
import { collect } from 'streaming-iterables'
|
|
43
|
+
|
|
44
|
+
// A simple upgrader that just returns the MultiaddrConnection
|
|
45
|
+
const upgrader = {
|
|
46
|
+
upgradeInbound: maConn => maConn,
|
|
47
|
+
upgradeOutbound: maConn => maConn
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const tcp = new TCP({ upgrader })
|
|
51
|
+
|
|
52
|
+
const listener = tcp.createListener({}, (socket) => {
|
|
53
|
+
console.log('new connection opened')
|
|
54
|
+
pipe(
|
|
55
|
+
['hello'],
|
|
56
|
+
socket
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const addr = multiaddr('/ip4/127.0.0.1/tcp/9090')
|
|
61
|
+
await listener.listen(addr)
|
|
62
|
+
console.log('listening')
|
|
63
|
+
|
|
64
|
+
const socket = await tcp.dial(addr)
|
|
65
|
+
const values = await pipe(
|
|
66
|
+
socket,
|
|
67
|
+
collect
|
|
68
|
+
)
|
|
69
|
+
console.log(`Value: ${values.toString()}`)
|
|
70
|
+
|
|
71
|
+
// Close connection after reading
|
|
72
|
+
await listener.close()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Outputs:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
listening
|
|
79
|
+
new connection opened
|
|
80
|
+
Value: hello
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## API
|
|
84
|
+
|
|
85
|
+
### Transport
|
|
86
|
+
|
|
87
|
+
[](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/transport)
|
|
88
|
+
|
|
89
|
+
`libp2p-tcp` accepts TCP addresses as both IPFS and non IPFS encapsulated addresses, i.e:
|
|
90
|
+
|
|
91
|
+
`/ip4/127.0.0.1/tcp/4001`
|
|
92
|
+
`/ip4/127.0.0.1/tcp/4001/ipfs/QmHash`
|
|
93
|
+
|
|
94
|
+
(both for dialing and listening)
|
|
95
|
+
|
|
96
|
+
### Connection
|
|
97
|
+
|
|
98
|
+
[](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/connection)
|
|
99
|
+
|
|
100
|
+
## Contribute
|
|
101
|
+
|
|
102
|
+
Contributions are welcome! The libp2p implementation in JavaScript is a work in progress. As such, there's a few things you can do right now to help out:
|
|
103
|
+
|
|
104
|
+
- [Check out the existing issues](//github.com/libp2p/js-libp2p-tcp/issues).
|
|
105
|
+
- **Perform code reviews**.
|
|
106
|
+
- **Add tests**. There can never be enough tests.
|
|
107
|
+
|
|
108
|
+
Please be aware that all interactions related to libp2p are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
|
109
|
+
|
|
110
|
+
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
[MIT](LICENSE) © 2015-2016 David Dias
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import net from 'net';
|
|
3
|
+
import type { Transport, Upgrader } from '@libp2p/interfaces/transport';
|
|
4
|
+
import type { Connection } from '@libp2p/interfaces/connection';
|
|
5
|
+
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
|
8
|
+
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
|
9
|
+
* @typedef {import('libp2p-interfaces/src/transport/types').Upgrader} Upgrader
|
|
10
|
+
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
|
|
11
|
+
* @typedef {import('net').Socket} Socket
|
|
12
|
+
*/
|
|
13
|
+
interface TCPOptions {
|
|
14
|
+
upgrader: Upgrader;
|
|
15
|
+
}
|
|
16
|
+
interface DialOptions {
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
export declare class TCP implements Transport<DialOptions, {}> {
|
|
20
|
+
private readonly _upgrader;
|
|
21
|
+
constructor(options: TCPOptions);
|
|
22
|
+
dial(ma: Multiaddr, options?: DialOptions): Promise<Connection>;
|
|
23
|
+
_connect(ma: Multiaddr, options?: DialOptions): Promise<net.Socket>;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a TCP listener. The provided `handler` function will be called
|
|
26
|
+
* anytime a new incoming Connection has been successfully upgraded via
|
|
27
|
+
* `upgrader.upgradeInbound`.
|
|
28
|
+
*/
|
|
29
|
+
createListener(options: {}, handler?: (connection: Connection) => void): import("@libp2p/interfaces/transport").Listener;
|
|
30
|
+
/**
|
|
31
|
+
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
|
|
32
|
+
*/
|
|
33
|
+
filter(multiaddrs: Multiaddr[]): Multiaddr[];
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AASrB,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAKxD;;;;;;GAMG;AAEH,UAAU,UAAU;IAClB,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,qBAAa,GAAI,YAAW,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;gBAEvB,OAAO,EAAE,UAAU;IAU1B,IAAI,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB;IAe9C,QAAQ,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB;IA+DxD;;;;OAIG;IACH,cAAc,CAAE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI;IAIvE;;OAEG;IACH,MAAM,CAAE,UAAU,EAAE,SAAS,EAAE;CAWhC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import net from 'net';
|
|
2
|
+
import * as mafmt from '@multiformats/mafmt';
|
|
3
|
+
import errCode from 'err-code';
|
|
4
|
+
import debug from 'debug';
|
|
5
|
+
import { toConnection } from './socket-to-conn.js';
|
|
6
|
+
import { createListener } from './listener.js';
|
|
7
|
+
import { multiaddrToNetConfig } from './utils.js';
|
|
8
|
+
import { AbortError } from 'abortable-iterator';
|
|
9
|
+
import { CODE_CIRCUIT, CODE_P2P } from './constants.js';
|
|
10
|
+
const log = debug('libp2p:tcp');
|
|
11
|
+
export class TCP {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
const { upgrader } = options;
|
|
14
|
+
if (upgrader == null) {
|
|
15
|
+
throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.');
|
|
16
|
+
}
|
|
17
|
+
this._upgrader = upgrader;
|
|
18
|
+
}
|
|
19
|
+
async dial(ma, options = {}) {
|
|
20
|
+
const socket = await this._connect(ma, options);
|
|
21
|
+
// Avoid uncaught errors caused by unstable connections
|
|
22
|
+
socket.on('error', err => {
|
|
23
|
+
log('socket error', err);
|
|
24
|
+
});
|
|
25
|
+
const maConn = toConnection(socket, { remoteAddr: ma, signal: options.signal });
|
|
26
|
+
log('new outbound connection %s', maConn.remoteAddr);
|
|
27
|
+
const conn = await this._upgrader.upgradeOutbound(maConn);
|
|
28
|
+
log('outbound connection %s upgraded', maConn.remoteAddr);
|
|
29
|
+
return conn;
|
|
30
|
+
}
|
|
31
|
+
async _connect(ma, options = {}) {
|
|
32
|
+
if (options.signal?.aborted === true) {
|
|
33
|
+
throw new AbortError();
|
|
34
|
+
}
|
|
35
|
+
return await new Promise((resolve, reject) => {
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
const cOpts = multiaddrToNetConfig(ma);
|
|
38
|
+
log('dialing %j', cOpts);
|
|
39
|
+
const rawSocket = net.connect(cOpts);
|
|
40
|
+
const onError = (err) => {
|
|
41
|
+
err.message = `connection error ${cOpts.host}:${cOpts.port}: ${err.message}`;
|
|
42
|
+
done(err);
|
|
43
|
+
};
|
|
44
|
+
const onTimeout = () => {
|
|
45
|
+
log('connection timeout %s:%s', cOpts.host, cOpts.port);
|
|
46
|
+
const err = errCode(new Error(`connection timeout after ${Date.now() - start}ms`), 'ERR_CONNECT_TIMEOUT');
|
|
47
|
+
// Note: this will result in onError() being called
|
|
48
|
+
rawSocket.emit('error', err);
|
|
49
|
+
};
|
|
50
|
+
const onConnect = () => {
|
|
51
|
+
log('connection opened %j', cOpts);
|
|
52
|
+
done();
|
|
53
|
+
};
|
|
54
|
+
const onAbort = () => {
|
|
55
|
+
log('connection aborted %j', cOpts);
|
|
56
|
+
rawSocket.destroy();
|
|
57
|
+
done(new AbortError());
|
|
58
|
+
};
|
|
59
|
+
const done = (err) => {
|
|
60
|
+
rawSocket.removeListener('error', onError);
|
|
61
|
+
rawSocket.removeListener('timeout', onTimeout);
|
|
62
|
+
rawSocket.removeListener('connect', onConnect);
|
|
63
|
+
if (options.signal != null) {
|
|
64
|
+
options.signal.removeEventListener('abort', onAbort);
|
|
65
|
+
}
|
|
66
|
+
if (err != null) {
|
|
67
|
+
return reject(err);
|
|
68
|
+
}
|
|
69
|
+
resolve(rawSocket);
|
|
70
|
+
};
|
|
71
|
+
rawSocket.on('error', onError);
|
|
72
|
+
rawSocket.on('timeout', onTimeout);
|
|
73
|
+
rawSocket.on('connect', onConnect);
|
|
74
|
+
if (options.signal != null) {
|
|
75
|
+
options.signal.addEventListener('abort', onAbort);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Creates a TCP listener. The provided `handler` function will be called
|
|
81
|
+
* anytime a new incoming Connection has been successfully upgraded via
|
|
82
|
+
* `upgrader.upgradeInbound`.
|
|
83
|
+
*/
|
|
84
|
+
createListener(options, handler) {
|
|
85
|
+
return createListener({ handler: handler, upgrader: this._upgrader });
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
|
|
89
|
+
*/
|
|
90
|
+
filter(multiaddrs) {
|
|
91
|
+
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs];
|
|
92
|
+
return multiaddrs.filter(ma => {
|
|
93
|
+
if (ma.protoCodes().includes(CODE_CIRCUIT)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return mafmt.TCP.matches(ma.decapsulateCode(CODE_P2P));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Connection } from '@libp2p/interfaces/connection';
|
|
2
|
+
import type { Upgrader, Listener } from '@libp2p/interfaces/transport';
|
|
3
|
+
interface Context {
|
|
4
|
+
handler?: (conn: Connection) => void;
|
|
5
|
+
upgrader: Upgrader;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create listener
|
|
9
|
+
*/
|
|
10
|
+
export declare function createListener(context: Context): Listener;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=listener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAuB,QAAQ,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAuB3F,UAAU,OAAO;IACf,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAE,OAAO,EAAE,OAAO,YAuH/C"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import net from 'net';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { toConnection } from './socket-to-conn.js';
|
|
5
|
+
import { CODE_P2P } from './constants.js';
|
|
6
|
+
import { getMultiaddrs, multiaddrToNetConfig } from './utils.js';
|
|
7
|
+
const log = Object.assign(debug('libp2p:tcp:listener'), { error: debug('libp2p:tcp:listener:error') });
|
|
8
|
+
/**
|
|
9
|
+
* Attempts to close the given maConn. If a failure occurs, it will be logged
|
|
10
|
+
*/
|
|
11
|
+
async function attemptClose(maConn) {
|
|
12
|
+
try {
|
|
13
|
+
await maConn.close();
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
log.error('an error occurred closing the connection', err);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create listener
|
|
21
|
+
*/
|
|
22
|
+
export function createListener(context) {
|
|
23
|
+
const { handler, upgrader } = context;
|
|
24
|
+
let peerId;
|
|
25
|
+
let listeningAddr;
|
|
26
|
+
const server = Object.assign(net.createServer(socket => {
|
|
27
|
+
// Avoid uncaught errors caused by unstable connections
|
|
28
|
+
socket.on('error', err => {
|
|
29
|
+
log('socket error', err);
|
|
30
|
+
});
|
|
31
|
+
let maConn;
|
|
32
|
+
try {
|
|
33
|
+
maConn = toConnection(socket, { listeningAddr });
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
log.error('inbound connection failed', err);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
log('new inbound connection %s', maConn.remoteAddr);
|
|
40
|
+
try {
|
|
41
|
+
upgrader.upgradeInbound(maConn)
|
|
42
|
+
.then((conn) => {
|
|
43
|
+
log('inbound connection %s upgraded', maConn.remoteAddr);
|
|
44
|
+
trackConn(server, maConn);
|
|
45
|
+
if (handler != null) {
|
|
46
|
+
handler(conn);
|
|
47
|
+
}
|
|
48
|
+
listener.emit('connection', conn);
|
|
49
|
+
})
|
|
50
|
+
.catch(async (err) => {
|
|
51
|
+
log.error('inbound connection failed', err);
|
|
52
|
+
await attemptClose(maConn);
|
|
53
|
+
})
|
|
54
|
+
.catch(err => {
|
|
55
|
+
log.error('closing inbound connection failed', err);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
log.error('inbound connection failed', err);
|
|
60
|
+
attemptClose(maConn)
|
|
61
|
+
.catch(err => {
|
|
62
|
+
log.error('closing inbound connection failed', err);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}),
|
|
66
|
+
// Keep track of open connections to destroy in case of timeout
|
|
67
|
+
{ __connections: [] });
|
|
68
|
+
const listener = Object.assign(new EventEmitter(), {
|
|
69
|
+
getAddrs: () => {
|
|
70
|
+
let addrs = [];
|
|
71
|
+
const address = server.address();
|
|
72
|
+
if (address == null) {
|
|
73
|
+
throw new Error('Listener is not ready yet');
|
|
74
|
+
}
|
|
75
|
+
if (typeof address === 'string') {
|
|
76
|
+
throw new Error('Incorrect server address type');
|
|
77
|
+
}
|
|
78
|
+
// Because TCP will only return the IPv6 version
|
|
79
|
+
// we need to capture from the passed multiaddr
|
|
80
|
+
if (listeningAddr.toString().startsWith('/ip4')) {
|
|
81
|
+
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port));
|
|
82
|
+
}
|
|
83
|
+
else if (address.family === 'IPv6') {
|
|
84
|
+
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port));
|
|
85
|
+
}
|
|
86
|
+
return addrs.map(ma => peerId != null ? ma.encapsulate(`/p2p/${peerId}`) : ma);
|
|
87
|
+
},
|
|
88
|
+
listen: async (ma) => {
|
|
89
|
+
listeningAddr = ma;
|
|
90
|
+
peerId = ma.getPeerId();
|
|
91
|
+
if (peerId == null) {
|
|
92
|
+
listeningAddr = ma.decapsulateCode(CODE_P2P);
|
|
93
|
+
}
|
|
94
|
+
return await new Promise((resolve, reject) => {
|
|
95
|
+
const options = multiaddrToNetConfig(listeningAddr);
|
|
96
|
+
server.listen(options, (err) => {
|
|
97
|
+
if (err != null) {
|
|
98
|
+
return reject(err);
|
|
99
|
+
}
|
|
100
|
+
log('Listening on %s', server.address());
|
|
101
|
+
resolve();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
close: async () => {
|
|
106
|
+
if (!server.listening) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await Promise.all([
|
|
110
|
+
server.__connections.map(async (maConn) => await attemptClose(maConn))
|
|
111
|
+
]);
|
|
112
|
+
await new Promise((resolve, reject) => {
|
|
113
|
+
server.close(err => (err != null) ? reject(err) : resolve());
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
server
|
|
118
|
+
.on('listening', () => listener.emit('listening'))
|
|
119
|
+
.on('error', err => listener.emit('error', err))
|
|
120
|
+
.on('close', () => listener.emit('close'));
|
|
121
|
+
return listener;
|
|
122
|
+
}
|
|
123
|
+
function trackConn(server, maConn) {
|
|
124
|
+
server.__connections.push(maConn);
|
|
125
|
+
const untrackConn = () => {
|
|
126
|
+
server.__connections = server.__connections.filter(c => c !== maConn);
|
|
127
|
+
};
|
|
128
|
+
// @ts-expect-error
|
|
129
|
+
maConn.conn.once('close', untrackConn);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/listener.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Socket } from 'net';
|
|
2
|
+
import type { Multiaddr } from '@multiformats/multiaddr';
|
|
3
|
+
import type { MultiaddrConnection } from '@libp2p/interfaces/transport';
|
|
4
|
+
interface ToConnectionOptions {
|
|
5
|
+
listeningAddr?: Multiaddr;
|
|
6
|
+
remoteAddr?: Multiaddr;
|
|
7
|
+
localAddr?: Multiaddr;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Convert a socket into a MultiaddrConnection
|
|
12
|
+
* https://github.com/libp2p/interface-transport#multiaddrconnection
|
|
13
|
+
*/
|
|
14
|
+
export declare const toConnection: (socket: Socket, options?: ToConnectionOptions | undefined) => MultiaddrConnection<Uint8Array>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=socket-to-conn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-to-conn.d.ts","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"AAMA,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;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,WAAY,MAAM,+EAuG1C,CAAA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import abortable from 'abortable-iterator';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
// @ts-expect-error no types
|
|
4
|
+
import toIterable from 'stream-to-it';
|
|
5
|
+
import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr';
|
|
6
|
+
import { CLOSE_TIMEOUT } from './constants.js';
|
|
7
|
+
const log = debug('libp2p:tcp:socket');
|
|
8
|
+
/**
|
|
9
|
+
* Convert a socket into a MultiaddrConnection
|
|
10
|
+
* https://github.com/libp2p/interface-transport#multiaddrconnection
|
|
11
|
+
*/
|
|
12
|
+
export const toConnection = (socket, options) => {
|
|
13
|
+
options = options ?? {};
|
|
14
|
+
// Check if we are connected on a unix path
|
|
15
|
+
if (options.listeningAddr?.getPath() != null) {
|
|
16
|
+
options.remoteAddr = options.listeningAddr;
|
|
17
|
+
}
|
|
18
|
+
if (options.remoteAddr?.getPath() != null) {
|
|
19
|
+
options.localAddr = options.remoteAddr;
|
|
20
|
+
}
|
|
21
|
+
const { sink, source } = toIterable.duplex(socket);
|
|
22
|
+
const maConn = {
|
|
23
|
+
async sink(source) {
|
|
24
|
+
if ((options?.signal) != null) {
|
|
25
|
+
source = abortable(source, options.signal);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
await sink((async function* () {
|
|
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
|
+
})());
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
// If aborted we can safely ignore
|
|
38
|
+
if (err.type !== 'aborted') {
|
|
39
|
+
// If the source errored the socket will already have been destroyed by
|
|
40
|
+
// toIterable.duplex(). If the socket errored it will already be
|
|
41
|
+
// destroyed. There's nothing to do here except log the error & return.
|
|
42
|
+
log(err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
// Missing Type for "abortable"
|
|
47
|
+
source: (options.signal != null) ? abortable(source, options.signal) : source,
|
|
48
|
+
conn: socket,
|
|
49
|
+
localAddr: options.localAddr ?? toMultiaddr(socket.localAddress ?? '', socket.localPort ?? ''),
|
|
50
|
+
// If the remote address was passed, use it - it may have the peer ID encapsulated
|
|
51
|
+
remoteAddr: options.remoteAddr ?? toMultiaddr(socket.remoteAddress ?? '', socket.remotePort ?? ''),
|
|
52
|
+
timeline: { open: Date.now() },
|
|
53
|
+
async close() {
|
|
54
|
+
if (socket.destroyed)
|
|
55
|
+
return;
|
|
56
|
+
return await new Promise((resolve, reject) => {
|
|
57
|
+
const start = Date.now();
|
|
58
|
+
// Attempt to end the socket. If it takes longer to close than the
|
|
59
|
+
// timeout, destroy it manually.
|
|
60
|
+
const timeout = setTimeout(() => {
|
|
61
|
+
const { host, port } = maConn.remoteAddr.toOptions();
|
|
62
|
+
log('timeout closing socket to %s:%s after %dms, destroying it manually', host, port, Date.now() - start);
|
|
63
|
+
if (socket.destroyed) {
|
|
64
|
+
log('%s:%s is already destroyed', host, port);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
socket.destroy();
|
|
68
|
+
}
|
|
69
|
+
resolve();
|
|
70
|
+
}, CLOSE_TIMEOUT).unref();
|
|
71
|
+
socket.once('close', () => {
|
|
72
|
+
clearTimeout(timeout);
|
|
73
|
+
resolve();
|
|
74
|
+
});
|
|
75
|
+
socket.end((err) => {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
maConn.timeline.close = Date.now();
|
|
78
|
+
if (err != null) {
|
|
79
|
+
return reject(err);
|
|
80
|
+
}
|
|
81
|
+
resolve();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
socket.once('close', () => {
|
|
87
|
+
// In instances where `close` was not explicitly called,
|
|
88
|
+
// such as an iterable stream ending, ensure we have set the close
|
|
89
|
+
// timeline
|
|
90
|
+
if (maConn.timeline.close == null) {
|
|
91
|
+
maConn.timeline.close = Date.now();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return maConn;
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=socket-to-conn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-to-conn.js","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Multiaddr } from '@multiformats/multiaddr';
|
|
2
|
+
export declare function multiaddrToNetConfig(addr: Multiaddr): {
|
|
3
|
+
family: number;
|
|
4
|
+
host: string;
|
|
5
|
+
transport: string;
|
|
6
|
+
port: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function getMultiaddrs(proto: 'ip4' | 'ip6', ip: string, port: number): Multiaddr[];
|
|
9
|
+
export declare function isAnyAddr(ip: string): boolean;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAKnD,wBAAgB,oBAAoB,CAAE,IAAI,EAAE,SAAS;;;;;EAWpD;AAED,wBAAgB,aAAa,CAAE,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,eAG5E;AAED,wBAAgB,SAAS,CAAE,EAAE,EAAE,MAAM,WAEpC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Multiaddr } from '@multiformats/multiaddr';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
const ProtoFamily = { ip4: 'IPv4', ip6: 'IPv6' };
|
|
4
|
+
export function multiaddrToNetConfig(addr) {
|
|
5
|
+
const listenPath = addr.getPath();
|
|
6
|
+
// unix socket listening
|
|
7
|
+
if (listenPath != null) {
|
|
8
|
+
// TCP should not return unix socket else need to refactor listener which accepts connection options object
|
|
9
|
+
throw new Error('Unix Sockets are not supported by the TCP transport');
|
|
10
|
+
}
|
|
11
|
+
// tcp listening
|
|
12
|
+
return addr.toOptions();
|
|
13
|
+
}
|
|
14
|
+
export function getMultiaddrs(proto, ip, port) {
|
|
15
|
+
const toMa = (ip) => new Multiaddr(`/${proto}/${ip}/tcp/${port}`);
|
|
16
|
+
return (isAnyAddr(ip) ? getNetworkAddrs(ProtoFamily[proto]) : [ip]).map(toMa);
|
|
17
|
+
}
|
|
18
|
+
export function isAnyAddr(ip) {
|
|
19
|
+
return ['0.0.0.0', '::'].includes(ip);
|
|
20
|
+
}
|
|
21
|
+
const networks = os.networkInterfaces();
|
|
22
|
+
function getNetworkAddrs(family) {
|
|
23
|
+
const addresses = [];
|
|
24
|
+
for (const [, netAddrs] of Object.entries(networks)) {
|
|
25
|
+
if (netAddrs != null) {
|
|
26
|
+
for (const netAddr of netAddrs) {
|
|
27
|
+
if (netAddr.family === family) {
|
|
28
|
+
addresses.push(netAddr.address);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return addresses;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;AAEhD,MAAM,UAAU,oBAAoB,CAAE,IAAe;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;IAEjC,wBAAwB;IACxB,IAAI,UAAU,IAAI,IAAI,EAAE;QACtB,2GAA2G;QAC3G,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;KACvE;IAED,gBAAgB;IAChB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAE,KAAoB,EAAE,EAAU,EAAE,IAAY;IAC3E,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAA;IACzE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAC/E,CAAC;AAED,MAAM,UAAU,SAAS,CAAE,EAAU;IACnC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,QAAQ,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAA;AAEvC,SAAS,eAAe,CAAE,MAAc;IACtC,MAAM,SAAS,GAAG,EAAE,CAAA;IAEpB,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QACnD,IAAI,QAAQ,IAAI,IAAI,EAAE;YACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;gBAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;oBAC7B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;iBAChC;aACF;SACF;KACF;IAED,OAAO,SAAS,CAAA;AAClB,CAAC"}
|