@libp2p/tcp 9.1.5 → 9.1.6

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.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack.
5
+ *
6
+ * @example
7
+ *
8
+ * ```TypeScript
9
+ * import { createLibp2p } from 'libp2p'
10
+ * import { tcp } from '@libp2p/tcp'
11
+ * import { multiaddr } from '@multiformats/multiaddr'
12
+ *
13
+ * const node = await createLibp2p({
14
+ * transports: [
15
+ * tcp()
16
+ * ]
17
+ * })
18
+ *
19
+ * const ma = multiaddr('/ip4/123.123.123.123/tcp/1234')
20
+ *
21
+ * // dial a TCP connection, timing out after 10 seconds
22
+ * const connection = await node.dial(ma, {
23
+ * signal: AbortSignal.timeout(10_000)
24
+ * })
25
+ *
26
+ * // use connection...
27
+ * ```
28
+ */
29
+ /// <reference types="node" />
30
+ import { serviceCapabilities, transportSymbol } from '@libp2p/interface';
31
+ import type { TCPComponents, TCPCreateListenerOptions, TCPDialEvents, TCPDialOptions, TCPOptions } from './index.js';
32
+ import type { Connection, Transport, Listener } from '@libp2p/interface';
33
+ import type { Multiaddr } from '@multiformats/multiaddr';
34
+ import type { Socket } from 'net';
35
+ export declare class TCP implements Transport<TCPDialEvents> {
36
+ private readonly opts;
37
+ private readonly metrics?;
38
+ private readonly components;
39
+ private readonly log;
40
+ constructor(components: TCPComponents, options?: TCPOptions);
41
+ readonly [transportSymbol] = true;
42
+ readonly [Symbol.toStringTag] = "@libp2p/tcp";
43
+ readonly [serviceCapabilities]: string[];
44
+ dial(ma: Multiaddr, options: TCPDialOptions): Promise<Connection>;
45
+ _connect(ma: Multiaddr, options: TCPDialOptions): Promise<Socket>;
46
+ /**
47
+ * Creates a TCP listener. The provided `handler` function will be called
48
+ * anytime a new incoming Connection has been successfully upgraded via
49
+ * `upgrader.upgradeInbound`.
50
+ */
51
+ createListener(options: TCPCreateListenerOptions): Listener;
52
+ /**
53
+ * Takes a list of `Multiaddr`s and returns only valid TCP addresses
54
+ */
55
+ listenFilter(multiaddrs: Multiaddr[]): Multiaddr[];
56
+ /**
57
+ * Filter check for all Multiaddrs that this transport can dial
58
+ */
59
+ dialFilter(multiaddrs: Multiaddr[]): Multiaddr[];
60
+ }
61
+ //# sourceMappingURL=tcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcp.d.ts","sourceRoot":"","sources":["../../src/tcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;AAGH,OAAO,EAAyB,mBAAmB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAO/F,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,aAAa,EAAE,cAAc,EAAc,UAAU,EAAE,MAAM,YAAY,CAAA;AAChI,OAAO,KAAK,EAAU,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,MAAM,EAA8C,MAAM,KAAK,CAAA;AAE7E,qBAAa,GAAI,YAAW,SAAS,CAAC,aAAa,CAAC;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAY;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEf,UAAU,EAAE,aAAa,EAAE,OAAO,GAAE,UAAe;IAehE,QAAQ,CAAC,CAAC,eAAe,CAAC,QAAO;IAEjC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,iBAAgB;IAE7C,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAEvC;IAEK,IAAI,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA4ClE,QAAQ,CAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAsExE;;;;OAIG;IACH,cAAc,CAAE,OAAO,EAAE,wBAAwB,GAAG,QAAQ;IAc5D;;OAEG;IACH,YAAY,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;IAgBnD;;OAEG;IACH,UAAU,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;CAGlD"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack.
5
+ *
6
+ * @example
7
+ *
8
+ * ```TypeScript
9
+ * import { createLibp2p } from 'libp2p'
10
+ * import { tcp } from '@libp2p/tcp'
11
+ * import { multiaddr } from '@multiformats/multiaddr'
12
+ *
13
+ * const node = await createLibp2p({
14
+ * transports: [
15
+ * tcp()
16
+ * ]
17
+ * })
18
+ *
19
+ * const ma = multiaddr('/ip4/123.123.123.123/tcp/1234')
20
+ *
21
+ * // dial a TCP connection, timing out after 10 seconds
22
+ * const connection = await node.dial(ma, {
23
+ * signal: AbortSignal.timeout(10_000)
24
+ * })
25
+ *
26
+ * // use connection...
27
+ * ```
28
+ */
29
+ import net from 'net';
30
+ import { AbortError, CodeError, serviceCapabilities, transportSymbol } from '@libp2p/interface';
31
+ import * as mafmt from '@multiformats/mafmt';
32
+ import { CustomProgressEvent } from 'progress-events';
33
+ import { CODE_CIRCUIT, CODE_P2P, CODE_UNIX } from './constants.js';
34
+ import { TCPListener } from './listener.js';
35
+ import { toMultiaddrConnection } from './socket-to-conn.js';
36
+ import { multiaddrToNetConfig } from './utils.js';
37
+ export class TCP {
38
+ opts;
39
+ metrics;
40
+ components;
41
+ log;
42
+ constructor(components, options = {}) {
43
+ this.log = components.logger.forComponent('libp2p:tcp');
44
+ this.opts = options;
45
+ this.components = components;
46
+ if (components.metrics != null) {
47
+ this.metrics = {
48
+ dialerEvents: components.metrics.registerCounterGroup('libp2p_tcp_dialer_events_total', {
49
+ label: 'event',
50
+ help: 'Total count of TCP dialer events by type'
51
+ })
52
+ };
53
+ }
54
+ }
55
+ [transportSymbol] = true;
56
+ [Symbol.toStringTag] = '@libp2p/tcp';
57
+ [serviceCapabilities] = [
58
+ '@libp2p/transport'
59
+ ];
60
+ async dial(ma, options) {
61
+ options.keepAlive = options.keepAlive ?? true;
62
+ options.noDelay = options.noDelay ?? true;
63
+ // options.signal destroys the socket before 'connect' event
64
+ const socket = await this._connect(ma, options);
65
+ // Avoid uncaught errors caused by unstable connections
66
+ socket.on('error', err => {
67
+ this.log('socket error', err);
68
+ });
69
+ const maConn = toMultiaddrConnection(socket, {
70
+ remoteAddr: ma,
71
+ socketInactivityTimeout: this.opts.outboundSocketInactivityTimeout,
72
+ socketCloseTimeout: this.opts.socketCloseTimeout,
73
+ metrics: this.metrics?.dialerEvents,
74
+ logger: this.components.logger
75
+ });
76
+ const onAbort = () => {
77
+ maConn.close().catch(err => {
78
+ this.log.error('Error closing maConn after abort', err);
79
+ });
80
+ };
81
+ options.signal?.addEventListener('abort', onAbort, { once: true });
82
+ this.log('new outbound connection %s', maConn.remoteAddr);
83
+ const conn = await options.upgrader.upgradeOutbound(maConn);
84
+ this.log('outbound connection %s upgraded', maConn.remoteAddr);
85
+ options.signal?.removeEventListener('abort', onAbort);
86
+ if (options.signal?.aborted === true) {
87
+ conn.close().catch(err => {
88
+ this.log.error('Error closing conn after abort', err);
89
+ });
90
+ throw new AbortError();
91
+ }
92
+ return conn;
93
+ }
94
+ async _connect(ma, options) {
95
+ options.signal?.throwIfAborted();
96
+ options.onProgress?.(new CustomProgressEvent('tcp:open-connection'));
97
+ return new Promise((resolve, reject) => {
98
+ const start = Date.now();
99
+ const cOpts = multiaddrToNetConfig(ma, {
100
+ ...(this.opts.dialOpts ?? {}),
101
+ ...options
102
+ });
103
+ this.log('dialing %a', ma);
104
+ const rawSocket = net.connect(cOpts);
105
+ const onError = (err) => {
106
+ const cOptsStr = cOpts.path ?? `${cOpts.host ?? ''}:${cOpts.port}`;
107
+ err.message = `connection error ${cOptsStr}: ${err.message}`;
108
+ this.metrics?.dialerEvents.increment({ error: true });
109
+ done(err);
110
+ };
111
+ const onTimeout = () => {
112
+ this.log('connection timeout %a', ma);
113
+ this.metrics?.dialerEvents.increment({ timeout: true });
114
+ const err = new CodeError(`connection timeout after ${Date.now() - start}ms`, 'ERR_CONNECT_TIMEOUT');
115
+ // Note: this will result in onError() being called
116
+ rawSocket.emit('error', err);
117
+ };
118
+ const onConnect = () => {
119
+ this.log('connection opened %a', ma);
120
+ this.metrics?.dialerEvents.increment({ connect: true });
121
+ done();
122
+ };
123
+ const onAbort = () => {
124
+ this.log('connection aborted %a', ma);
125
+ this.metrics?.dialerEvents.increment({ abort: true });
126
+ rawSocket.destroy();
127
+ done(new AbortError());
128
+ };
129
+ const done = (err) => {
130
+ rawSocket.removeListener('error', onError);
131
+ rawSocket.removeListener('timeout', onTimeout);
132
+ rawSocket.removeListener('connect', onConnect);
133
+ if (options.signal != null) {
134
+ options.signal.removeEventListener('abort', onAbort);
135
+ }
136
+ if (err != null) {
137
+ reject(err);
138
+ return;
139
+ }
140
+ resolve(rawSocket);
141
+ };
142
+ rawSocket.on('error', onError);
143
+ rawSocket.on('timeout', onTimeout);
144
+ rawSocket.on('connect', onConnect);
145
+ if (options.signal != null) {
146
+ options.signal.addEventListener('abort', onAbort);
147
+ }
148
+ });
149
+ }
150
+ /**
151
+ * Creates a TCP listener. The provided `handler` function will be called
152
+ * anytime a new incoming Connection has been successfully upgraded via
153
+ * `upgrader.upgradeInbound`.
154
+ */
155
+ createListener(options) {
156
+ return new TCPListener({
157
+ ...(this.opts.listenOpts ?? {}),
158
+ ...options,
159
+ maxConnections: this.opts.maxConnections,
160
+ backlog: this.opts.backlog,
161
+ closeServerOnMaxConnections: this.opts.closeServerOnMaxConnections,
162
+ socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
163
+ socketCloseTimeout: this.opts.socketCloseTimeout,
164
+ metrics: this.components.metrics,
165
+ logger: this.components.logger
166
+ });
167
+ }
168
+ /**
169
+ * Takes a list of `Multiaddr`s and returns only valid TCP addresses
170
+ */
171
+ listenFilter(multiaddrs) {
172
+ multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs];
173
+ return multiaddrs.filter(ma => {
174
+ if (ma.protoCodes().includes(CODE_CIRCUIT)) {
175
+ return false;
176
+ }
177
+ if (ma.protoCodes().includes(CODE_UNIX)) {
178
+ return true;
179
+ }
180
+ return mafmt.TCP.matches(ma.decapsulateCode(CODE_P2P));
181
+ });
182
+ }
183
+ /**
184
+ * Filter check for all Multiaddrs that this transport can dial
185
+ */
186
+ dialFilter(multiaddrs) {
187
+ return this.listenFilter(multiaddrs);
188
+ }
189
+ }
190
+ //# sourceMappingURL=tcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../src/tcp.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/tcp",
3
- "version": "9.1.5",
3
+ "version": "9.1.6",
4
4
  "description": "A TCP transport for libp2p",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-tcp#readme",
@@ -52,6 +52,10 @@
52
52
  "doc-check": "aegir doc-check",
53
53
  "build": "aegir build",
54
54
  "test": "aegir test -t node -t electron-main",
55
+ "test:chrome": "aegir test -t browser -f ./dist/test/browser.js --cov",
56
+ "test:chrome-webworker": "aegir test -t webworker -f ./dist/test/browser.js",
57
+ "test:firefox": "aegir test -t browser -f ./dist/test/browser.js -- --browser firefox",
58
+ "test:firefox-webworker": "aegir test -t webworker -f ./dist/test/browser.js -- --browser firefox",
55
59
  "test:node": "aegir test -t node --cov",
56
60
  "test:electron-main": "aegir test -t electron-main"
57
61
  },
@@ -72,7 +76,11 @@
72
76
  "it-pipe": "^3.0.1",
73
77
  "p-defer": "^4.0.1",
74
78
  "sinon": "^18.0.0",
75
- "uint8arrays": "^5.1.0"
79
+ "uint8arrays": "^5.1.0",
80
+ "wherearewe": "^2.0.1"
81
+ },
82
+ "browser": {
83
+ "./dist/src/tcp.js": "./dist/src/tcp.browser.js"
76
84
  },
77
85
  "sideEffects": false
78
86
  }
package/src/index.ts CHANGED
@@ -27,17 +27,10 @@
27
27
  * ```
28
28
  */
29
29
 
30
- import net from 'net'
31
- import { AbortError, CodeError, serviceCapabilities, transportSymbol } from '@libp2p/interface'
32
- import * as mafmt from '@multiformats/mafmt'
33
- import { CustomProgressEvent } from 'progress-events'
34
- import { CODE_CIRCUIT, CODE_P2P, CODE_UNIX } from './constants.js'
35
- import { type CloseServerOnMaxConnectionsOpts, TCPListener } from './listener.js'
36
- import { toMultiaddrConnection } from './socket-to-conn.js'
37
- import { multiaddrToNetConfig } from './utils.js'
38
- import type { ComponentLogger, Logger, Connection, CounterGroup, Metrics, CreateListenerOptions, DialTransportOptions, Transport, Listener, OutboundConnectionUpgradeEvents } from '@libp2p/interface'
39
- import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
40
- import type { Socket, IpcSocketConnectOpts, TcpSocketConnectOpts } from 'net'
30
+ import { TCP } from './tcp.js'
31
+ import type { CloseServerOnMaxConnectionsOpts } from './listener.js'
32
+ import type { ComponentLogger, CounterGroup, Metrics, CreateListenerOptions, DialTransportOptions, Transport, OutboundConnectionUpgradeEvents } from '@libp2p/interface'
33
+ import type { AbortOptions } from '@multiformats/multiaddr'
41
34
  import type { ProgressEvent } from 'progress-events'
42
35
 
43
36
  export interface TCPOptions {
@@ -131,195 +124,6 @@ export interface TCPMetrics {
131
124
  dialerEvents: CounterGroup
132
125
  }
133
126
 
134
- class TCP implements Transport<TCPDialEvents> {
135
- private readonly opts: TCPOptions
136
- private readonly metrics?: TCPMetrics
137
- private readonly components: TCPComponents
138
- private readonly log: Logger
139
-
140
- constructor (components: TCPComponents, options: TCPOptions = {}) {
141
- this.log = components.logger.forComponent('libp2p:tcp')
142
- this.opts = options
143
- this.components = components
144
-
145
- if (components.metrics != null) {
146
- this.metrics = {
147
- dialerEvents: components.metrics.registerCounterGroup('libp2p_tcp_dialer_events_total', {
148
- label: 'event',
149
- help: 'Total count of TCP dialer events by type'
150
- })
151
- }
152
- }
153
- }
154
-
155
- readonly [transportSymbol] = true
156
-
157
- readonly [Symbol.toStringTag] = '@libp2p/tcp'
158
-
159
- readonly [serviceCapabilities]: string[] = [
160
- '@libp2p/transport'
161
- ]
162
-
163
- async dial (ma: Multiaddr, options: TCPDialOptions): Promise<Connection> {
164
- options.keepAlive = options.keepAlive ?? true
165
- options.noDelay = options.noDelay ?? true
166
-
167
- // options.signal destroys the socket before 'connect' event
168
- const socket = await this._connect(ma, options)
169
-
170
- // Avoid uncaught errors caused by unstable connections
171
- socket.on('error', err => {
172
- this.log('socket error', err)
173
- })
174
-
175
- const maConn = toMultiaddrConnection(socket, {
176
- remoteAddr: ma,
177
- socketInactivityTimeout: this.opts.outboundSocketInactivityTimeout,
178
- socketCloseTimeout: this.opts.socketCloseTimeout,
179
- metrics: this.metrics?.dialerEvents,
180
- logger: this.components.logger
181
- })
182
-
183
- const onAbort = (): void => {
184
- maConn.close().catch(err => {
185
- this.log.error('Error closing maConn after abort', err)
186
- })
187
- }
188
- options.signal?.addEventListener('abort', onAbort, { once: true })
189
-
190
- this.log('new outbound connection %s', maConn.remoteAddr)
191
- const conn = await options.upgrader.upgradeOutbound(maConn)
192
- this.log('outbound connection %s upgraded', maConn.remoteAddr)
193
-
194
- options.signal?.removeEventListener('abort', onAbort)
195
-
196
- if (options.signal?.aborted === true) {
197
- conn.close().catch(err => {
198
- this.log.error('Error closing conn after abort', err)
199
- })
200
-
201
- throw new AbortError()
202
- }
203
-
204
- return conn
205
- }
206
-
207
- async _connect (ma: Multiaddr, options: TCPDialOptions): Promise<Socket> {
208
- options.signal?.throwIfAborted()
209
- options.onProgress?.(new CustomProgressEvent('tcp:open-connection'))
210
-
211
- return new Promise<Socket>((resolve, reject) => {
212
- const start = Date.now()
213
- const cOpts = multiaddrToNetConfig(ma, {
214
- ...(this.opts.dialOpts ?? {}),
215
- ...options
216
- }) as (IpcSocketConnectOpts & TcpSocketConnectOpts)
217
-
218
- this.log('dialing %a', ma)
219
- const rawSocket = net.connect(cOpts)
220
-
221
- const onError = (err: Error): void => {
222
- const cOptsStr = cOpts.path ?? `${cOpts.host ?? ''}:${cOpts.port}`
223
- err.message = `connection error ${cOptsStr}: ${err.message}`
224
- this.metrics?.dialerEvents.increment({ error: true })
225
-
226
- done(err)
227
- }
228
-
229
- const onTimeout = (): void => {
230
- this.log('connection timeout %a', ma)
231
- this.metrics?.dialerEvents.increment({ timeout: true })
232
-
233
- const err = new CodeError(`connection timeout after ${Date.now() - start}ms`, 'ERR_CONNECT_TIMEOUT')
234
- // Note: this will result in onError() being called
235
- rawSocket.emit('error', err)
236
- }
237
-
238
- const onConnect = (): void => {
239
- this.log('connection opened %a', ma)
240
- this.metrics?.dialerEvents.increment({ connect: true })
241
- done()
242
- }
243
-
244
- const onAbort = (): void => {
245
- this.log('connection aborted %a', ma)
246
- this.metrics?.dialerEvents.increment({ abort: true })
247
- rawSocket.destroy()
248
- done(new AbortError())
249
- }
250
-
251
- const done = (err?: Error): void => {
252
- rawSocket.removeListener('error', onError)
253
- rawSocket.removeListener('timeout', onTimeout)
254
- rawSocket.removeListener('connect', onConnect)
255
-
256
- if (options.signal != null) {
257
- options.signal.removeEventListener('abort', onAbort)
258
- }
259
-
260
- if (err != null) {
261
- reject(err); return
262
- }
263
-
264
- resolve(rawSocket)
265
- }
266
-
267
- rawSocket.on('error', onError)
268
- rawSocket.on('timeout', onTimeout)
269
- rawSocket.on('connect', onConnect)
270
-
271
- if (options.signal != null) {
272
- options.signal.addEventListener('abort', onAbort)
273
- }
274
- })
275
- }
276
-
277
- /**
278
- * Creates a TCP listener. The provided `handler` function will be called
279
- * anytime a new incoming Connection has been successfully upgraded via
280
- * `upgrader.upgradeInbound`.
281
- */
282
- createListener (options: TCPCreateListenerOptions): Listener {
283
- return new TCPListener({
284
- ...(this.opts.listenOpts ?? {}),
285
- ...options,
286
- maxConnections: this.opts.maxConnections,
287
- backlog: this.opts.backlog,
288
- closeServerOnMaxConnections: this.opts.closeServerOnMaxConnections,
289
- socketInactivityTimeout: this.opts.inboundSocketInactivityTimeout,
290
- socketCloseTimeout: this.opts.socketCloseTimeout,
291
- metrics: this.components.metrics,
292
- logger: this.components.logger
293
- })
294
- }
295
-
296
- /**
297
- * Takes a list of `Multiaddr`s and returns only valid TCP addresses
298
- */
299
- listenFilter (multiaddrs: Multiaddr[]): Multiaddr[] {
300
- multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
301
-
302
- return multiaddrs.filter(ma => {
303
- if (ma.protoCodes().includes(CODE_CIRCUIT)) {
304
- return false
305
- }
306
-
307
- if (ma.protoCodes().includes(CODE_UNIX)) {
308
- return true
309
- }
310
-
311
- return mafmt.TCP.matches(ma.decapsulateCode(CODE_P2P))
312
- })
313
- }
314
-
315
- /**
316
- * Filter check for all Multiaddrs that this transport can dial
317
- */
318
- dialFilter (multiaddrs: Multiaddr[]): Multiaddr[] {
319
- return this.listenFilter(multiaddrs)
320
- }
321
- }
322
-
323
127
  export function tcp (init: TCPOptions = {}): (components: TCPComponents) => Transport {
324
128
  return (components: TCPComponents) => {
325
129
  return new TCP(components, init)
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * A [libp2p transport](https://docs.libp2p.io/concepts/transports/overview/) based on the TCP networking stack.
5
+ *
6
+ * @example
7
+ *
8
+ * ```TypeScript
9
+ * import { createLibp2p } from 'libp2p'
10
+ * import { tcp } from '@libp2p/tcp'
11
+ * import { multiaddr } from '@multiformats/multiaddr'
12
+ *
13
+ * const node = await createLibp2p({
14
+ * transports: [
15
+ * tcp()
16
+ * ]
17
+ * })
18
+ *
19
+ * const ma = multiaddr('/ip4/123.123.123.123/tcp/1234')
20
+ *
21
+ * // dial a TCP connection, timing out after 10 seconds
22
+ * const connection = await node.dial(ma, {
23
+ * signal: AbortSignal.timeout(10_000)
24
+ * })
25
+ *
26
+ * // use connection...
27
+ * ```
28
+ */
29
+
30
+ import { serviceCapabilities, transportSymbol } from '@libp2p/interface'
31
+ import type { TCPComponents, TCPDialEvents, TCPMetrics, TCPOptions } from './index.js'
32
+ import type { Logger, Connection, Transport, Listener } from '@libp2p/interface'
33
+ import type { Multiaddr } from '@multiformats/multiaddr'
34
+
35
+ export class TCP implements Transport<TCPDialEvents> {
36
+ private readonly opts: TCPOptions
37
+ private readonly metrics?: TCPMetrics
38
+ private readonly components: TCPComponents
39
+ private readonly log: Logger
40
+
41
+ constructor () {
42
+ throw new Error('TCP connections are not possible in browsers')
43
+ }
44
+
45
+ readonly [transportSymbol] = true
46
+
47
+ readonly [Symbol.toStringTag] = '@libp2p/tcp'
48
+
49
+ readonly [serviceCapabilities]: string[] = [
50
+ '@libp2p/transport'
51
+ ]
52
+
53
+ async dial (): Promise<Connection> {
54
+ throw new Error('TCP connections are not possible in browsers')
55
+ }
56
+
57
+ createListener (): Listener {
58
+ throw new Error('TCP connections are not possible in browsers')
59
+ }
60
+
61
+ listenFilter (): Multiaddr[] {
62
+ return []
63
+ }
64
+
65
+ dialFilter (): Multiaddr[] {
66
+ return []
67
+ }
68
+ }