@libp2p/interop 5.0.0 → 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.js +2 -2
- package/dist/src/connect.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 +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/pubsub/floodsub.js +6 -4
- package/dist/src/pubsub/floodsub.js.map +1 -1
- package/dist/src/pubsub/gossipsub.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/package.json +14 -4
- package/src/connect.ts +2 -2
- package/src/index.ts +8 -1
- package/src/pubsub/floodsub.ts +6 -4
- package/src/pubsub/gossipsub.ts +1 -1
- 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
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
/* eslint-disable import/export */
|
|
2
|
+
/* eslint-disable complexity */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
|
+
|
|
7
|
+
import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime'
|
|
8
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
9
|
+
import type { Codec } from 'protons-runtime'
|
|
10
|
+
|
|
11
|
+
export interface HopMessage {
|
|
12
|
+
type?: HopMessage.Type
|
|
13
|
+
peer?: Peer
|
|
14
|
+
reservation?: Reservation
|
|
15
|
+
limit?: Limit
|
|
16
|
+
status?: Status
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export namespace HopMessage {
|
|
20
|
+
export enum Type {
|
|
21
|
+
RESERVE = 'RESERVE',
|
|
22
|
+
CONNECT = 'CONNECT',
|
|
23
|
+
STATUS = 'STATUS'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
enum __TypeValues {
|
|
27
|
+
RESERVE = 0,
|
|
28
|
+
CONNECT = 1,
|
|
29
|
+
STATUS = 2
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export namespace Type {
|
|
33
|
+
export const codec = (): Codec<Type> => {
|
|
34
|
+
return enumeration<Type>(__TypeValues)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let _codec: Codec<HopMessage>
|
|
39
|
+
|
|
40
|
+
export const codec = (): Codec<HopMessage> => {
|
|
41
|
+
if (_codec == null) {
|
|
42
|
+
_codec = message<HopMessage>((obj, w, opts = {}) => {
|
|
43
|
+
if (opts.lengthDelimited !== false) {
|
|
44
|
+
w.fork()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (obj.type != null) {
|
|
48
|
+
w.uint32(8)
|
|
49
|
+
HopMessage.Type.codec().encode(obj.type, w)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (obj.peer != null) {
|
|
53
|
+
w.uint32(18)
|
|
54
|
+
Peer.codec().encode(obj.peer, w, {
|
|
55
|
+
writeDefaults: false
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (obj.reservation != null) {
|
|
60
|
+
w.uint32(26)
|
|
61
|
+
Reservation.codec().encode(obj.reservation, w, {
|
|
62
|
+
writeDefaults: false
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (obj.limit != null) {
|
|
67
|
+
w.uint32(34)
|
|
68
|
+
Limit.codec().encode(obj.limit, w, {
|
|
69
|
+
writeDefaults: false
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (obj.status != null) {
|
|
74
|
+
w.uint32(40)
|
|
75
|
+
Status.codec().encode(obj.status, w)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (opts.lengthDelimited !== false) {
|
|
79
|
+
w.ldelim()
|
|
80
|
+
}
|
|
81
|
+
}, (reader, length) => {
|
|
82
|
+
const obj: any = {}
|
|
83
|
+
|
|
84
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
85
|
+
|
|
86
|
+
while (reader.pos < end) {
|
|
87
|
+
const tag = reader.uint32()
|
|
88
|
+
|
|
89
|
+
switch (tag >>> 3) {
|
|
90
|
+
case 1:
|
|
91
|
+
obj.type = HopMessage.Type.codec().decode(reader)
|
|
92
|
+
break
|
|
93
|
+
case 2:
|
|
94
|
+
obj.peer = Peer.codec().decode(reader, reader.uint32())
|
|
95
|
+
break
|
|
96
|
+
case 3:
|
|
97
|
+
obj.reservation = Reservation.codec().decode(reader, reader.uint32())
|
|
98
|
+
break
|
|
99
|
+
case 4:
|
|
100
|
+
obj.limit = Limit.codec().decode(reader, reader.uint32())
|
|
101
|
+
break
|
|
102
|
+
case 5:
|
|
103
|
+
obj.status = Status.codec().decode(reader)
|
|
104
|
+
break
|
|
105
|
+
default:
|
|
106
|
+
reader.skipType(tag & 7)
|
|
107
|
+
break
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return obj
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return _codec
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export const encode = (obj: HopMessage): Uint8Array => {
|
|
119
|
+
return encodeMessage(obj, HopMessage.codec())
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): HopMessage => {
|
|
123
|
+
return decodeMessage(buf, HopMessage.codec())
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface StopMessage {
|
|
128
|
+
type?: StopMessage.Type
|
|
129
|
+
peer?: Peer
|
|
130
|
+
limit?: Limit
|
|
131
|
+
status?: Status
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export namespace StopMessage {
|
|
135
|
+
export enum Type {
|
|
136
|
+
CONNECT = 'CONNECT',
|
|
137
|
+
STATUS = 'STATUS'
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
enum __TypeValues {
|
|
141
|
+
CONNECT = 0,
|
|
142
|
+
STATUS = 1
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export namespace Type {
|
|
146
|
+
export const codec = (): Codec<Type> => {
|
|
147
|
+
return enumeration<Type>(__TypeValues)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let _codec: Codec<StopMessage>
|
|
152
|
+
|
|
153
|
+
export const codec = (): Codec<StopMessage> => {
|
|
154
|
+
if (_codec == null) {
|
|
155
|
+
_codec = message<StopMessage>((obj, w, opts = {}) => {
|
|
156
|
+
if (opts.lengthDelimited !== false) {
|
|
157
|
+
w.fork()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (obj.type != null) {
|
|
161
|
+
w.uint32(8)
|
|
162
|
+
StopMessage.Type.codec().encode(obj.type, w)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (obj.peer != null) {
|
|
166
|
+
w.uint32(18)
|
|
167
|
+
Peer.codec().encode(obj.peer, w, {
|
|
168
|
+
writeDefaults: false
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (obj.limit != null) {
|
|
173
|
+
w.uint32(26)
|
|
174
|
+
Limit.codec().encode(obj.limit, w, {
|
|
175
|
+
writeDefaults: false
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (obj.status != null) {
|
|
180
|
+
w.uint32(32)
|
|
181
|
+
Status.codec().encode(obj.status, w)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (opts.lengthDelimited !== false) {
|
|
185
|
+
w.ldelim()
|
|
186
|
+
}
|
|
187
|
+
}, (reader, length) => {
|
|
188
|
+
const obj: any = {}
|
|
189
|
+
|
|
190
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
191
|
+
|
|
192
|
+
while (reader.pos < end) {
|
|
193
|
+
const tag = reader.uint32()
|
|
194
|
+
|
|
195
|
+
switch (tag >>> 3) {
|
|
196
|
+
case 1:
|
|
197
|
+
obj.type = StopMessage.Type.codec().decode(reader)
|
|
198
|
+
break
|
|
199
|
+
case 2:
|
|
200
|
+
obj.peer = Peer.codec().decode(reader, reader.uint32())
|
|
201
|
+
break
|
|
202
|
+
case 3:
|
|
203
|
+
obj.limit = Limit.codec().decode(reader, reader.uint32())
|
|
204
|
+
break
|
|
205
|
+
case 4:
|
|
206
|
+
obj.status = Status.codec().decode(reader)
|
|
207
|
+
break
|
|
208
|
+
default:
|
|
209
|
+
reader.skipType(tag & 7)
|
|
210
|
+
break
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return obj
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return _codec
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const encode = (obj: StopMessage): Uint8Array => {
|
|
222
|
+
return encodeMessage(obj, StopMessage.codec())
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): StopMessage => {
|
|
226
|
+
return decodeMessage(buf, StopMessage.codec())
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface Peer {
|
|
231
|
+
id: Uint8Array
|
|
232
|
+
addrs: Uint8Array[]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export namespace Peer {
|
|
236
|
+
let _codec: Codec<Peer>
|
|
237
|
+
|
|
238
|
+
export const codec = (): Codec<Peer> => {
|
|
239
|
+
if (_codec == null) {
|
|
240
|
+
_codec = message<Peer>((obj, w, opts = {}) => {
|
|
241
|
+
if (opts.lengthDelimited !== false) {
|
|
242
|
+
w.fork()
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (opts.writeDefaults === true || (obj.id != null && obj.id.byteLength > 0)) {
|
|
246
|
+
w.uint32(10)
|
|
247
|
+
w.bytes(obj.id)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (obj.addrs != null) {
|
|
251
|
+
for (const value of obj.addrs) {
|
|
252
|
+
w.uint32(18)
|
|
253
|
+
w.bytes(value)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (opts.lengthDelimited !== false) {
|
|
258
|
+
w.ldelim()
|
|
259
|
+
}
|
|
260
|
+
}, (reader, length) => {
|
|
261
|
+
const obj: any = {
|
|
262
|
+
id: new Uint8Array(0),
|
|
263
|
+
addrs: []
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
267
|
+
|
|
268
|
+
while (reader.pos < end) {
|
|
269
|
+
const tag = reader.uint32()
|
|
270
|
+
|
|
271
|
+
switch (tag >>> 3) {
|
|
272
|
+
case 1:
|
|
273
|
+
obj.id = reader.bytes()
|
|
274
|
+
break
|
|
275
|
+
case 2:
|
|
276
|
+
obj.addrs.push(reader.bytes())
|
|
277
|
+
break
|
|
278
|
+
default:
|
|
279
|
+
reader.skipType(tag & 7)
|
|
280
|
+
break
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return obj
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return _codec
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export const encode = (obj: Peer): Uint8Array => {
|
|
292
|
+
return encodeMessage(obj, Peer.codec())
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): Peer => {
|
|
296
|
+
return decodeMessage(buf, Peer.codec())
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export interface Reservation {
|
|
301
|
+
expire: bigint
|
|
302
|
+
addrs: Uint8Array[]
|
|
303
|
+
voucher?: Uint8Array
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export namespace Reservation {
|
|
307
|
+
let _codec: Codec<Reservation>
|
|
308
|
+
|
|
309
|
+
export const codec = (): Codec<Reservation> => {
|
|
310
|
+
if (_codec == null) {
|
|
311
|
+
_codec = message<Reservation>((obj, w, opts = {}) => {
|
|
312
|
+
if (opts.lengthDelimited !== false) {
|
|
313
|
+
w.fork()
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (opts.writeDefaults === true || obj.expire !== 0n) {
|
|
317
|
+
w.uint32(8)
|
|
318
|
+
w.uint64(obj.expire)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (obj.addrs != null) {
|
|
322
|
+
for (const value of obj.addrs) {
|
|
323
|
+
w.uint32(18)
|
|
324
|
+
w.bytes(value)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (obj.voucher != null) {
|
|
329
|
+
w.uint32(26)
|
|
330
|
+
w.bytes(obj.voucher)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (opts.lengthDelimited !== false) {
|
|
334
|
+
w.ldelim()
|
|
335
|
+
}
|
|
336
|
+
}, (reader, length) => {
|
|
337
|
+
const obj: any = {
|
|
338
|
+
expire: 0n,
|
|
339
|
+
addrs: []
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
343
|
+
|
|
344
|
+
while (reader.pos < end) {
|
|
345
|
+
const tag = reader.uint32()
|
|
346
|
+
|
|
347
|
+
switch (tag >>> 3) {
|
|
348
|
+
case 1:
|
|
349
|
+
obj.expire = reader.uint64()
|
|
350
|
+
break
|
|
351
|
+
case 2:
|
|
352
|
+
obj.addrs.push(reader.bytes())
|
|
353
|
+
break
|
|
354
|
+
case 3:
|
|
355
|
+
obj.voucher = reader.bytes()
|
|
356
|
+
break
|
|
357
|
+
default:
|
|
358
|
+
reader.skipType(tag & 7)
|
|
359
|
+
break
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return obj
|
|
364
|
+
})
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return _codec
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export const encode = (obj: Reservation): Uint8Array => {
|
|
371
|
+
return encodeMessage(obj, Reservation.codec())
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): Reservation => {
|
|
375
|
+
return decodeMessage(buf, Reservation.codec())
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export interface Limit {
|
|
380
|
+
duration?: number
|
|
381
|
+
data?: bigint
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export namespace Limit {
|
|
385
|
+
let _codec: Codec<Limit>
|
|
386
|
+
|
|
387
|
+
export const codec = (): Codec<Limit> => {
|
|
388
|
+
if (_codec == null) {
|
|
389
|
+
_codec = message<Limit>((obj, w, opts = {}) => {
|
|
390
|
+
if (opts.lengthDelimited !== false) {
|
|
391
|
+
w.fork()
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (obj.duration != null) {
|
|
395
|
+
w.uint32(8)
|
|
396
|
+
w.uint32(obj.duration)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (obj.data != null) {
|
|
400
|
+
w.uint32(16)
|
|
401
|
+
w.uint64(obj.data)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (opts.lengthDelimited !== false) {
|
|
405
|
+
w.ldelim()
|
|
406
|
+
}
|
|
407
|
+
}, (reader, length) => {
|
|
408
|
+
const obj: any = {}
|
|
409
|
+
|
|
410
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
411
|
+
|
|
412
|
+
while (reader.pos < end) {
|
|
413
|
+
const tag = reader.uint32()
|
|
414
|
+
|
|
415
|
+
switch (tag >>> 3) {
|
|
416
|
+
case 1:
|
|
417
|
+
obj.duration = reader.uint32()
|
|
418
|
+
break
|
|
419
|
+
case 2:
|
|
420
|
+
obj.data = reader.uint64()
|
|
421
|
+
break
|
|
422
|
+
default:
|
|
423
|
+
reader.skipType(tag & 7)
|
|
424
|
+
break
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return obj
|
|
429
|
+
})
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return _codec
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export const encode = (obj: Limit): Uint8Array => {
|
|
436
|
+
return encodeMessage(obj, Limit.codec())
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): Limit => {
|
|
440
|
+
return decodeMessage(buf, Limit.codec())
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export enum Status {
|
|
445
|
+
UNUSED = 'UNUSED',
|
|
446
|
+
OK = 'OK',
|
|
447
|
+
RESERVATION_REFUSED = 'RESERVATION_REFUSED',
|
|
448
|
+
RESOURCE_LIMIT_EXCEEDED = 'RESOURCE_LIMIT_EXCEEDED',
|
|
449
|
+
PERMISSION_DENIED = 'PERMISSION_DENIED',
|
|
450
|
+
CONNECTION_FAILED = 'CONNECTION_FAILED',
|
|
451
|
+
NO_RESERVATION = 'NO_RESERVATION',
|
|
452
|
+
MALFORMED_MESSAGE = 'MALFORMED_MESSAGE',
|
|
453
|
+
UNEXPECTED_MESSAGE = 'UNEXPECTED_MESSAGE'
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
enum __StatusValues {
|
|
457
|
+
UNUSED = 0,
|
|
458
|
+
OK = 100,
|
|
459
|
+
RESERVATION_REFUSED = 200,
|
|
460
|
+
RESOURCE_LIMIT_EXCEEDED = 201,
|
|
461
|
+
PERMISSION_DENIED = 202,
|
|
462
|
+
CONNECTION_FAILED = 203,
|
|
463
|
+
NO_RESERVATION = 204,
|
|
464
|
+
MALFORMED_MESSAGE = 400,
|
|
465
|
+
UNEXPECTED_MESSAGE = 401
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export namespace Status {
|
|
469
|
+
export const codec = (): Codec<Status> => {
|
|
470
|
+
return enumeration<Status>(__StatusValues)
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
export interface ReservationVoucher {
|
|
474
|
+
relay: Uint8Array
|
|
475
|
+
peer: Uint8Array
|
|
476
|
+
expiration: bigint
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export namespace ReservationVoucher {
|
|
480
|
+
let _codec: Codec<ReservationVoucher>
|
|
481
|
+
|
|
482
|
+
export const codec = (): Codec<ReservationVoucher> => {
|
|
483
|
+
if (_codec == null) {
|
|
484
|
+
_codec = message<ReservationVoucher>((obj, w, opts = {}) => {
|
|
485
|
+
if (opts.lengthDelimited !== false) {
|
|
486
|
+
w.fork()
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (opts.writeDefaults === true || (obj.relay != null && obj.relay.byteLength > 0)) {
|
|
490
|
+
w.uint32(10)
|
|
491
|
+
w.bytes(obj.relay)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (opts.writeDefaults === true || (obj.peer != null && obj.peer.byteLength > 0)) {
|
|
495
|
+
w.uint32(18)
|
|
496
|
+
w.bytes(obj.peer)
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (opts.writeDefaults === true || obj.expiration !== 0n) {
|
|
500
|
+
w.uint32(24)
|
|
501
|
+
w.uint64(obj.expiration)
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (opts.lengthDelimited !== false) {
|
|
505
|
+
w.ldelim()
|
|
506
|
+
}
|
|
507
|
+
}, (reader, length) => {
|
|
508
|
+
const obj: any = {
|
|
509
|
+
relay: new Uint8Array(0),
|
|
510
|
+
peer: new Uint8Array(0),
|
|
511
|
+
expiration: 0n
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
515
|
+
|
|
516
|
+
while (reader.pos < end) {
|
|
517
|
+
const tag = reader.uint32()
|
|
518
|
+
|
|
519
|
+
switch (tag >>> 3) {
|
|
520
|
+
case 1:
|
|
521
|
+
obj.relay = reader.bytes()
|
|
522
|
+
break
|
|
523
|
+
case 2:
|
|
524
|
+
obj.peer = reader.bytes()
|
|
525
|
+
break
|
|
526
|
+
case 3:
|
|
527
|
+
obj.expiration = reader.uint64()
|
|
528
|
+
break
|
|
529
|
+
default:
|
|
530
|
+
reader.skipType(tag & 7)
|
|
531
|
+
break
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return obj
|
|
536
|
+
})
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return _codec
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export const encode = (obj: ReservationVoucher): Uint8Array => {
|
|
543
|
+
return encodeMessage(obj, ReservationVoucher.codec())
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): ReservationVoucher => {
|
|
547
|
+
return decodeMessage(buf, ReservationVoucher.codec())
|
|
548
|
+
}
|
|
549
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
2
|
+
import type { Daemon } from '../index.js'
|
|
3
|
+
import { HopMessage } from './pb/index.js'
|
|
4
|
+
import type { Duplex } from 'it-stream-types'
|
|
5
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
6
|
+
import { pipe } from 'it-pipe'
|
|
7
|
+
import { pbStream } from 'it-pb-stream'
|
|
8
|
+
|
|
9
|
+
const RELAY_V2_HOP = '/libp2p/circuit/relay/0.2.0/hop'
|
|
10
|
+
|
|
11
|
+
export const reserve = async (d: Daemon, peerID: PeerId, message?: Partial<HopMessage>): Promise<HopMessage> => {
|
|
12
|
+
const stream = await d.client.openStream(peerID, RELAY_V2_HOP)
|
|
13
|
+
const pb = pbStream(stream)
|
|
14
|
+
pb.writePB({
|
|
15
|
+
type: HopMessage.Type.RESERVE,
|
|
16
|
+
...(message ?? {})
|
|
17
|
+
}, HopMessage)
|
|
18
|
+
|
|
19
|
+
return await pb.readPB(HopMessage)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const echoHandler = {
|
|
23
|
+
protocol: '/echo/1.0.0',
|
|
24
|
+
handler: async (stream: Duplex<Uint8ArrayList | Uint8Array, Uint8Array, Promise<void>>) => {
|
|
25
|
+
await pipe(
|
|
26
|
+
stream,
|
|
27
|
+
async function * (src) {
|
|
28
|
+
for await (const buf of src) {
|
|
29
|
+
yield buf.subarray()
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
stream
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|