@libp2p/interface-compliance-tests 6.1.7 → 6.1.8-32ca76fcb
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/matchers.d.ts +6 -0
- package/dist/src/matchers.d.ts.map +1 -1
- package/dist/src/matchers.js +6 -0
- package/dist/src/matchers.js.map +1 -1
- package/dist/src/mocks/muxer.d.ts +8 -3
- package/dist/src/mocks/muxer.d.ts.map +1 -1
- package/dist/src/mocks/muxer.js +15 -6
- package/dist/src/mocks/muxer.js.map +1 -1
- package/dist/src/transport/index.d.ts +13 -9
- package/dist/src/transport/index.d.ts.map +1 -1
- package/dist/src/transport/index.js +321 -6
- package/dist/src/transport/index.js.map +1 -1
- package/dist/src/transport/utils.d.ts +19 -0
- package/dist/src/transport/utils.d.ts.map +1 -0
- package/dist/src/transport/utils.js +62 -0
- package/dist/src/transport/utils.js.map +1 -0
- package/package.json +14 -13
- package/src/matchers.ts +6 -0
- package/src/mocks/muxer.ts +24 -10
- package/src/transport/index.ts +405 -17
- package/src/transport/utils.ts +76 -0
- package/dist/src/connection/index.d.ts +0 -5
- package/dist/src/connection/index.d.ts.map +0 -1
- package/dist/src/connection/index.js +0 -135
- package/dist/src/connection/index.js.map +0 -1
- package/dist/src/transport/dial-test.d.ts +0 -5
- package/dist/src/transport/dial-test.d.ts.map +0 -1
- package/dist/src/transport/dial-test.js +0 -99
- package/dist/src/transport/dial-test.js.map +0 -1
- package/dist/src/transport/filter-test.d.ts +0 -5
- package/dist/src/transport/filter-test.d.ts.map +0 -1
- package/dist/src/transport/filter-test.js +0 -24
- package/dist/src/transport/filter-test.js.map +0 -1
- package/dist/src/transport/listen-test.d.ts +0 -5
- package/dist/src/transport/listen-test.d.ts.map +0 -1
- package/dist/src/transport/listen-test.js +0 -154
- package/dist/src/transport/listen-test.js.map +0 -1
- package/dist/typedoc-urls.json +0 -49
- package/src/connection/index.ts +0 -166
- package/src/transport/dial-test.ts +0 -125
- package/src/transport/filter-test.ts +0 -32
- package/src/transport/listen-test.ts +0 -192
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/interface-compliance-tests",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.8-32ca76fcb",
|
|
4
4
|
"description": "Compliance tests for JS libp2p interfaces",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/interface-compliance-tests#readme",
|
|
@@ -48,10 +48,6 @@
|
|
|
48
48
|
"types": "./dist/src/index.d.ts",
|
|
49
49
|
"import": "./dist/src/index.js"
|
|
50
50
|
},
|
|
51
|
-
"./connection": {
|
|
52
|
-
"types": "./dist/src/connection/index.d.ts",
|
|
53
|
-
"import": "./dist/src/connection/index.js"
|
|
54
|
-
},
|
|
55
51
|
"./connection-encryption": {
|
|
56
52
|
"types": "./dist/src/connection-encryption/index.d.ts",
|
|
57
53
|
"import": "./dist/src/connection-encryption/index.js"
|
|
@@ -108,14 +104,17 @@
|
|
|
108
104
|
"test:electron-main": "aegir test -t electron-main"
|
|
109
105
|
},
|
|
110
106
|
"dependencies": {
|
|
111
|
-
"@libp2p/crypto": "
|
|
112
|
-
"@libp2p/
|
|
113
|
-
"@libp2p/interface
|
|
114
|
-
"@libp2p/
|
|
115
|
-
"@libp2p/
|
|
116
|
-
"@libp2p/
|
|
117
|
-
"@libp2p/
|
|
118
|
-
"@libp2p/
|
|
107
|
+
"@libp2p/crypto": "5.0.6-32ca76fcb",
|
|
108
|
+
"@libp2p/echo": "2.1.1-32ca76fcb",
|
|
109
|
+
"@libp2p/interface": "2.2.0-32ca76fcb",
|
|
110
|
+
"@libp2p/interface-internal": "2.0.10-32ca76fcb",
|
|
111
|
+
"@libp2p/logger": "5.1.3-32ca76fcb",
|
|
112
|
+
"@libp2p/memory": "0.0.0-32ca76fcb",
|
|
113
|
+
"@libp2p/multistream-select": "6.0.8-32ca76fcb",
|
|
114
|
+
"@libp2p/peer-collections": "6.0.10-32ca76fcb",
|
|
115
|
+
"@libp2p/peer-id": "5.0.7-32ca76fcb",
|
|
116
|
+
"@libp2p/plaintext": "2.0.10-32ca76fcb",
|
|
117
|
+
"@libp2p/utils": "6.1.3-32ca76fcb",
|
|
119
118
|
"@multiformats/multiaddr": "^12.2.3",
|
|
120
119
|
"abortable-iterator": "^5.0.1",
|
|
121
120
|
"aegir": "^44.0.1",
|
|
@@ -131,12 +130,14 @@
|
|
|
131
130
|
"it-pushable": "^3.2.3",
|
|
132
131
|
"it-stream-types": "^2.0.1",
|
|
133
132
|
"it-to-buffer": "^4.0.7",
|
|
133
|
+
"libp2p": "2.2.1-32ca76fcb",
|
|
134
134
|
"merge-options": "^3.0.4",
|
|
135
135
|
"p-defer": "^4.0.1",
|
|
136
136
|
"p-event": "^6.0.1",
|
|
137
137
|
"p-limit": "^6.0.0",
|
|
138
138
|
"p-wait-for": "^5.0.2",
|
|
139
139
|
"protons-runtime": "^5.4.0",
|
|
140
|
+
"race-signal": "^1.1.0",
|
|
140
141
|
"sinon": "^18.0.0",
|
|
141
142
|
"tdigest": "^0.1.2",
|
|
142
143
|
"uint8arraylist": "^2.4.8",
|
package/src/matchers.ts
CHANGED
|
@@ -2,10 +2,16 @@ import Sinon from 'sinon'
|
|
|
2
2
|
import type { PeerId } from '@libp2p/interface'
|
|
3
3
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated PeerIds can be passed to sinon matchers directly
|
|
7
|
+
*/
|
|
5
8
|
export function matchPeerId (peerId: PeerId): Sinon.SinonMatcher {
|
|
6
9
|
return Sinon.match(p => p.toString() === peerId.toString())
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Multiaddrs can be passed to sinon matchers directly
|
|
14
|
+
*/
|
|
9
15
|
export function matchMultiaddr (ma: Multiaddr): Sinon.SinonMatcher {
|
|
10
16
|
return Sinon.match(m => m.toString() === ma.toString())
|
|
11
17
|
}
|
package/src/mocks/muxer.ts
CHANGED
|
@@ -27,9 +27,15 @@ interface ResetMessage {
|
|
|
27
27
|
direction: Direction
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
interface
|
|
30
|
+
interface CloseWriteMessage {
|
|
31
31
|
id: string
|
|
32
|
-
type: '
|
|
32
|
+
type: 'closeWrite'
|
|
33
|
+
direction: Direction
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface CloseReadMessage {
|
|
37
|
+
id: string
|
|
38
|
+
type: 'closeRead'
|
|
33
39
|
direction: Direction
|
|
34
40
|
}
|
|
35
41
|
|
|
@@ -39,7 +45,7 @@ interface CreateMessage {
|
|
|
39
45
|
direction: 'outbound'
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
type StreamMessage = DataMessage | ResetMessage |
|
|
48
|
+
type StreamMessage = DataMessage | ResetMessage | CloseWriteMessage | CloseReadMessage | CreateMessage
|
|
43
49
|
|
|
44
50
|
export interface MockMuxedStreamInit extends AbstractStreamInit {
|
|
45
51
|
push: Pushable<StreamMessage>
|
|
@@ -84,16 +90,21 @@ class MuxedStream extends AbstractStream {
|
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
sendCloseWrite (): void {
|
|
87
|
-
const closeMsg:
|
|
93
|
+
const closeMsg: CloseWriteMessage = {
|
|
88
94
|
id: this.id,
|
|
89
|
-
type: '
|
|
95
|
+
type: 'closeWrite',
|
|
90
96
|
direction: this.direction
|
|
91
97
|
}
|
|
92
98
|
this.push.push(closeMsg)
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
sendCloseRead (): void {
|
|
96
|
-
|
|
102
|
+
const closeMsg: CloseReadMessage = {
|
|
103
|
+
id: this.id,
|
|
104
|
+
type: 'closeRead',
|
|
105
|
+
direction: this.direction
|
|
106
|
+
}
|
|
107
|
+
this.push.push(closeMsg)
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
|
|
@@ -153,10 +164,10 @@ class MockMuxer implements StreamMuxer {
|
|
|
153
164
|
}
|
|
154
165
|
)
|
|
155
166
|
|
|
156
|
-
this.log('
|
|
167
|
+
this.log('muxer ended')
|
|
157
168
|
this.input.end()
|
|
158
169
|
} catch (err: any) {
|
|
159
|
-
this.log('
|
|
170
|
+
this.log.error('muxer errored - %e', err)
|
|
160
171
|
this.input.end(err)
|
|
161
172
|
}
|
|
162
173
|
}
|
|
@@ -192,9 +203,12 @@ class MockMuxer implements StreamMuxer {
|
|
|
192
203
|
} else if (message.type === 'reset') {
|
|
193
204
|
this.log('-> reset stream %s %s', muxedStream.direction, muxedStream.id)
|
|
194
205
|
muxedStream.reset()
|
|
195
|
-
} else if (message.type === '
|
|
196
|
-
this.log('-> closing stream %s %s', muxedStream.direction, muxedStream.id)
|
|
206
|
+
} else if (message.type === 'closeWrite') {
|
|
207
|
+
this.log('-> closing writeable end of stream %s %s', muxedStream.direction, muxedStream.id)
|
|
197
208
|
muxedStream.remoteCloseWrite()
|
|
209
|
+
} else if (message.type === 'closeRead') {
|
|
210
|
+
this.log('-> closing readable end of stream %s %s', muxedStream.direction, muxedStream.id)
|
|
211
|
+
muxedStream.remoteCloseRead()
|
|
198
212
|
}
|
|
199
213
|
}
|
|
200
214
|
|
package/src/transport/index.ts
CHANGED
|
@@ -1,27 +1,415 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { echo } from '@libp2p/echo'
|
|
2
|
+
import { stop } from '@libp2p/interface'
|
|
3
|
+
import { expect } from 'aegir/chai'
|
|
4
|
+
import delay from 'delay'
|
|
5
|
+
import { pEvent } from 'p-event'
|
|
6
|
+
import pWaitFor from 'p-wait-for'
|
|
7
|
+
import { raceSignal } from 'race-signal'
|
|
8
|
+
import { isValidTick } from '../is-valid-tick.js'
|
|
9
|
+
import { createPeer, getTransportManager, getUpgrader, slowNetwork } from './utils.js'
|
|
4
10
|
import type { TestSetup } from '../index.js'
|
|
5
|
-
import type {
|
|
11
|
+
import type { Echo } from '@libp2p/echo'
|
|
12
|
+
import type { Connection, Libp2p, Stream, Transport } from '@libp2p/interface'
|
|
6
13
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
7
14
|
|
|
8
|
-
export interface Connector {
|
|
9
|
-
delay(ms: number): void
|
|
10
|
-
restore(): void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
15
|
export interface TransportTestFixtures {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Addresses that will be used to dial listeners from `listenAddrs`
|
|
18
|
+
*/
|
|
19
|
+
dialAddrs: [Multiaddr, Multiaddr]
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Addresses that will be used to create listeners to dial
|
|
23
|
+
*/
|
|
24
|
+
listenAddrs?: [Multiaddr, Multiaddr]
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Only run the dial portion of the tests, do not try to create listeners
|
|
28
|
+
*/
|
|
29
|
+
dialOnly?: boolean
|
|
30
|
+
|
|
31
|
+
transport(components: any): Transport
|
|
19
32
|
}
|
|
20
33
|
|
|
21
34
|
export default (common: TestSetup<TransportTestFixtures>): void => {
|
|
22
35
|
describe('interface-transport', () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
let dialAddrs: Multiaddr[]
|
|
37
|
+
let listenAddrs: Multiaddr[]
|
|
38
|
+
let transport: (components: any) => Transport
|
|
39
|
+
let dialer: Libp2p<{ echo: Echo }>
|
|
40
|
+
let listener: Libp2p<{ echo: Echo }> | undefined
|
|
41
|
+
let dialOnly: boolean
|
|
42
|
+
|
|
43
|
+
beforeEach(async () => {
|
|
44
|
+
({ dialAddrs, listenAddrs = dialAddrs, transport, dialOnly = false } = await common.setup())
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
afterEach(async () => {
|
|
48
|
+
await stop(dialer, listener)
|
|
49
|
+
await common.teardown()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('simple', async () => {
|
|
53
|
+
dialer = await createPeer({
|
|
54
|
+
transports: [
|
|
55
|
+
transport
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
if (!dialOnly) {
|
|
60
|
+
listener = await createPeer({
|
|
61
|
+
addresses: {
|
|
62
|
+
listen: [listenAddrs[0].toString()]
|
|
63
|
+
},
|
|
64
|
+
transports: [
|
|
65
|
+
transport
|
|
66
|
+
]
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const input = Uint8Array.from([0, 1, 2, 3, 4])
|
|
71
|
+
const output = await dialer.services.echo.echo(dialAddrs[0], input, {
|
|
72
|
+
signal: AbortSignal.timeout(5000)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
expect(output).to.equalBytes(input)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('should listen on multiple addresses', async () => {
|
|
79
|
+
dialer = await createPeer({
|
|
80
|
+
transports: [
|
|
81
|
+
transport
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
if (!dialOnly) {
|
|
86
|
+
listener = await createPeer({
|
|
87
|
+
addresses: {
|
|
88
|
+
listen: [
|
|
89
|
+
listenAddrs[0].toString(),
|
|
90
|
+
listenAddrs[1].toString()
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
transports: [
|
|
94
|
+
transport
|
|
95
|
+
]
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const input = Uint8Array.from([0, 1, 2, 3, 4])
|
|
100
|
+
|
|
101
|
+
await expect(dialer.services.echo.echo(dialAddrs[0], input, {
|
|
102
|
+
signal: AbortSignal.timeout(5000)
|
|
103
|
+
})).to.eventually.deep.equal(input)
|
|
104
|
+
|
|
105
|
+
await expect(dialer.services.echo.echo(dialAddrs[1], input, {
|
|
106
|
+
signal: AbortSignal.timeout(5000)
|
|
107
|
+
})).to.eventually.deep.equal(input)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('can close connections', async () => {
|
|
111
|
+
dialer = await createPeer({
|
|
112
|
+
transports: [
|
|
113
|
+
transport
|
|
114
|
+
]
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if (!dialOnly) {
|
|
118
|
+
listener = await createPeer({
|
|
119
|
+
addresses: {
|
|
120
|
+
listen: [listenAddrs[0].toString()]
|
|
121
|
+
},
|
|
122
|
+
transports: [
|
|
123
|
+
transport
|
|
124
|
+
]
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const conn = await dialer.dial(dialAddrs[0], {
|
|
129
|
+
signal: AbortSignal.timeout(5000)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
await conn.close()
|
|
133
|
+
expect(isValidTick(conn.timeline.close)).to.equal(true)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('abort before dialing throws AbortError', async () => {
|
|
137
|
+
dialer = await createPeer({
|
|
138
|
+
transports: [
|
|
139
|
+
transport
|
|
140
|
+
]
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
if (!dialOnly) {
|
|
144
|
+
listener = await createPeer({
|
|
145
|
+
addresses: {
|
|
146
|
+
listen: [listenAddrs[0].toString()]
|
|
147
|
+
},
|
|
148
|
+
transports: [
|
|
149
|
+
transport
|
|
150
|
+
]
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const controller = new AbortController()
|
|
155
|
+
controller.abort()
|
|
156
|
+
|
|
157
|
+
await expect(dialer.dial(dialAddrs[0], {
|
|
158
|
+
signal: controller.signal
|
|
159
|
+
})).to.eventually.be.rejected()
|
|
160
|
+
.with.property('name', 'AbortError')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('abort while dialing throws AbortError', async () => {
|
|
164
|
+
dialer = await createPeer({
|
|
165
|
+
transports: [
|
|
166
|
+
transport
|
|
167
|
+
]
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
if (!dialOnly) {
|
|
171
|
+
listener = await createPeer({
|
|
172
|
+
addresses: {
|
|
173
|
+
listen: [listenAddrs[0].toString()]
|
|
174
|
+
},
|
|
175
|
+
transports: [
|
|
176
|
+
transport
|
|
177
|
+
]
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
slowNetwork(dialer, 100)
|
|
181
|
+
|
|
182
|
+
const controller = new AbortController()
|
|
183
|
+
setTimeout(() => { controller.abort() }, 50)
|
|
184
|
+
|
|
185
|
+
await expect(dialer.dial(dialAddrs[0], {
|
|
186
|
+
signal: controller.signal
|
|
187
|
+
})).to.eventually.be.rejected()
|
|
188
|
+
.with.property('name', 'AbortError')
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('should close all streams when the connection closes', async () => {
|
|
192
|
+
dialer = await createPeer({
|
|
193
|
+
transports: [
|
|
194
|
+
transport
|
|
195
|
+
]
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
if (!dialOnly) {
|
|
199
|
+
listener = await createPeer({
|
|
200
|
+
addresses: {
|
|
201
|
+
listen: [listenAddrs[0].toString()]
|
|
202
|
+
},
|
|
203
|
+
transports: [
|
|
204
|
+
transport
|
|
205
|
+
],
|
|
206
|
+
services: {
|
|
207
|
+
echo: echo({
|
|
208
|
+
maxInboundStreams: 5
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const connection = await dialer.dial(listenAddrs[0])
|
|
215
|
+
let remoteConn: Connection | undefined
|
|
216
|
+
|
|
217
|
+
if (listener != null) {
|
|
218
|
+
const remoteConnections = listener.getConnections(dialer.peerId)
|
|
219
|
+
expect(remoteConnections).to.have.lengthOf(1)
|
|
220
|
+
remoteConn = remoteConnections[0]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const streams: Stream[] = []
|
|
224
|
+
|
|
225
|
+
for (let i = 0; i < 5; i++) {
|
|
226
|
+
streams.push(await connection.newStream('/echo/1.0.0', {
|
|
227
|
+
maxOutboundStreams: 5
|
|
228
|
+
}))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Close the connection and verify all streams have been closed
|
|
232
|
+
await connection.close()
|
|
233
|
+
await pWaitFor(() => connection.streams.length === 0)
|
|
234
|
+
|
|
235
|
+
if (remoteConn != null) {
|
|
236
|
+
await pWaitFor(() => remoteConn.streams.length === 0)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
expect(streams.find(stream => stream.status !== 'closed')).to.be.undefined()
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('should not handle connection if upgradeInbound rejects', async function () {
|
|
243
|
+
if (dialOnly) {
|
|
244
|
+
return this.skip()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
dialer = await createPeer({
|
|
248
|
+
transports: [
|
|
249
|
+
transport
|
|
250
|
+
]
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
if (!dialOnly) {
|
|
254
|
+
listener = await createPeer({
|
|
255
|
+
addresses: {
|
|
256
|
+
listen: [listenAddrs[0].toString()]
|
|
257
|
+
},
|
|
258
|
+
transports: [
|
|
259
|
+
transport
|
|
260
|
+
]
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const upgrader = getUpgrader(listener)
|
|
265
|
+
upgrader.upgradeInbound = async () => {
|
|
266
|
+
await delay(100)
|
|
267
|
+
throw new Error('Oh noes!')
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
await expect(dialer.dial(listenAddrs[0])).to.eventually.be.rejected
|
|
271
|
+
.with.property('name', 'EncryptionFailedError')
|
|
272
|
+
|
|
273
|
+
expect(dialer.getConnections()).to.have.lengthOf(0)
|
|
274
|
+
|
|
275
|
+
if (listener != null) {
|
|
276
|
+
expect(listener.getConnections()).to.have.lengthOf(0)
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
describe('events', () => {
|
|
282
|
+
let listenAddrs: Multiaddr[]
|
|
283
|
+
let dialAddrs: Multiaddr[]
|
|
284
|
+
let transport: (components: any) => Transport
|
|
285
|
+
let dialer: Libp2p<{ echo: Echo }>
|
|
286
|
+
let listener: Libp2p<{ echo: Echo }> | undefined
|
|
287
|
+
let dialOnly: boolean
|
|
288
|
+
|
|
289
|
+
beforeEach(async () => {
|
|
290
|
+
({ dialAddrs, listenAddrs = dialAddrs, transport, dialOnly = false } = await common.setup())
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
afterEach(async () => {
|
|
294
|
+
await stop(dialer, listener)
|
|
295
|
+
await common.teardown()
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it('emits connection', async function () {
|
|
299
|
+
if (dialOnly) {
|
|
300
|
+
return this.skip()
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
dialer = await createPeer({
|
|
304
|
+
transports: [
|
|
305
|
+
transport
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
if (!dialOnly) {
|
|
310
|
+
listener = await createPeer({
|
|
311
|
+
addresses: {
|
|
312
|
+
listen: [listenAddrs[0].toString()]
|
|
313
|
+
},
|
|
314
|
+
transports: [
|
|
315
|
+
transport
|
|
316
|
+
]
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const transportManager = getTransportManager(listener)
|
|
321
|
+
const transportListener = transportManager.getListeners()[0]
|
|
322
|
+
|
|
323
|
+
const p = pEvent(transportListener, 'connection')
|
|
324
|
+
|
|
325
|
+
await expect(dialer.dial(dialAddrs[0])).to.eventually.be.ok()
|
|
326
|
+
|
|
327
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
328
|
+
errorMessage: 'Did not emit connection event'
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
it('emits listening', async function () {
|
|
333
|
+
if (dialOnly) {
|
|
334
|
+
return this.skip()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
dialer = await createPeer({
|
|
338
|
+
transports: [
|
|
339
|
+
transport
|
|
340
|
+
]
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
if (!dialOnly) {
|
|
344
|
+
listener = await createPeer({
|
|
345
|
+
addresses: {
|
|
346
|
+
listen: [listenAddrs[0].toString()]
|
|
347
|
+
},
|
|
348
|
+
transports: [
|
|
349
|
+
transport
|
|
350
|
+
]
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const transportManager = getTransportManager(listener)
|
|
355
|
+
const t = transportManager.dialTransportForMultiaddr(dialAddrs[0])
|
|
356
|
+
|
|
357
|
+
if (t == null) {
|
|
358
|
+
throw new Error(`No transport configured for dial address ${dialAddrs[0]}`)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
let p: Promise<unknown> | undefined
|
|
362
|
+
const originalCreateListener = t.createListener.bind(t)
|
|
363
|
+
|
|
364
|
+
t.createListener = (opts) => {
|
|
365
|
+
const listener = originalCreateListener(opts)
|
|
366
|
+
p = pEvent(listener, 'listening')
|
|
367
|
+
|
|
368
|
+
return listener
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
await transportManager.listen([
|
|
372
|
+
listenAddrs[1]
|
|
373
|
+
])
|
|
374
|
+
|
|
375
|
+
if (p == null) {
|
|
376
|
+
throw new Error('Listener was not created')
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
380
|
+
errorMessage: 'Did not emit connection event'
|
|
381
|
+
})
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
it('emits close', async function () {
|
|
385
|
+
if (dialOnly) {
|
|
386
|
+
return this.skip()
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
dialer = await createPeer({
|
|
390
|
+
transports: [
|
|
391
|
+
transport
|
|
392
|
+
]
|
|
393
|
+
})
|
|
394
|
+
listener = await createPeer({
|
|
395
|
+
addresses: {
|
|
396
|
+
listen: [listenAddrs[0].toString()]
|
|
397
|
+
},
|
|
398
|
+
transports: [
|
|
399
|
+
transport
|
|
400
|
+
]
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
const transportManager = getTransportManager(listener)
|
|
404
|
+
const transportListener = transportManager.getListeners()[0]
|
|
405
|
+
|
|
406
|
+
const p = pEvent(transportListener, 'close')
|
|
407
|
+
|
|
408
|
+
await listener.stop()
|
|
409
|
+
|
|
410
|
+
await raceSignal(p, AbortSignal.timeout(1000), {
|
|
411
|
+
errorMessage: 'Did not emit close event'
|
|
412
|
+
})
|
|
413
|
+
})
|
|
26
414
|
})
|
|
27
415
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import { echo } from '@libp2p/echo'
|
|
4
|
+
import { memory } from '@libp2p/memory'
|
|
5
|
+
import { plaintext } from '@libp2p/plaintext'
|
|
6
|
+
import delay from 'delay'
|
|
7
|
+
import map from 'it-map'
|
|
8
|
+
import { createLibp2p } from 'libp2p'
|
|
9
|
+
import { mockMuxer } from '../mocks/muxer.js'
|
|
10
|
+
import type { Echo } from '@libp2p/echo'
|
|
11
|
+
import type { Libp2p, Upgrader } from '@libp2p/interface'
|
|
12
|
+
import type { TransportManager } from '@libp2p/interface-internal'
|
|
13
|
+
import type { Libp2pOptions } from 'libp2p'
|
|
14
|
+
|
|
15
|
+
export async function createPeer (config: Partial<Libp2pOptions<{ echo: Echo }>> = {}): Promise<Libp2p<{ echo: Echo }>> {
|
|
16
|
+
const node = await createLibp2p({
|
|
17
|
+
transports: [
|
|
18
|
+
memory()
|
|
19
|
+
],
|
|
20
|
+
connectionEncrypters: [
|
|
21
|
+
plaintext()
|
|
22
|
+
],
|
|
23
|
+
streamMuxers: [
|
|
24
|
+
() => mockMuxer()
|
|
25
|
+
],
|
|
26
|
+
connectionGater: {
|
|
27
|
+
denyDialMultiaddr: () => false
|
|
28
|
+
},
|
|
29
|
+
...config,
|
|
30
|
+
services: {
|
|
31
|
+
echo: echo(),
|
|
32
|
+
...config.services
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return node
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Monkey patch the upgrader in the passed libp2p to add latency to any
|
|
41
|
+
* multiaddr connections upgraded to connections - this is to work with
|
|
42
|
+
* transports that have their own muxers/encrypters and do not support
|
|
43
|
+
* connection protection
|
|
44
|
+
*/
|
|
45
|
+
export function slowNetwork (libp2p: any, latency: number): void {
|
|
46
|
+
const upgrader: Upgrader = getUpgrader(libp2p)
|
|
47
|
+
|
|
48
|
+
const originalUpgradeInbound = upgrader.upgradeInbound.bind(upgrader)
|
|
49
|
+
const originalUpgradeOutbound = upgrader.upgradeOutbound.bind(upgrader)
|
|
50
|
+
|
|
51
|
+
upgrader.upgradeInbound = async (maConn, opts) => {
|
|
52
|
+
maConn.source = map(maConn.source, async (buf) => {
|
|
53
|
+
await delay(latency)
|
|
54
|
+
return buf
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
return originalUpgradeInbound(maConn, opts)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
upgrader.upgradeOutbound = async (maConn, opts) => {
|
|
61
|
+
maConn.source = map(maConn.source, async (buf) => {
|
|
62
|
+
await delay(latency)
|
|
63
|
+
return buf
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return originalUpgradeOutbound(maConn, opts)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function getUpgrader (libp2p: any): Upgrader {
|
|
71
|
+
return libp2p.components.upgrader
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function getTransportManager (libp2p: any): TransportManager {
|
|
75
|
+
return libp2p.components.transportManager
|
|
76
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connection/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;+BAE7B,UAAU,UAAU,CAAC,KAAG,IAAI;AAAlD,wBAgKC"}
|