Skip to content

Commit a1ec46b

Browse files
authored
feat: mark connections with limits as transient (#1890)
Some connections have resources limits imposed on them, such as circuit relay connections. If these limits are breached the connection will be closed by the remote. When this is the case, the connection will have a `.transient` boolean property set to true. By default any attempt to run a protocol over a transient connection will throw (outgoing) or be reset (incoming), this is to prevent, for example, bitswap exceeding the connection transfer limit and causing the connection to be closed by the relay server when it should be reserved for the WebRTC SDP exchange to allow incoming dials. Protocols can opt-in to being run over transient connections by specifying a `runOnTransientConnection` flag during `libp2p.handle` (incoming) and `connection.openStream`/`libp2p.dialProtocol` (outgoing). Closes #1611
1 parent 7debe03 commit a1ec46b

File tree

21 files changed

+227
-57
lines changed

21 files changed

+227
-57
lines changed

packages/interface-compliance-tests/src/mocks/connection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class MockConnection implements Connection {
4343
public status: ConnectionStatus
4444
public streams: Stream[]
4545
public tags: string[]
46+
public transient: boolean
4647

4748
private readonly muxer: StreamMuxer
4849
private readonly maConn: MultiaddrConnection
@@ -63,6 +64,7 @@ class MockConnection implements Connection {
6364
this.tags = []
6465
this.muxer = muxer
6566
this.maConn = maConn
67+
this.transient = false
6668
}
6769

6870
async newStream (protocols: string | string[], options?: AbortOptions): Promise<Stream> {

packages/interface-compliance-tests/src/mocks/upgrader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { mockConnection } from './connection.js'
22
import type { Libp2pEvents } from '@libp2p/interface'
33
import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection'
44
import type { EventEmitter } from '@libp2p/interface/events'
5+
import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport'
56
import type { Registrar } from '@libp2p/interface-internal/registrar'
6-
import type { Upgrader, UpgraderOptions } from '@libp2p/interface-internal/upgrader'
77

88
export interface MockUpgraderInit {
99
registrar?: Registrar

packages/interface-internal/src/registrar/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ export interface StreamHandlerOptions {
2020
* How many outgoing streams can be open for this protocol at the same time on each connection (default: 64)
2121
*/
2222
maxOutboundStreams?: number
23+
24+
/**
25+
* If true, allow this protocol to run on limited connections (e.g.
26+
* connections with data or duration limits such as circuit relay
27+
* connections) (default: false)
28+
*/
29+
runOnTransientConnection?: boolean
2330
}
2431

2532
export interface StreamHandlerRecord {

packages/interface-internal/src/upgrader/index.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

packages/interface/src/connection/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ export interface NewStreamOptions extends AbortOptions {
178178
* for the protocol
179179
*/
180180
maxOutboundStreams?: number
181+
182+
/**
183+
* Opt-in to running over a transient connection - one that has time/data limits
184+
* placed on it.
185+
*/
186+
runOnTransientConnection?: boolean
181187
}
182188

183189
export type ConnectionStatus = 'open' | 'closing' | 'closed'
@@ -239,6 +245,14 @@ export interface Connection {
239245
*/
240246
status: ConnectionStatus
241247

248+
/**
249+
* A transient connection is one that is not expected to be open for very long
250+
* or one that cannot transfer very much data, such as one being used as a
251+
* circuit relay connection. Protocols need to explicitly opt-in to being run
252+
* over transient connections.
253+
*/
254+
transient: boolean
255+
242256
/**
243257
* Create a new stream on this connection and negotiate one of the passed protocols
244258
*/

packages/interface/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* ```
1515
*/
1616

17-
import type { Connection, Stream } from './connection/index.js'
17+
import type { Connection, NewStreamOptions, Stream } from './connection/index.js'
1818
import type { ContentRouting } from './content-routing/index.js'
1919
import type { EventEmitter } from './events.js'
2020
import type { KeyChain } from './keychain/index.js'
@@ -503,7 +503,7 @@ export interface Libp2p<T extends ServiceMap = ServiceMap> extends Startable, Ev
503503
* pipe([1, 2, 3], stream, consume)
504504
* ```
505505
*/
506-
dialProtocol: (peer: PeerId | Multiaddr | Multiaddr[], protocols: string | string[], options?: AbortOptions) => Promise<Stream>
506+
dialProtocol: (peer: PeerId | Multiaddr | Multiaddr[], protocols: string | string[], options?: NewStreamOptions) => Promise<Stream>
507507

508508
/**
509509
* Attempts to gracefully close an open connection to the given peer. If the

packages/interface/src/stream-handler/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ export interface StreamHandlerOptions {
1919
* How many outgoing streams can be open for this protocol at the same time on each connection (default: 64)
2020
*/
2121
maxOutboundStreams?: number
22+
23+
/**
24+
* Opt-in to running over a transient connection - one that has time/data limits
25+
* placed on it.
26+
*/
27+
runOnTransientConnection?: boolean
2228
}
2329

2430
export interface StreamHandlerRecord {

packages/interface/src/transport/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ export interface UpgraderOptions {
9696
skipEncryption?: boolean
9797
skipProtection?: boolean
9898
muxerFactory?: StreamMuxerFactory
99+
100+
/**
101+
* The passed MultiaddrConnection has limits place on duration and/or data
102+
* transfer amounts so is not expected to be open for very long.
103+
*/
104+
transient?: boolean
99105
}
100106

101107
export interface Upgrader {

packages/libp2p-daemon-server/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ export class Server implements Libp2pServer {
103103
const { peer, proto } = request.streamOpen
104104
const peerId = peerIdFromBytes(peer)
105105
const connection = await this.libp2p.dial(peerId)
106-
const stream = await connection.newStream(proto)
106+
const stream = await connection.newStream(proto, {
107+
runOnTransientConnection: true
108+
})
107109

108110
return {
109111
streamInfo: {
@@ -178,6 +180,8 @@ export class Server implements Libp2pServer {
178180
})
179181
}
180182
})
183+
}, {
184+
runOnTransientConnection: true
181185
})
182186
}
183187

packages/libp2p/src/circuit-relay/server/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import { MAX_CONNECTIONS } from '../../connection-manager/constants.js'
1010
import {
1111
CIRCUIT_PROTO_CODE,
1212
DEFAULT_HOP_TIMEOUT,
13-
RELAY_SOURCE_TAG
14-
, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC
13+
RELAY_SOURCE_TAG,
14+
RELAY_V2_HOP_CODEC,
15+
RELAY_V2_STOP_CODEC
1516
} from '../constants.js'
1617
import { HopMessage, type Reservation, Status, StopMessage } from '../pb/index.js'
1718
import { createLimitedRelay } from '../utils.js'
@@ -172,7 +173,8 @@ class CircuitRelayServer extends EventEmitter<RelayServerEvents> implements Star
172173
})
173174
}, {
174175
maxInboundStreams: this.maxInboundHopStreams,
175-
maxOutboundStreams: this.maxOutboundHopStreams
176+
maxOutboundStreams: this.maxOutboundHopStreams,
177+
runOnTransientConnection: true
176178
})
177179

178180
this.reservationStore.start()
@@ -404,7 +406,8 @@ class CircuitRelayServer extends EventEmitter<RelayServerEvents> implements Star
404406
}: StopOptions): Promise<Stream | undefined> {
405407
log('starting circuit relay v2 stop request to %s', connection.remotePeer)
406408
const stream = await connection.newStream([RELAY_V2_STOP_CODEC], {
407-
maxOutboundStreams: this.maxOutboundStopStreams
409+
maxOutboundStreams: this.maxOutboundStopStreams,
410+
runOnTransientConnection: true
408411
})
409412
const pbstr = pbStream(stream)
410413
const stopstr = pbstr.pb(StopMessage)

0 commit comments

Comments
 (0)