@helia/bitswap 0.0.0 → 1.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 +6 -1
- package/dist/src/bitswap.d.ts +3 -2
- package/dist/src/bitswap.d.ts.map +1 -1
- package/dist/src/bitswap.js +7 -14
- package/dist/src/bitswap.js.map +1 -1
- package/dist/src/index.d.ts +2 -38
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/network.d.ts +3 -4
- package/dist/src/network.d.ts.map +1 -1
- package/dist/src/network.js +28 -50
- package/dist/src/network.js.map +1 -1
- package/dist/src/peer-want-lists/index.d.ts +2 -2
- package/dist/src/peer-want-lists/index.d.ts.map +1 -1
- package/dist/src/peer-want-lists/index.js +2 -2
- package/dist/src/peer-want-lists/index.js.map +1 -1
- package/dist/src/session.d.ts +13 -8
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/session.js +25 -88
- package/dist/src/session.js.map +1 -1
- package/dist/src/stats.d.ts +2 -2
- package/dist/src/stats.d.ts.map +1 -1
- package/dist/src/stats.js +4 -4
- package/dist/src/stats.js.map +1 -1
- package/dist/src/want-list.d.ts +20 -23
- package/dist/src/want-list.d.ts.map +1 -1
- package/dist/src/want-list.js +130 -130
- package/dist/src/want-list.js.map +1 -1
- package/dist/typedoc-urls.json +0 -4
- package/package.json +5 -5
- package/src/bitswap.ts +9 -16
- package/src/index.ts +2 -43
- package/src/network.ts +32 -59
- package/src/peer-want-lists/index.ts +4 -4
- package/src/session.ts +31 -120
- package/src/stats.ts +6 -6
- package/src/want-list.ts +197 -209
package/src/want-list.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { trackedPeerMap
|
|
1
|
+
import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface'
|
|
2
|
+
import { trackedPeerMap } from '@libp2p/peer-collections'
|
|
3
3
|
import { trackedMap } from '@libp2p/utils/tracked-map'
|
|
4
4
|
import all from 'it-all'
|
|
5
5
|
import filter from 'it-filter'
|
|
@@ -8,14 +8,16 @@ import { pipe } from 'it-pipe'
|
|
|
8
8
|
import { CID } from 'multiformats/cid'
|
|
9
9
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
10
10
|
import pDefer from 'p-defer'
|
|
11
|
+
import { raceEvent } from 'race-event'
|
|
12
|
+
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
11
13
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
12
14
|
import { DEFAULT_MESSAGE_SEND_DELAY } from './constants.js'
|
|
13
15
|
import { BlockPresenceType, WantType } from './pb/message.js'
|
|
14
16
|
import vd from './utils/varint-decoder.js'
|
|
15
|
-
import type { MultihashHasherLoader } from './index.js'
|
|
17
|
+
import type { BitswapNotifyProgressEvents, MultihashHasherLoader } from './index.js'
|
|
16
18
|
import type { BitswapNetworkWantProgressEvents, Network } from './network.js'
|
|
17
19
|
import type { BitswapMessage } from './pb/message.js'
|
|
18
|
-
import type { ComponentLogger,
|
|
20
|
+
import type { ComponentLogger, PeerId, Startable, AbortOptions, Libp2p, TypedEventTarget } from '@libp2p/interface'
|
|
19
21
|
import type { Logger } from '@libp2p/logger'
|
|
20
22
|
import type { PeerMap } from '@libp2p/peer-collections'
|
|
21
23
|
import type { DeferredPromise } from 'p-defer'
|
|
@@ -24,7 +26,7 @@ import type { ProgressOptions } from 'progress-events'
|
|
|
24
26
|
export interface WantListComponents {
|
|
25
27
|
network: Network
|
|
26
28
|
logger: ComponentLogger
|
|
27
|
-
|
|
29
|
+
libp2p: Libp2p
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export interface WantListInit {
|
|
@@ -58,29 +60,9 @@ export interface WantListEntry {
|
|
|
58
60
|
* Whether the remote should tell us if they have the block or not
|
|
59
61
|
*/
|
|
60
62
|
sendDontHave: boolean
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* If this set has members, the want will only be sent to these peers
|
|
64
|
-
*/
|
|
65
|
-
session: PeerSet
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Promises returned from `.wantBlock` for this block
|
|
69
|
-
*/
|
|
70
|
-
blockWantListeners: Array<DeferredPromise<WantBlockResult>>
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Promises returned from `.wantPresence` for this block
|
|
74
|
-
*/
|
|
75
|
-
blockPresenceListeners: Array<DeferredPromise<WantPresenceResult>>
|
|
76
63
|
}
|
|
77
64
|
|
|
78
65
|
export interface WantOptions extends AbortOptions, ProgressOptions<BitswapNetworkWantProgressEvents> {
|
|
79
|
-
/**
|
|
80
|
-
* If set, this WantList entry will only be sent to this peer
|
|
81
|
-
*/
|
|
82
|
-
peerId?: PeerId
|
|
83
|
-
|
|
84
66
|
/**
|
|
85
67
|
* Allow prioritising blocks
|
|
86
68
|
*/
|
|
@@ -108,7 +90,12 @@ export interface WantHaveResult {
|
|
|
108
90
|
|
|
109
91
|
export type WantPresenceResult = WantDontHaveResult | WantHaveResult
|
|
110
92
|
|
|
111
|
-
export
|
|
93
|
+
export interface WantListEvents {
|
|
94
|
+
block: CustomEvent<WantBlockResult>
|
|
95
|
+
presence: CustomEvent<WantPresenceResult>
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export class WantList extends TypedEventEmitter<WantListEvents> implements Startable, TypedEventTarget<WantListEvents> {
|
|
112
99
|
/**
|
|
113
100
|
* Tracks what CIDs we've previously sent to which peers
|
|
114
101
|
*/
|
|
@@ -119,15 +106,19 @@ export class WantList implements Startable {
|
|
|
119
106
|
private readonly sendMessagesDelay: number
|
|
120
107
|
private sendMessagesTimeout?: ReturnType<typeof setTimeout>
|
|
121
108
|
private readonly hashLoader?: MultihashHasherLoader
|
|
109
|
+
private sendingMessages?: DeferredPromise<void>
|
|
122
110
|
|
|
123
111
|
constructor (components: WantListComponents, init: WantListInit = {}) {
|
|
112
|
+
super()
|
|
113
|
+
|
|
114
|
+
setMaxListeners(Infinity, this)
|
|
124
115
|
this.peers = trackedPeerMap({
|
|
125
|
-
name: '
|
|
126
|
-
metrics: components.metrics
|
|
116
|
+
name: 'helia_bitswap_peers',
|
|
117
|
+
metrics: components.libp2p.metrics
|
|
127
118
|
})
|
|
128
119
|
this.wants = trackedMap({
|
|
129
|
-
name: '
|
|
130
|
-
metrics: components.metrics
|
|
120
|
+
name: 'helia_bitswap_wantlist',
|
|
121
|
+
metrics: components.libp2p.metrics
|
|
131
122
|
})
|
|
132
123
|
this.network = components.network
|
|
133
124
|
this.sendMessagesDelay = init.sendMessagesDelay ?? DEFAULT_MESSAGE_SEND_DELAY
|
|
@@ -160,17 +151,10 @@ export class WantList implements Startable {
|
|
|
160
151
|
if (entry == null) {
|
|
161
152
|
entry = {
|
|
162
153
|
cid,
|
|
163
|
-
session: new PeerSet(),
|
|
164
154
|
priority: options.priority ?? 1,
|
|
165
155
|
wantType: options.wantType ?? WantType.WantBlock,
|
|
166
156
|
cancel: false,
|
|
167
|
-
sendDontHave: true
|
|
168
|
-
blockWantListeners: [],
|
|
169
|
-
blockPresenceListeners: []
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (options.peerId != null) {
|
|
173
|
-
entry.session.add(options.peerId)
|
|
157
|
+
sendDontHave: true
|
|
174
158
|
}
|
|
175
159
|
|
|
176
160
|
this.wants.set(cidStr, entry)
|
|
@@ -182,46 +166,41 @@ export class WantList implements Startable {
|
|
|
182
166
|
entry.wantType = WantType.WantBlock
|
|
183
167
|
}
|
|
184
168
|
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
// if the new want is also part of a session, expand the want session to
|
|
188
|
-
// include both sets of peers
|
|
189
|
-
if (options.peerId != null) {
|
|
190
|
-
entry.session.add(options.peerId)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// if the new want is not part of a session, make this want a non-session
|
|
194
|
-
// want - nb. this will cause this WantList entry to be sent to every peer
|
|
195
|
-
// instead of just the ones in the session
|
|
196
|
-
if (options.peerId == null) {
|
|
197
|
-
entry.session.clear()
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// add a promise that will be resolved or rejected when the response arrives
|
|
202
|
-
let deferred: DeferredPromise<WantBlockResult | WantPresenceResult>
|
|
203
|
-
|
|
204
|
-
if (options.wantType === WantType.WantBlock) {
|
|
205
|
-
const p = deferred = pDefer<WantBlockResult>()
|
|
169
|
+
// broadcast changes
|
|
170
|
+
await this.sendMessagesDebounced()
|
|
206
171
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
172
|
+
try {
|
|
173
|
+
if (options.wantType === WantType.WantBlock) {
|
|
174
|
+
const event = await raceEvent<CustomEvent<WantBlockResult>>(this, 'block', options?.signal, {
|
|
175
|
+
filter: (event) => {
|
|
176
|
+
return uint8ArrayEquals(cid.multihash.digest, event.detail.cid.multihash.digest)
|
|
177
|
+
},
|
|
178
|
+
errorMessage: 'Want was aborted'
|
|
179
|
+
})
|
|
210
180
|
|
|
211
|
-
|
|
212
|
-
|
|
181
|
+
return event.detail
|
|
182
|
+
}
|
|
213
183
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
184
|
+
const event = await raceEvent<CustomEvent<WantPresenceResult>>(this, 'presence', options?.signal, {
|
|
185
|
+
filter: (event) => {
|
|
186
|
+
return uint8ArrayEquals(cid.multihash.digest, event.detail.cid.multihash.digest)
|
|
187
|
+
},
|
|
188
|
+
errorMessage: 'Want was aborted'
|
|
189
|
+
})
|
|
217
190
|
|
|
218
|
-
|
|
191
|
+
return event.detail
|
|
192
|
+
} finally {
|
|
193
|
+
if (options.signal?.aborted === true) {
|
|
194
|
+
this.log('want for %c was aborted, cancelling want', cid)
|
|
219
195
|
entry.cancel = true
|
|
196
|
+
// broadcast changes
|
|
197
|
+
await this.sendMessagesDebounced()
|
|
220
198
|
}
|
|
221
|
-
|
|
222
|
-
deferred.reject(new AbortError('Want was aborted'))
|
|
223
199
|
}
|
|
224
|
-
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private async sendMessagesDebounced (): Promise<void> {
|
|
203
|
+
await this.sendingMessages?.promise
|
|
225
204
|
|
|
226
205
|
// broadcast changes
|
|
227
206
|
clearTimeout(this.sendMessagesTimeout)
|
|
@@ -231,77 +210,65 @@ export class WantList implements Startable {
|
|
|
231
210
|
this.log('error sending messages to peers', err)
|
|
232
211
|
})
|
|
233
212
|
}, this.sendMessagesDelay)
|
|
234
|
-
|
|
235
|
-
try {
|
|
236
|
-
return await deferred.promise
|
|
237
|
-
} finally {
|
|
238
|
-
// remove listener
|
|
239
|
-
options.signal?.removeEventListener('abort', abortListener)
|
|
240
|
-
// remove deferred promise
|
|
241
|
-
if (options.wantType === WantType.WantBlock) {
|
|
242
|
-
entry.blockWantListeners = entry.blockWantListeners.filter(recipient => recipient !== deferred)
|
|
243
|
-
} else {
|
|
244
|
-
entry.blockPresenceListeners = entry.blockPresenceListeners.filter(recipient => recipient !== deferred)
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
213
|
}
|
|
248
214
|
|
|
249
215
|
private async sendMessages (): Promise<void> {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
)
|
|
216
|
+
this.sendingMessages = pDefer()
|
|
217
|
+
|
|
218
|
+
await Promise.all(
|
|
219
|
+
[...this.peers.entries()].map(async ([peerId, sentWants]) => {
|
|
220
|
+
const sent = new Set<string>()
|
|
221
|
+
const message: Partial<BitswapMessage> = {
|
|
222
|
+
wantlist: {
|
|
223
|
+
full: false,
|
|
224
|
+
entries: pipe(
|
|
225
|
+
this.wants.entries(),
|
|
226
|
+
(source) => filter(source, ([key, entry]) => {
|
|
227
|
+
const sentPreviously = sentWants.has(key)
|
|
228
|
+
|
|
229
|
+
// don't cancel if we've not sent it to them before
|
|
230
|
+
if (entry.cancel) {
|
|
231
|
+
return sentPreviously
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// only send if we've not sent it to them before
|
|
235
|
+
return !sentPreviously
|
|
236
|
+
}),
|
|
237
|
+
(source) => map(source, ([key, entry]) => {
|
|
238
|
+
sent.add(key)
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
cid: entry.cid.bytes,
|
|
242
|
+
priority: entry.priority,
|
|
243
|
+
wantType: entry.wantType,
|
|
244
|
+
cancel: entry.cancel,
|
|
245
|
+
sendDontHave: entry.sendDontHave
|
|
246
|
+
}
|
|
247
|
+
}),
|
|
248
|
+
(source) => all(source)
|
|
249
|
+
)
|
|
250
|
+
}
|
|
286
251
|
}
|
|
287
|
-
}
|
|
288
252
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
253
|
+
if (message.wantlist?.entries.length === 0) {
|
|
254
|
+
return
|
|
255
|
+
}
|
|
292
256
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
257
|
+
// add message to send queue
|
|
258
|
+
try {
|
|
259
|
+
await this.network.sendMessage(peerId, message)
|
|
296
260
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
261
|
+
// update list of messages sent to remote
|
|
262
|
+
for (const key of sent) {
|
|
263
|
+
sentWants.add(key)
|
|
264
|
+
}
|
|
265
|
+
} catch (err: any) {
|
|
266
|
+
this.log.error('error sending full wantlist to new peer', err)
|
|
300
267
|
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
268
|
+
})
|
|
269
|
+
).catch(err => {
|
|
270
|
+
this.log.error('error sending messages', err)
|
|
271
|
+
})
|
|
305
272
|
|
|
306
273
|
// queued all message sends, remove cancelled wants from wantlist and sent
|
|
307
274
|
// wants
|
|
@@ -314,6 +281,8 @@ export class WantList implements Startable {
|
|
|
314
281
|
}
|
|
315
282
|
}
|
|
316
283
|
}
|
|
284
|
+
|
|
285
|
+
this.sendingMessages.resolve()
|
|
317
286
|
}
|
|
318
287
|
|
|
319
288
|
has (cid: CID): boolean {
|
|
@@ -324,38 +293,28 @@ export class WantList implements Startable {
|
|
|
324
293
|
/**
|
|
325
294
|
* Add a CID to the wantlist
|
|
326
295
|
*/
|
|
327
|
-
async
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
full: false,
|
|
339
|
-
entries: [{
|
|
340
|
-
cid: cid.bytes,
|
|
341
|
-
sendDontHave: true,
|
|
342
|
-
wantType: WantType.WantHave,
|
|
343
|
-
priority: 1
|
|
344
|
-
}]
|
|
345
|
-
}
|
|
346
|
-
})
|
|
347
|
-
} catch (err) {
|
|
348
|
-
// sending failed, remove them as a peer
|
|
349
|
-
this.peers.delete(options.peerId)
|
|
350
|
-
|
|
351
|
-
throw err
|
|
296
|
+
async wantSessionPresence (cid: CID, peerId: PeerId, options: WantOptions = {}): Promise<WantPresenceResult> {
|
|
297
|
+
// sending WantHave directly to peer
|
|
298
|
+
await this.network.sendMessage(peerId, {
|
|
299
|
+
wantlist: {
|
|
300
|
+
full: false,
|
|
301
|
+
entries: [{
|
|
302
|
+
cid: cid.bytes,
|
|
303
|
+
sendDontHave: true,
|
|
304
|
+
wantType: WantType.WantHave,
|
|
305
|
+
priority: 1
|
|
306
|
+
}]
|
|
352
307
|
}
|
|
353
|
-
}
|
|
308
|
+
})
|
|
354
309
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
310
|
+
// wait for peer response
|
|
311
|
+
const event = await raceEvent<CustomEvent<WantHaveResult | WantDontHaveResult>>(this, 'presence', options.signal, {
|
|
312
|
+
filter: (event) => {
|
|
313
|
+
return peerId.equals(event.detail.sender) && uint8ArrayEquals(cid.multihash.digest, event.detail.cid.multihash.digest)
|
|
314
|
+
}
|
|
358
315
|
})
|
|
316
|
+
|
|
317
|
+
return event.detail
|
|
359
318
|
}
|
|
360
319
|
|
|
361
320
|
/**
|
|
@@ -368,15 +327,56 @@ export class WantList implements Startable {
|
|
|
368
327
|
})
|
|
369
328
|
}
|
|
370
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Add a CID to the wantlist
|
|
332
|
+
*/
|
|
333
|
+
async wantSessionBlock (cid: CID, peerId: PeerId, options: WantOptions = {}): Promise<WantPresenceResult> {
|
|
334
|
+
// sending WantBlockResult directly to peer
|
|
335
|
+
await this.network.sendMessage(peerId, {
|
|
336
|
+
wantlist: {
|
|
337
|
+
full: false,
|
|
338
|
+
entries: [{
|
|
339
|
+
cid: cid.bytes,
|
|
340
|
+
sendDontHave: true,
|
|
341
|
+
wantType: WantType.WantBlock,
|
|
342
|
+
priority: 1
|
|
343
|
+
}]
|
|
344
|
+
}
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
// wait for peer response
|
|
348
|
+
const event = await raceEvent<CustomEvent<WantPresenceResult>>(this, 'presence', options.signal, {
|
|
349
|
+
filter: (event) => {
|
|
350
|
+
return peerId.equals(event.detail.sender) && uint8ArrayEquals(cid.multihash.digest, event.detail.cid.multihash.digest)
|
|
351
|
+
}
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
return event.detail
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Invoked when a block has been received from an external source
|
|
359
|
+
*/
|
|
360
|
+
async receivedBlock (cid: CID, options: ProgressOptions<BitswapNotifyProgressEvents> & AbortOptions): Promise<void> {
|
|
361
|
+
const cidStr = uint8ArrayToString(cid.multihash.bytes, 'base64')
|
|
362
|
+
|
|
363
|
+
const entry = this.wants.get(cidStr)
|
|
364
|
+
|
|
365
|
+
if (entry == null) {
|
|
366
|
+
return
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
entry.cancel = true
|
|
370
|
+
|
|
371
|
+
await this.sendMessagesDebounced()
|
|
372
|
+
}
|
|
373
|
+
|
|
371
374
|
/**
|
|
372
375
|
* Invoked when a message is received from a bitswap peer
|
|
373
376
|
*/
|
|
374
377
|
private async receiveMessage (sender: PeerId, message: BitswapMessage): Promise<void> {
|
|
375
378
|
this.log('received message from %p', sender)
|
|
376
|
-
|
|
377
|
-
// blocks received
|
|
378
|
-
const blockResults: WantBlockResult[] = []
|
|
379
|
-
const presenceResults: WantPresenceResult[] = []
|
|
379
|
+
let blocksCancelled = false
|
|
380
380
|
|
|
381
381
|
// process blocks
|
|
382
382
|
for (const block of message.blocks) {
|
|
@@ -384,7 +384,6 @@ export class WantList implements Startable {
|
|
|
384
384
|
continue
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
this.log('received block')
|
|
388
387
|
const values = vd(block.prefix)
|
|
389
388
|
const cidVersion = values[0]
|
|
390
389
|
const multicodec = values[1]
|
|
@@ -403,66 +402,55 @@ export class WantList implements Startable {
|
|
|
403
402
|
|
|
404
403
|
this.log('received block from %p for %c', sender, cid)
|
|
405
404
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
presenceResults.push({
|
|
413
|
-
sender,
|
|
414
|
-
cid,
|
|
415
|
-
has: true
|
|
405
|
+
this.safeDispatchEvent<WantBlockResult>('block', {
|
|
406
|
+
detail: {
|
|
407
|
+
sender,
|
|
408
|
+
cid,
|
|
409
|
+
block: block.data
|
|
410
|
+
}
|
|
416
411
|
})
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// process block presences
|
|
420
|
-
for (const { cid: cidBytes, type } of message.blockPresences) {
|
|
421
|
-
const cid = CID.decode(cidBytes)
|
|
422
|
-
|
|
423
|
-
this.log('received %s from %p for %c', type, sender, cid)
|
|
424
412
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
413
|
+
this.safeDispatchEvent<WantHaveResult | WantDontHaveResult>('presence', {
|
|
414
|
+
detail: {
|
|
415
|
+
sender,
|
|
416
|
+
cid,
|
|
417
|
+
has: true,
|
|
418
|
+
block: block.data
|
|
419
|
+
}
|
|
429
420
|
})
|
|
430
|
-
}
|
|
431
421
|
|
|
432
|
-
|
|
433
|
-
const cidStr = uint8ArrayToString(result.cid.multihash.bytes, 'base64')
|
|
422
|
+
const cidStr = uint8ArrayToString(cid.multihash.bytes, 'base64')
|
|
434
423
|
const entry = this.wants.get(cidStr)
|
|
435
424
|
|
|
436
425
|
if (entry == null) {
|
|
437
426
|
return
|
|
438
427
|
}
|
|
439
428
|
|
|
440
|
-
const recipients = entry.blockWantListeners
|
|
441
|
-
entry.blockWantListeners = []
|
|
442
|
-
recipients.forEach((p) => {
|
|
443
|
-
p.resolve(result)
|
|
444
|
-
})
|
|
445
|
-
|
|
446
429
|
// since we received the block, flip the cancel flag to send cancels to
|
|
447
430
|
// any peers on the next message sending iteration, this will remove it
|
|
448
431
|
// from the internal want list
|
|
449
432
|
entry.cancel = true
|
|
433
|
+
blocksCancelled = true
|
|
450
434
|
}
|
|
451
435
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const
|
|
436
|
+
// process block presences
|
|
437
|
+
for (const { cid: cidBytes, type } of message.blockPresences) {
|
|
438
|
+
const cid = CID.decode(cidBytes)
|
|
455
439
|
|
|
456
|
-
|
|
457
|
-
return
|
|
458
|
-
}
|
|
440
|
+
this.log('received %s from %p for %c', type, sender, cid)
|
|
459
441
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
442
|
+
this.safeDispatchEvent<WantHaveResult | WantDontHaveResult>('presence', {
|
|
443
|
+
detail: {
|
|
444
|
+
sender,
|
|
445
|
+
cid,
|
|
446
|
+
has: type === BlockPresenceType.HaveBlock
|
|
447
|
+
}
|
|
464
448
|
})
|
|
465
449
|
}
|
|
450
|
+
|
|
451
|
+
if (blocksCancelled) {
|
|
452
|
+
await this.sendMessagesDebounced()
|
|
453
|
+
}
|
|
466
454
|
}
|
|
467
455
|
|
|
468
456
|
/**
|
|
@@ -477,7 +465,6 @@ export class WantList implements Startable {
|
|
|
477
465
|
full: true,
|
|
478
466
|
entries: pipe(
|
|
479
467
|
this.wants.entries(),
|
|
480
|
-
(source) => filter(source, ([key, entry]) => !entry.cancel && (entry.session.size > 0 && !entry.session.has(peerId))),
|
|
481
468
|
(source) => filter(source, ([key, entry]) => !entry.cancel),
|
|
482
469
|
(source) => map(source, ([key, entry]) => {
|
|
483
470
|
sentWants.add(key)
|
|
@@ -525,5 +512,6 @@ export class WantList implements Startable {
|
|
|
525
512
|
|
|
526
513
|
stop (): void {
|
|
527
514
|
this.peers.clear()
|
|
515
|
+
clearTimeout(this.sendMessagesTimeout)
|
|
528
516
|
}
|
|
529
517
|
}
|