@libp2p/interop 4.0.2 → 6.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/dist/index.min.js +5 -5
- package/dist/src/connect.d.ts.map +1 -1
- package/dist/src/connect.js +3 -3
- package/dist/src/connect.js.map +1 -1
- package/dist/src/dht/content-fetching.d.ts.map +1 -1
- package/dist/src/dht/content-fetching.js +1 -1
- package/dist/src/dht/content-fetching.js.map +1 -1
- package/dist/src/dht/content-routing.d.ts.map +1 -1
- package/dist/src/dht/content-routing.js +1 -1
- package/dist/src/dht/content-routing.js.map +1 -1
- package/dist/src/dht/index.d.ts.map +1 -1
- package/dist/src/dht/index.js +3 -3
- package/dist/src/dht/index.js.map +1 -1
- package/dist/src/dht/peer-routing.d.ts.map +1 -1
- package/dist/src/dht/peer-routing.js +1 -1
- package/dist/src/dht/peer-routing.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/pubsub/floodsub.d.ts.map +1 -1
- package/dist/src/pubsub/floodsub.js +7 -5
- package/dist/src/pubsub/floodsub.js.map +1 -1
- package/dist/src/pubsub/gossipsub.d.ts.map +1 -1
- package/dist/src/pubsub/gossipsub.js +1 -1
- package/dist/src/pubsub/gossipsub.js.map +1 -1
- package/dist/src/pubsub/hybrid.d.ts.map +1 -1
- package/dist/src/pubsub/hybrid.js +1 -1
- package/dist/src/pubsub/hybrid.js.map +1 -1
- package/dist/src/pubsub/index.d.ts.map +1 -1
- package/dist/src/pubsub/index.js +3 -3
- package/dist/src/pubsub/index.js.map +1 -1
- package/dist/src/relay/index.d.ts +3 -0
- package/dist/src/relay/index.d.ts.map +1 -0
- package/dist/src/relay/index.js +62 -0
- package/dist/src/relay/index.js.map +1 -0
- package/dist/src/relay/pb/index.d.ts +93 -0
- package/dist/src/relay/pb/index.d.ts.map +1 -0
- package/dist/src/relay/pb/index.js +435 -0
- package/dist/src/relay/pb/index.js.map +1 -0
- package/dist/src/relay/util.d.ts +11 -0
- package/dist/src/relay/util.d.ts.map +1 -0
- package/dist/src/relay/util.js +24 -0
- package/dist/src/relay/util.js.map +1 -0
- package/dist/src/streams/echo.d.ts.map +1 -1
- package/dist/src/streams/echo.js +1 -1
- package/dist/src/streams/echo.js.map +1 -1
- package/dist/src/streams/index.d.ts.map +1 -1
- package/dist/src/streams/index.js +2 -2
- package/dist/src/streams/index.js.map +1 -1
- package/package.json +14 -7
- package/src/connect.ts +5 -5
- package/src/dht/content-fetching.ts +3 -3
- package/src/dht/content-routing.ts +3 -3
- package/src/dht/index.ts +4 -4
- package/src/dht/peer-routing.ts +3 -3
- package/src/index.ts +10 -3
- package/src/pubsub/floodsub.ts +11 -9
- package/src/pubsub/gossipsub.ts +5 -5
- package/src/pubsub/hybrid.ts +5 -5
- package/src/pubsub/index.ts +4 -4
- package/src/relay/index.ts +76 -0
- package/src/relay/pb/index.proto +67 -0
- package/src/relay/pb/index.ts +549 -0
- package/src/relay/util.ts +35 -0
- package/src/streams/echo.ts +3 -3
- package/src/streams/index.ts +3 -3
|
@@ -13,7 +13,7 @@ const record = {
|
|
|
13
13
|
value: uint8ArrayFromString('080012a60230820122300d06092a864886f70d01010105000382010f003082010a0282010100c2588f998971dac9e3eef76a311bf9159505aff69ea3b664c55a36aa28ee08de1127228a4d431bb9c0840240c75f6e98a0843a78d945491a3ea5e1f7cee2bc71383510db5290702383975b7bffae9fb40c84cc1220fb4a7db862fffb0de42f8fd8fb33a17deb20f30e2d0f194791fe69355a392f77df35f101e08a2fc95b2c018768938814fcb52482f899f5e90a1905e8abbcdbb1647ad80a5b0417e1ce8320d64197a6ba3848926375c63adebabdf6eb82109bcadfee13b62bf922bbb6f74c1a26c9bc6122d1436787e0e6de3c152b1959701092abef84599f73eaedb2fcef9f87293e1bbe8e0fef3f1a7fd2e8b94c7e633f88473644a63cb948e4d25c54490203010001', 'hex')
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function contentFetchingTests (factory: DaemonFactory) {
|
|
16
|
+
export function contentFetchingTests (factory: DaemonFactory): void {
|
|
17
17
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
18
18
|
|
|
19
19
|
for (const typeA of nodeTypes) {
|
|
@@ -27,7 +27,7 @@ export function contentFetchingTests (factory: DaemonFactory) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function runContentFetchingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
30
|
+
function runContentFetchingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
31
31
|
describe('dht.contentFetching', () => {
|
|
32
32
|
let daemons: Daemon[]
|
|
33
33
|
|
|
@@ -53,7 +53,7 @@ function runContentFetchingTests (factory: DaemonFactory, optionsA: SpawnOptions
|
|
|
53
53
|
after(async function () {
|
|
54
54
|
if (daemons != null) {
|
|
55
55
|
await Promise.all(
|
|
56
|
-
daemons.map(async (daemon) => await daemon.stop())
|
|
56
|
+
daemons.map(async (daemon) => { await daemon.stop() })
|
|
57
57
|
)
|
|
58
58
|
}
|
|
59
59
|
})
|
|
@@ -6,7 +6,7 @@ import all from 'it-all'
|
|
|
6
6
|
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
7
7
|
import type { IdentifyResult } from '@libp2p/daemon-client'
|
|
8
8
|
|
|
9
|
-
export function contentRoutingTests (factory: DaemonFactory) {
|
|
9
|
+
export function contentRoutingTests (factory: DaemonFactory): void {
|
|
10
10
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
11
11
|
|
|
12
12
|
for (const typeA of nodeTypes) {
|
|
@@ -25,7 +25,7 @@ export function contentRoutingTests (factory: DaemonFactory) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function runContentRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
28
|
+
function runContentRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
29
29
|
describe('dht.contentRouting', () => {
|
|
30
30
|
let daemons: Daemon[]
|
|
31
31
|
let identify: IdentifyResult[]
|
|
@@ -55,7 +55,7 @@ function runContentRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions,
|
|
|
55
55
|
after(async function () {
|
|
56
56
|
if (daemons != null) {
|
|
57
57
|
await Promise.all(
|
|
58
|
-
daemons.map(async (daemon) => await daemon.stop())
|
|
58
|
+
daemons.map(async (daemon) => { await daemon.stop() })
|
|
59
59
|
)
|
|
60
60
|
}
|
|
61
61
|
})
|
package/src/dht/index.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { contentFetchingTests } from './content-fetching.js'
|
|
|
3
3
|
import { contentRoutingTests } from './content-routing.js'
|
|
4
4
|
import { peerRoutingTests } from './peer-routing.js'
|
|
5
5
|
|
|
6
|
-
export async function dhtTests (factory: DaemonFactory) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export async function dhtTests (factory: DaemonFactory): Promise<void> {
|
|
7
|
+
contentFetchingTests(factory)
|
|
8
|
+
contentRoutingTests(factory)
|
|
9
|
+
peerRoutingTests(factory)
|
|
10
10
|
}
|
package/src/dht/peer-routing.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
|
5
5
|
import pRetry from 'p-retry'
|
|
6
6
|
import type { PeerInfo } from '@libp2p/interface-peer-info'
|
|
7
7
|
|
|
8
|
-
export function peerRoutingTests (factory: DaemonFactory) {
|
|
8
|
+
export function peerRoutingTests (factory: DaemonFactory): void {
|
|
9
9
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
10
|
|
|
11
11
|
for (const typeA of nodeTypes) {
|
|
@@ -19,7 +19,7 @@ export function peerRoutingTests (factory: DaemonFactory) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function runPeerRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
22
|
+
function runPeerRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
23
23
|
describe('dht.peerRouting', () => {
|
|
24
24
|
let daemons: Daemon[]
|
|
25
25
|
|
|
@@ -38,7 +38,7 @@ function runPeerRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, op
|
|
|
38
38
|
after(async function () {
|
|
39
39
|
if (daemons != null) {
|
|
40
40
|
await Promise.all(
|
|
41
|
-
daemons.map(async (daemon) => await daemon.stop())
|
|
41
|
+
daemons.map(async (daemon) => { await daemon.stop() })
|
|
42
42
|
)
|
|
43
43
|
}
|
|
44
44
|
})
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { connectTests } from './connect.js'
|
|
|
2
2
|
import { dhtTests } from './dht/index.js'
|
|
3
3
|
import { pubsubTests } from './pubsub/index.js'
|
|
4
4
|
import { streamTests } from './streams/index.js'
|
|
5
|
+
import { relayTests } from './relay/index.js'
|
|
5
6
|
import type { DaemonClient } from '@libp2p/daemon-client'
|
|
6
7
|
|
|
7
8
|
export interface Daemon {
|
|
@@ -22,14 +23,19 @@ export interface SpawnOptions {
|
|
|
22
23
|
pubsub?: boolean
|
|
23
24
|
pubsubRouter?: PubSubRouter
|
|
24
25
|
muxer?: Muxer
|
|
26
|
+
relay?: boolean
|
|
27
|
+
// the node will not listen on any
|
|
28
|
+
// addresses if true
|
|
29
|
+
noListen?: boolean
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
export interface DaemonFactory {
|
|
28
33
|
spawn: (options: SpawnOptions) => Promise<Daemon>
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
export async function interopTests (factory: DaemonFactory) {
|
|
32
|
-
|
|
36
|
+
export async function interopTests (factory: DaemonFactory): Promise<void> {
|
|
37
|
+
connectTests(factory)
|
|
38
|
+
relayTests(factory)
|
|
33
39
|
await dhtTests(factory)
|
|
34
40
|
await pubsubTests(factory)
|
|
35
41
|
await streamTests(factory)
|
|
@@ -39,5 +45,6 @@ export {
|
|
|
39
45
|
connectTests as connectInteropTests,
|
|
40
46
|
dhtTests as dhtInteropTests,
|
|
41
47
|
pubsubTests as pubsubInteropTests,
|
|
42
|
-
streamTests as streamInteropTests
|
|
48
|
+
streamTests as streamInteropTests,
|
|
49
|
+
relayTests as relayInteropTests
|
|
43
50
|
}
|
package/src/pubsub/floodsub.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
|
5
5
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
6
|
import first from 'it-first'
|
|
7
7
|
|
|
8
|
-
export function floodsubTests (factory: DaemonFactory) {
|
|
8
|
+
export function floodsubTests (factory: DaemonFactory): void {
|
|
9
9
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
10
|
|
|
11
11
|
for (const typeA of nodeTypes) {
|
|
@@ -19,7 +19,7 @@ export function floodsubTests (factory: DaemonFactory) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
22
|
+
function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
23
23
|
describe('pubsub.floodSub', () => {
|
|
24
24
|
let daemons: Daemon[]
|
|
25
25
|
|
|
@@ -32,15 +32,16 @@ function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optio
|
|
|
32
32
|
factory.spawn(optionsB)
|
|
33
33
|
])
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
await
|
|
35
|
+
const [peerA, peerB] = daemons
|
|
36
|
+
const identifyB = await peerB.client.identify()
|
|
37
|
+
await peerA.client.connect(identifyB.peerId, identifyB.addrs)
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
// Stop daemons
|
|
40
41
|
after(async function () {
|
|
41
42
|
if (daemons != null) {
|
|
42
43
|
await Promise.all(
|
|
43
|
-
daemons.map(async (daemon) => await daemon.stop())
|
|
44
|
+
daemons.map(async (daemon) => { await daemon.stop() })
|
|
44
45
|
)
|
|
45
46
|
}
|
|
46
47
|
})
|
|
@@ -48,19 +49,20 @@ function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optio
|
|
|
48
49
|
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
49
50
|
const topic = 'test-topic'
|
|
50
51
|
const data = uint8ArrayFromString('test-data')
|
|
52
|
+
const [peerA, peerB] = daemons
|
|
51
53
|
|
|
52
|
-
const subscribeIterator =
|
|
53
|
-
const subscriber = async () => {
|
|
54
|
+
const subscribeIterator = peerB.client.pubsub.subscribe(topic)
|
|
55
|
+
const subscriber = async (): Promise<void> => {
|
|
54
56
|
const message = await first(subscribeIterator)
|
|
55
57
|
|
|
56
58
|
expect(message).to.exist()
|
|
57
59
|
expect(message).to.have.property('data').that.equalBytes(data)
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
const publisher = async () => {
|
|
62
|
+
const publisher = async (): Promise<void> => {
|
|
61
63
|
// wait for subscription stream
|
|
62
64
|
await new Promise(resolve => setTimeout(resolve, 800))
|
|
63
|
-
await
|
|
65
|
+
await peerA.client.pubsub.publish(topic, data)
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
return await Promise.all([
|
package/src/pubsub/gossipsub.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
|
5
5
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
6
|
import first from 'it-first'
|
|
7
7
|
|
|
8
|
-
export function gossipsubTests (factory: DaemonFactory) {
|
|
8
|
+
export function gossipsubTests (factory: DaemonFactory): void {
|
|
9
9
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
10
|
|
|
11
11
|
for (const typeA of nodeTypes) {
|
|
@@ -19,7 +19,7 @@ export function gossipsubTests (factory: DaemonFactory) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
22
|
+
function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
23
23
|
describe('pubsub.gossipsub', () => {
|
|
24
24
|
let daemons: Daemon[]
|
|
25
25
|
|
|
@@ -40,7 +40,7 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
|
|
|
40
40
|
after(async function () {
|
|
41
41
|
if (daemons != null) {
|
|
42
42
|
await Promise.all(
|
|
43
|
-
daemons.map(async
|
|
43
|
+
daemons.map(async daemon => { await daemon.stop() })
|
|
44
44
|
)
|
|
45
45
|
}
|
|
46
46
|
})
|
|
@@ -50,14 +50,14 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
|
|
|
50
50
|
const data = uint8ArrayFromString('test-data')
|
|
51
51
|
|
|
52
52
|
const subscribeIterator = daemons[1].client.pubsub.subscribe(topic)
|
|
53
|
-
const subscriber = async () => {
|
|
53
|
+
const subscriber = async (): Promise<void> => {
|
|
54
54
|
const message = await first(subscribeIterator)
|
|
55
55
|
|
|
56
56
|
expect(message).to.exist()
|
|
57
57
|
expect(message).to.have.property('data').that.equalBytes(data)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const publisher = async () => {
|
|
60
|
+
const publisher = async (): Promise<void> => {
|
|
61
61
|
// wait for subscription stream
|
|
62
62
|
await new Promise(resolve => setTimeout(resolve, 800))
|
|
63
63
|
await daemons[0].client.pubsub.publish(topic, data)
|
package/src/pubsub/hybrid.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
|
5
5
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
6
|
import first from 'it-first'
|
|
7
7
|
|
|
8
|
-
export function hybridTests (factory: DaemonFactory) {
|
|
8
|
+
export function hybridTests (factory: DaemonFactory): void {
|
|
9
9
|
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
10
|
|
|
11
11
|
for (const typeA of nodeTypes) {
|
|
@@ -19,7 +19,7 @@ export function hybridTests (factory: DaemonFactory) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
22
|
+
function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
|
|
23
23
|
describe('pubsub.hybrid', () => {
|
|
24
24
|
let daemons: Daemon[]
|
|
25
25
|
|
|
@@ -40,7 +40,7 @@ function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, options
|
|
|
40
40
|
after(async function () {
|
|
41
41
|
if (daemons != null) {
|
|
42
42
|
await Promise.all(
|
|
43
|
-
daemons.map(async (daemon) => await daemon.stop())
|
|
43
|
+
daemons.map(async (daemon) => { await daemon.stop() })
|
|
44
44
|
)
|
|
45
45
|
}
|
|
46
46
|
})
|
|
@@ -50,14 +50,14 @@ function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, options
|
|
|
50
50
|
const data = uint8ArrayFromString('test-data')
|
|
51
51
|
|
|
52
52
|
const subscribeIterator = daemons[1].client.pubsub.subscribe(topic)
|
|
53
|
-
const subscriber = async () => {
|
|
53
|
+
const subscriber = async (): Promise<void> => {
|
|
54
54
|
const message = await first(subscribeIterator)
|
|
55
55
|
|
|
56
56
|
expect(message).to.exist()
|
|
57
57
|
expect(message).to.have.property('data').that.equalBytes(data)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const publisher = async () => {
|
|
60
|
+
const publisher = async (): Promise<void> => {
|
|
61
61
|
// wait for subscription stream
|
|
62
62
|
await new Promise(resolve => setTimeout(resolve, 800))
|
|
63
63
|
await daemons[0].client.pubsub.publish(topic, data)
|
package/src/pubsub/index.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { floodsubTests } from './floodsub.js'
|
|
|
3
3
|
import { gossipsubTests } from './gossipsub.js'
|
|
4
4
|
import { hybridTests } from './hybrid.js'
|
|
5
5
|
|
|
6
|
-
export async function pubsubTests (factory: DaemonFactory) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export async function pubsubTests (factory: DaemonFactory): Promise<void> {
|
|
7
|
+
floodsubTests(factory)
|
|
8
|
+
gossipsubTests(factory)
|
|
9
|
+
hybridTests(factory)
|
|
10
10
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Multiaddr, multiaddr } from '@multiformats/multiaddr'
|
|
2
|
+
import { expect } from 'aegir/chai'
|
|
3
|
+
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
4
|
+
import { Status } from './pb/index.js'
|
|
5
|
+
import { echoHandler, reserve } from './util.js'
|
|
6
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
7
|
+
import type { IdentifyResult } from '@libp2p/daemon-client'
|
|
8
|
+
import { handshake } from 'it-handshake'
|
|
9
|
+
|
|
10
|
+
export function relayTests (factory: DaemonFactory): void {
|
|
11
|
+
const t: NodeType[] = ['go', 'js']
|
|
12
|
+
t.forEach(a => { t.forEach(b => { t.forEach(r => { relayTest(factory, a, b, r) }) }) })
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function relayTest (factory: DaemonFactory, aType: NodeType, bType: NodeType, relayType: NodeType): void {
|
|
16
|
+
describe(`${aType} to ${bType} over relay ${relayType}`, () => {
|
|
17
|
+
const opts: SpawnOptions[] = [
|
|
18
|
+
{ type: aType, noise: true, noListen: true },
|
|
19
|
+
{ type: bType, noise: true, noListen: true },
|
|
20
|
+
{ type: relayType, noise: true, relay: true }
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
let aNode: Daemon
|
|
24
|
+
let bNode: Daemon
|
|
25
|
+
let relay: Daemon
|
|
26
|
+
let bId: IdentifyResult
|
|
27
|
+
let relayId: IdentifyResult
|
|
28
|
+
let bAddrViaRelay: Multiaddr
|
|
29
|
+
|
|
30
|
+
beforeEach(async function () {
|
|
31
|
+
this.timeout(20 * 1000)
|
|
32
|
+
;[aNode, bNode, relay] = await Promise.all(opts.map(async o => await factory.spawn(o)))
|
|
33
|
+
;[bId, relayId] = await Promise.all([bNode, relay].map(async d => await d.client.identify()))
|
|
34
|
+
|
|
35
|
+
// construct a relay address
|
|
36
|
+
bAddrViaRelay = multiaddr(`${relayId.addrs[0].toString()}/p2p/${relayId.peerId.toString()}/p2p-circuit/p2p/${bId.peerId.toString()}`)
|
|
37
|
+
|
|
38
|
+
// connect b to the relay
|
|
39
|
+
await bNode.client.connect(relayId.peerId, relayId.addrs)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
afterEach(async function () {
|
|
43
|
+
await Promise.all([aNode, bNode, relay].map(async d => { await d.stop() }))
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('connects', async () => {
|
|
47
|
+
// b makes reservation on relay
|
|
48
|
+
const reserveResponse = await reserve(bNode, relayId.peerId)
|
|
49
|
+
expect(reserveResponse.status).to.eq(Status.OK)
|
|
50
|
+
|
|
51
|
+
// a dials b through relay
|
|
52
|
+
await aNode.client.connect(bId.peerId, [bAddrViaRelay])
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, 500))
|
|
54
|
+
const connectedPeers = await aNode.client.listPeers()
|
|
55
|
+
expect(connectedPeers.filter(p => p.equals(bId.peerId))).to.have.length(1)
|
|
56
|
+
|
|
57
|
+
// run an echo test
|
|
58
|
+
await bNode.client.registerStreamHandler(echoHandler.protocol, echoHandler.handler)
|
|
59
|
+
const stream = await aNode.client.openStream(bId.peerId, echoHandler.protocol)
|
|
60
|
+
|
|
61
|
+
// send some data, read the response
|
|
62
|
+
const input = uint8ArrayFromString('test')
|
|
63
|
+
const shake = handshake(stream)
|
|
64
|
+
shake.write(input)
|
|
65
|
+
const output = await shake.read()
|
|
66
|
+
|
|
67
|
+
expect(output?.subarray()).to.deep.equal(input)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('fails to connect without a reservation', async () => {
|
|
71
|
+
// a dials b through relay
|
|
72
|
+
await expect(aNode.client.connect(bId.peerId, [bAddrViaRelay])).to.eventually.be.rejected
|
|
73
|
+
.with.property('message').that.matches(/NO_RESERVATION/)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
message HopMessage {
|
|
4
|
+
enum Type {
|
|
5
|
+
RESERVE = 0;
|
|
6
|
+
CONNECT = 1;
|
|
7
|
+
STATUS = 2;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// the presence of this field is enforced at application level
|
|
11
|
+
optional Type type = 1;
|
|
12
|
+
|
|
13
|
+
optional Peer peer = 2;
|
|
14
|
+
optional Reservation reservation = 3;
|
|
15
|
+
optional Limit limit = 4;
|
|
16
|
+
|
|
17
|
+
optional Status status = 5;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
message StopMessage {
|
|
21
|
+
enum Type {
|
|
22
|
+
CONNECT = 0;
|
|
23
|
+
STATUS = 1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// the presence of this field is enforced at application level
|
|
27
|
+
optional Type type = 1;
|
|
28
|
+
|
|
29
|
+
optional Peer peer = 2;
|
|
30
|
+
optional Limit limit = 3;
|
|
31
|
+
|
|
32
|
+
optional Status status = 4;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
message Peer {
|
|
36
|
+
bytes id = 1;
|
|
37
|
+
repeated bytes addrs = 2;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
message Reservation {
|
|
41
|
+
uint64 expire = 1; // Unix expiration time (UTC)
|
|
42
|
+
repeated bytes addrs = 2; // relay addrs for reserving peer
|
|
43
|
+
optional bytes voucher = 3; // reservation voucher
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
message Limit {
|
|
47
|
+
optional uint32 duration = 1; // seconds
|
|
48
|
+
optional uint64 data = 2; // bytes
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
enum Status {
|
|
52
|
+
UNUSED = 0;
|
|
53
|
+
OK = 100;
|
|
54
|
+
RESERVATION_REFUSED = 200;
|
|
55
|
+
RESOURCE_LIMIT_EXCEEDED = 201;
|
|
56
|
+
PERMISSION_DENIED = 202;
|
|
57
|
+
CONNECTION_FAILED = 203;
|
|
58
|
+
NO_RESERVATION = 204;
|
|
59
|
+
MALFORMED_MESSAGE = 400;
|
|
60
|
+
UNEXPECTED_MESSAGE = 401;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
message ReservationVoucher {
|
|
64
|
+
bytes relay = 1;
|
|
65
|
+
bytes peer = 2;
|
|
66
|
+
uint64 expiration = 3;
|
|
67
|
+
}
|