hypercore 11.16.2 → 11.17.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/README.md +31 -29
- package/index.js +212 -127
- package/lib/audit.js +17 -6
- package/lib/bit-interlude.js +17 -7
- package/lib/bitfield.js +72 -52
- package/lib/caps.js +5 -1
- package/lib/copy-prologue.js +14 -10
- package/lib/core.js +109 -56
- package/lib/default-encryption.js +14 -28
- package/lib/download.js +10 -10
- package/lib/fully-remote-proof.js +3 -3
- package/lib/hotswap-queue.js +5 -5
- package/lib/info.js +4 -4
- package/lib/merkle-tree.js +143 -104
- package/lib/messages.js +163 -143
- package/lib/multisig.js +19 -12
- package/lib/mutex.js +9 -7
- package/lib/receiver-queue.js +6 -6
- package/lib/remote-bitfield.js +30 -32
- package/lib/replicator.js +383 -265
- package/lib/session-state.js +112 -75
- package/lib/streams.js +16 -16
- package/lib/verifier.js +69 -43
- package/package.json +5 -3
package/lib/replicator.js
CHANGED
|
@@ -30,14 +30,20 @@ const ReceiverQueue = require('./receiver-queue')
|
|
|
30
30
|
const HotswapQueue = require('./hotswap-queue')
|
|
31
31
|
const RemoteBitfield = require('./remote-bitfield')
|
|
32
32
|
const { MerkleTree } = require('./merkle-tree')
|
|
33
|
-
const {
|
|
33
|
+
const {
|
|
34
|
+
REQUEST_CANCELLED,
|
|
35
|
+
REQUEST_TIMEOUT,
|
|
36
|
+
INVALID_CAPABILITY,
|
|
37
|
+
SNAPSHOT_NOT_AVAILABLE,
|
|
38
|
+
ASSERTION
|
|
39
|
+
} = require('hypercore-errors')
|
|
34
40
|
const m = require('./messages')
|
|
35
41
|
const caps = require('./caps')
|
|
36
42
|
|
|
37
43
|
const DEFAULT_MAX_INFLIGHT = [16, 512]
|
|
38
44
|
const SCALE_LATENCY = 50
|
|
39
45
|
const DEFAULT_SEGMENT_SIZE = 256 * 1024 * 8 // 256 KiB in bits
|
|
40
|
-
const NOT_DOWNLOADING_SLACK = 20000 +
|
|
46
|
+
const NOT_DOWNLOADING_SLACK = (20000 + Math.random() * 20000) | 0
|
|
41
47
|
const MAX_PEERS_UPGRADE = 3
|
|
42
48
|
const LAST_BLOCKS = 256
|
|
43
49
|
const MAX_REMOTE_SEGMENTS = 2048
|
|
@@ -57,14 +63,14 @@ const PRIORITY = {
|
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
class Attachable {
|
|
60
|
-
constructor
|
|
66
|
+
constructor(replicator) {
|
|
61
67
|
this.replicator = replicator
|
|
62
68
|
this.resolved = false
|
|
63
69
|
this.processing = false
|
|
64
70
|
this.refs = []
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
attach
|
|
73
|
+
attach(session) {
|
|
68
74
|
const r = {
|
|
69
75
|
context: this,
|
|
70
76
|
session,
|
|
@@ -87,7 +93,7 @@ class Attachable {
|
|
|
87
93
|
return r
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
detach
|
|
96
|
+
detach(r, err = null) {
|
|
91
97
|
if (r.context !== this) return false
|
|
92
98
|
|
|
93
99
|
this._detach(r)
|
|
@@ -97,12 +103,12 @@ class Attachable {
|
|
|
97
103
|
return true
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
_detach
|
|
106
|
+
_detach(r) {
|
|
101
107
|
const rh = this.refs.pop()
|
|
102
108
|
const sh = r.session.pop()
|
|
103
109
|
|
|
104
|
-
if (r.rindex < this.refs.length) this.refs[rh.rindex = r.rindex] = rh
|
|
105
|
-
if (r.sindex < r.session.length) r.session[sh.sindex = r.sindex] = sh
|
|
110
|
+
if (r.rindex < this.refs.length) this.refs[(rh.rindex = r.rindex)] = rh
|
|
111
|
+
if (r.sindex < r.session.length) r.session[(sh.sindex = r.sindex)] = sh
|
|
106
112
|
|
|
107
113
|
destroyRequestTimeout(r)
|
|
108
114
|
r.context = null
|
|
@@ -110,45 +116,45 @@ class Attachable {
|
|
|
110
116
|
return r
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
gc
|
|
119
|
+
gc() {
|
|
114
120
|
if (this.refs.length === 0 && !this.processing) this._unref()
|
|
115
121
|
}
|
|
116
122
|
|
|
117
|
-
processed
|
|
123
|
+
processed() {
|
|
118
124
|
this.processing = false
|
|
119
125
|
this.gc()
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
_cancel
|
|
128
|
+
_cancel(r, err) {
|
|
123
129
|
r.reject(err || REQUEST_CANCELLED())
|
|
124
130
|
}
|
|
125
131
|
|
|
126
|
-
_unref
|
|
132
|
+
_unref() {
|
|
127
133
|
// overwrite me
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
resolve
|
|
136
|
+
resolve(val) {
|
|
131
137
|
this.resolved = true
|
|
132
138
|
while (this.refs.length > 0) {
|
|
133
139
|
this._detach(this.refs[this.refs.length - 1]).resolve(val)
|
|
134
140
|
}
|
|
135
141
|
}
|
|
136
142
|
|
|
137
|
-
reject
|
|
143
|
+
reject(err) {
|
|
138
144
|
this.resolved = true
|
|
139
145
|
while (this.refs.length > 0) {
|
|
140
146
|
this._detach(this.refs[this.refs.length - 1]).reject(err)
|
|
141
147
|
}
|
|
142
148
|
}
|
|
143
149
|
|
|
144
|
-
setTimeout
|
|
150
|
+
setTimeout(r, ms) {
|
|
145
151
|
destroyRequestTimeout(r)
|
|
146
152
|
r.timeout = setTimeout(onrequesttimeout, ms, r)
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
class BlockRequest extends Attachable {
|
|
151
|
-
constructor
|
|
157
|
+
constructor(replicator, tracker, index, priority) {
|
|
152
158
|
super(replicator)
|
|
153
159
|
|
|
154
160
|
this.index = index
|
|
@@ -159,7 +165,7 @@ class BlockRequest extends Attachable {
|
|
|
159
165
|
this.tracker = tracker
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
_unref
|
|
168
|
+
_unref() {
|
|
163
169
|
this.queued = false
|
|
164
170
|
|
|
165
171
|
for (const req of this.inflight) {
|
|
@@ -172,7 +178,7 @@ class BlockRequest extends Attachable {
|
|
|
172
178
|
}
|
|
173
179
|
|
|
174
180
|
class RangeRequest extends Attachable {
|
|
175
|
-
constructor
|
|
181
|
+
constructor(replicator, ranges, start, end, linear, ifAvailable, blocks) {
|
|
176
182
|
super(replicator)
|
|
177
183
|
|
|
178
184
|
this.start = start
|
|
@@ -187,20 +193,20 @@ class RangeRequest extends Attachable {
|
|
|
187
193
|
this.userEnd = end
|
|
188
194
|
}
|
|
189
195
|
|
|
190
|
-
_unref
|
|
196
|
+
_unref() {
|
|
191
197
|
const i = this.ranges.indexOf(this)
|
|
192
198
|
if (i === -1) return
|
|
193
199
|
const h = this.ranges.pop()
|
|
194
200
|
if (i < this.ranges.length) this.ranges[i] = h
|
|
195
201
|
}
|
|
196
202
|
|
|
197
|
-
_cancel
|
|
203
|
+
_cancel(r) {
|
|
198
204
|
r.resolve(false)
|
|
199
205
|
}
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
class UpgradeRequest extends Attachable {
|
|
203
|
-
constructor
|
|
209
|
+
constructor(replicator, fork, length) {
|
|
204
210
|
super(replicator)
|
|
205
211
|
|
|
206
212
|
this.fork = fork
|
|
@@ -208,18 +214,18 @@ class UpgradeRequest extends Attachable {
|
|
|
208
214
|
this.inflight = []
|
|
209
215
|
}
|
|
210
216
|
|
|
211
|
-
_unref
|
|
217
|
+
_unref() {
|
|
212
218
|
if (this.replicator.eagerUpgrade === true || this.inflight.length > 0) return
|
|
213
219
|
this.replicator._upgrade = null
|
|
214
220
|
}
|
|
215
221
|
|
|
216
|
-
_cancel
|
|
222
|
+
_cancel(r) {
|
|
217
223
|
r.resolve(false)
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
class SeekRequest extends Attachable {
|
|
222
|
-
constructor
|
|
228
|
+
constructor(replicator, seeks, seeker) {
|
|
223
229
|
super(replicator)
|
|
224
230
|
|
|
225
231
|
this.seeker = seeker
|
|
@@ -227,7 +233,7 @@ class SeekRequest extends Attachable {
|
|
|
227
233
|
this.seeks = seeks
|
|
228
234
|
}
|
|
229
235
|
|
|
230
|
-
_unref
|
|
236
|
+
_unref() {
|
|
231
237
|
if (this.inflight.length > 0) return
|
|
232
238
|
const i = this.seeks.indexOf(this)
|
|
233
239
|
if (i === -1) return
|
|
@@ -237,23 +243,23 @@ class SeekRequest extends Attachable {
|
|
|
237
243
|
}
|
|
238
244
|
|
|
239
245
|
class InflightTracker {
|
|
240
|
-
constructor
|
|
246
|
+
constructor() {
|
|
241
247
|
this._requests = []
|
|
242
248
|
this._free = []
|
|
243
249
|
this._active = 0
|
|
244
250
|
}
|
|
245
251
|
|
|
246
|
-
get idle
|
|
252
|
+
get idle() {
|
|
247
253
|
return this._active === 0
|
|
248
254
|
}
|
|
249
255
|
|
|
250
|
-
*
|
|
256
|
+
*[Symbol.iterator]() {
|
|
251
257
|
for (const req of this._requests) {
|
|
252
258
|
if (req !== null) yield req
|
|
253
259
|
}
|
|
254
260
|
}
|
|
255
261
|
|
|
256
|
-
add
|
|
262
|
+
add(req) {
|
|
257
263
|
const id = this._free.length ? this._free.pop() : this._requests.push(null)
|
|
258
264
|
req.id = id
|
|
259
265
|
this._requests[id - 1] = req
|
|
@@ -261,45 +267,45 @@ class InflightTracker {
|
|
|
261
267
|
return req
|
|
262
268
|
}
|
|
263
269
|
|
|
264
|
-
get
|
|
270
|
+
get(id) {
|
|
265
271
|
return id <= this._requests.length ? this._requests[id - 1] : null
|
|
266
272
|
}
|
|
267
273
|
|
|
268
|
-
remove
|
|
274
|
+
remove(id, roundtrip) {
|
|
269
275
|
if (id > this._requests.length) return
|
|
270
276
|
if (this._requests[id - 1]) this._active--
|
|
271
277
|
this._requests[id - 1] = null
|
|
272
278
|
if (roundtrip === true) this._free.push(id)
|
|
273
279
|
}
|
|
274
280
|
|
|
275
|
-
reusable
|
|
281
|
+
reusable(id) {
|
|
276
282
|
this._free.push(id)
|
|
277
283
|
}
|
|
278
284
|
}
|
|
279
285
|
|
|
280
286
|
class BlockTracker {
|
|
281
|
-
constructor
|
|
287
|
+
constructor(replicator) {
|
|
282
288
|
this._replicator = replicator
|
|
283
289
|
this._map = new Map()
|
|
284
290
|
}
|
|
285
291
|
|
|
286
|
-
[Symbol.iterator]
|
|
292
|
+
[Symbol.iterator]() {
|
|
287
293
|
return this._map.values()
|
|
288
294
|
}
|
|
289
295
|
|
|
290
|
-
isEmpty
|
|
296
|
+
isEmpty() {
|
|
291
297
|
return this._map.size === 0
|
|
292
298
|
}
|
|
293
299
|
|
|
294
|
-
has
|
|
300
|
+
has(index) {
|
|
295
301
|
return this._map.has(index)
|
|
296
302
|
}
|
|
297
303
|
|
|
298
|
-
get
|
|
304
|
+
get(index) {
|
|
299
305
|
return this._map.get(index) || null
|
|
300
306
|
}
|
|
301
307
|
|
|
302
|
-
add
|
|
308
|
+
add(index, priority) {
|
|
303
309
|
let b = this._map.get(index)
|
|
304
310
|
if (b) return b
|
|
305
311
|
|
|
@@ -309,7 +315,7 @@ class BlockTracker {
|
|
|
309
315
|
return b
|
|
310
316
|
}
|
|
311
317
|
|
|
312
|
-
remove
|
|
318
|
+
remove(index) {
|
|
313
319
|
const b = this.get(index)
|
|
314
320
|
this._map.delete(index)
|
|
315
321
|
return b
|
|
@@ -317,12 +323,12 @@ class BlockTracker {
|
|
|
317
323
|
}
|
|
318
324
|
|
|
319
325
|
class RoundtripQueue {
|
|
320
|
-
constructor
|
|
326
|
+
constructor() {
|
|
321
327
|
this.queue = []
|
|
322
328
|
this.tick = 0
|
|
323
329
|
}
|
|
324
330
|
|
|
325
|
-
clear
|
|
331
|
+
clear() {
|
|
326
332
|
const ids = new Array(this.queue.length)
|
|
327
333
|
for (let i = 0; i < ids.length; i++) {
|
|
328
334
|
ids[i] = this.queue[i][1]
|
|
@@ -333,11 +339,11 @@ class RoundtripQueue {
|
|
|
333
339
|
return ids
|
|
334
340
|
}
|
|
335
341
|
|
|
336
|
-
add
|
|
342
|
+
add(id) {
|
|
337
343
|
this.queue.push([++this.tick, id])
|
|
338
344
|
}
|
|
339
345
|
|
|
340
|
-
flush
|
|
346
|
+
flush(tick) {
|
|
341
347
|
let flushed = null
|
|
342
348
|
|
|
343
349
|
for (let i = 0; i < this.queue.length; i++) {
|
|
@@ -352,14 +358,14 @@ class RoundtripQueue {
|
|
|
352
358
|
}
|
|
353
359
|
|
|
354
360
|
class ProofRequest {
|
|
355
|
-
constructor
|
|
361
|
+
constructor(msg, proof, block, manifest) {
|
|
356
362
|
this.msg = msg
|
|
357
363
|
this.proof = proof
|
|
358
364
|
this.block = block
|
|
359
365
|
this.manifest = manifest
|
|
360
366
|
}
|
|
361
367
|
|
|
362
|
-
async fulfill
|
|
368
|
+
async fulfill() {
|
|
363
369
|
if (this.proof === null) return null
|
|
364
370
|
|
|
365
371
|
const [proof, block] = await Promise.all([this.proof.settle(), this.block])
|
|
@@ -374,7 +380,7 @@ class ProofRequest {
|
|
|
374
380
|
}
|
|
375
381
|
|
|
376
382
|
class Peer {
|
|
377
|
-
constructor
|
|
383
|
+
constructor(replicator, protomux, channel, inflightRange) {
|
|
378
384
|
this.core = replicator.core
|
|
379
385
|
this.replicator = replicator
|
|
380
386
|
this.stream = protomux.stream
|
|
@@ -466,34 +472,41 @@ class Peer {
|
|
|
466
472
|
replicator._active++
|
|
467
473
|
}
|
|
468
474
|
|
|
469
|
-
get remoteContiguousLength
|
|
475
|
+
get remoteContiguousLength() {
|
|
470
476
|
return this.remoteBitfield.findFirst(false, this._remoteContiguousLength)
|
|
471
477
|
}
|
|
472
478
|
|
|
473
|
-
getMaxInflight
|
|
479
|
+
getMaxInflight() {
|
|
474
480
|
const stream = this.stream.rawStream
|
|
475
481
|
if (!stream.udx) return Math.min(this.inflightRange[1], this.inflightRange[0] * 3)
|
|
476
482
|
|
|
477
|
-
const scale =
|
|
478
|
-
|
|
483
|
+
const scale =
|
|
484
|
+
stream.rtt <= SCALE_LATENCY
|
|
485
|
+
? 1
|
|
486
|
+
: (stream.rtt / SCALE_LATENCY) * Math.min(1, 2 / this.replicator.peers.length)
|
|
487
|
+
return Math.max(
|
|
488
|
+
this.inflightRange[0],
|
|
489
|
+
Math.round(Math.min(this.inflightRange[1], this.inflightRange[0] * scale))
|
|
490
|
+
)
|
|
479
491
|
}
|
|
480
492
|
|
|
481
|
-
getMaxHotswapInflight
|
|
493
|
+
getMaxHotswapInflight() {
|
|
482
494
|
const inf = this.getMaxInflight()
|
|
483
495
|
return Math.max(16, inf / 2)
|
|
484
496
|
}
|
|
485
497
|
|
|
486
|
-
signalUpgrade
|
|
487
|
-
if (this.fullyDownloadedSignaled && !this.replicator.fullyDownloaded())
|
|
498
|
+
signalUpgrade() {
|
|
499
|
+
if (this.fullyDownloadedSignaled && !this.replicator.fullyDownloaded())
|
|
500
|
+
this.fullyDownloadedSignaled = false
|
|
488
501
|
if (this._shouldUpdateCanUpgrade() === true) this._updateCanUpgradeAndSync()
|
|
489
502
|
else this.sendSync()
|
|
490
503
|
}
|
|
491
504
|
|
|
492
|
-
_markInflight
|
|
505
|
+
_markInflight(index) {
|
|
493
506
|
this.missingBlocks.set(index, false)
|
|
494
507
|
}
|
|
495
508
|
|
|
496
|
-
broadcastRange
|
|
509
|
+
broadcastRange(start, length, drop) {
|
|
497
510
|
if (!this.isActive()) return
|
|
498
511
|
|
|
499
512
|
if (drop) this._unclearLocalRange(start, length)
|
|
@@ -502,7 +515,13 @@ class Peer {
|
|
|
502
515
|
const i = Math.floor(start / DEFAULT_SEGMENT_SIZE)
|
|
503
516
|
const contig = this.core.header.hints.contiguousLength === this.core.state.length
|
|
504
517
|
|
|
505
|
-
if (
|
|
518
|
+
if (
|
|
519
|
+
start + LAST_BLOCKS < this.core.state.length &&
|
|
520
|
+
!this.remoteSegmentsWanted.has(i) &&
|
|
521
|
+
!drop &&
|
|
522
|
+
!contig
|
|
523
|
+
)
|
|
524
|
+
return
|
|
506
525
|
|
|
507
526
|
let force = false
|
|
508
527
|
if (contig && !drop) {
|
|
@@ -537,20 +556,21 @@ class Peer {
|
|
|
537
556
|
incrementTx(this.stats.wireRange, this.replicator.stats.wireRange)
|
|
538
557
|
}
|
|
539
558
|
|
|
540
|
-
extension
|
|
559
|
+
extension(name, message) {
|
|
541
560
|
this.wireExtension.send({ name: name === this.lastExtensionSent ? '' : name, message })
|
|
542
561
|
incrementTx(this.stats.wireExtension, this.replicator.stats.wireExtension)
|
|
543
562
|
this.lastExtensionSent = name
|
|
544
563
|
}
|
|
545
564
|
|
|
546
|
-
onextension
|
|
565
|
+
onextension(message) {
|
|
547
566
|
const name = message.name || this.lastExtensionRecv
|
|
548
567
|
this.lastExtensionRecv = name
|
|
549
568
|
const ext = this.extensions.get(name)
|
|
550
|
-
if (ext)
|
|
569
|
+
if (ext)
|
|
570
|
+
ext._onmessage({ start: 0, end: message.message.byteLength, buffer: message.message }, this)
|
|
551
571
|
}
|
|
552
572
|
|
|
553
|
-
sendSync
|
|
573
|
+
sendSync() {
|
|
554
574
|
if (this.syncsProcessing !== 0) {
|
|
555
575
|
this.needsSync = true
|
|
556
576
|
return
|
|
@@ -574,10 +594,15 @@ class Peer {
|
|
|
574
594
|
incrementTx(this.stats.wireSync, this.replicator.stats.wireSync)
|
|
575
595
|
}
|
|
576
596
|
|
|
577
|
-
onopen
|
|
578
|
-
const expected = caps.replicate(
|
|
597
|
+
onopen({ seeks, capability }) {
|
|
598
|
+
const expected = caps.replicate(
|
|
599
|
+
this.stream.isInitiator === false,
|
|
600
|
+
this.core.key,
|
|
601
|
+
this.stream.handshakeHash
|
|
602
|
+
)
|
|
579
603
|
|
|
580
|
-
if (b4a.equals(capability, expected) !== true) {
|
|
604
|
+
if (b4a.equals(capability, expected) !== true) {
|
|
605
|
+
// TODO: change this to a rejection instead, less leakage
|
|
581
606
|
throw INVALID_CAPABILITY('Remote sent an invalid replication capability')
|
|
582
607
|
}
|
|
583
608
|
|
|
@@ -606,12 +631,16 @@ class Peer {
|
|
|
606
631
|
this.core.checkIfIdle()
|
|
607
632
|
}
|
|
608
633
|
|
|
609
|
-
onclose
|
|
634
|
+
onclose(isRemote) {
|
|
610
635
|
// we might have signalled to the remote that we are done (ie not downloading) and the remote might agree on that
|
|
611
636
|
// if that happens, the channel might be closed by the remote. if so just renegotiate it.
|
|
612
637
|
// TODO: add a CLOSE_REASON to mux to we can make this cleaner...
|
|
613
|
-
const reopen =
|
|
614
|
-
|
|
638
|
+
const reopen =
|
|
639
|
+
isRemote === true &&
|
|
640
|
+
this.remoteOpened === true &&
|
|
641
|
+
this.remoteDownloading === false &&
|
|
642
|
+
this.remoteUploading === true &&
|
|
643
|
+
this.replicator.downloading === true
|
|
615
644
|
|
|
616
645
|
if (this.remoteOpened === false) {
|
|
617
646
|
this.replicator._ifAvailable--
|
|
@@ -635,7 +664,7 @@ class Peer {
|
|
|
635
664
|
}
|
|
636
665
|
}
|
|
637
666
|
|
|
638
|
-
closeIfIdle
|
|
667
|
+
closeIfIdle() {
|
|
639
668
|
if (this.remoteDownloading === false && this.replicator.isDownloading() === false) {
|
|
640
669
|
// idling, shut it down...
|
|
641
670
|
this.channel.close()
|
|
@@ -645,7 +674,7 @@ class Peer {
|
|
|
645
674
|
return false
|
|
646
675
|
}
|
|
647
676
|
|
|
648
|
-
async onsync
|
|
677
|
+
async onsync({ fork, length, remoteLength, canUpgrade, uploading, downloading, hasManifest }) {
|
|
649
678
|
const lengthChanged = length !== this.remoteLength
|
|
650
679
|
const sameFork = fork === this.core.state.fork
|
|
651
680
|
|
|
@@ -668,9 +697,10 @@ class Peer {
|
|
|
668
697
|
if (this.replicator._addUpgradeMaybe() !== null) this._update()
|
|
669
698
|
}
|
|
670
699
|
|
|
671
|
-
const upgrade =
|
|
672
|
-
|
|
673
|
-
|
|
700
|
+
const upgrade =
|
|
701
|
+
lengthChanged === false || sameFork === false
|
|
702
|
+
? this.canUpgrade && sameFork
|
|
703
|
+
: await this._canUpgrade(length, fork)
|
|
674
704
|
|
|
675
705
|
if (length === this.remoteLength && fork === this.core.state.fork) {
|
|
676
706
|
this.canUpgrade = upgrade
|
|
@@ -682,28 +712,37 @@ class Peer {
|
|
|
682
712
|
|
|
683
713
|
if (--this.syncsProcessing !== 0) return // ie not latest
|
|
684
714
|
|
|
685
|
-
if (
|
|
715
|
+
if (
|
|
716
|
+
this.needsSync === true ||
|
|
717
|
+
(this.core.state.fork === this.remoteFork && this.core.state.length > this.remoteLength)
|
|
718
|
+
) {
|
|
686
719
|
this.signalUpgrade()
|
|
687
720
|
}
|
|
688
721
|
|
|
689
722
|
this._update()
|
|
690
723
|
}
|
|
691
724
|
|
|
692
|
-
_shouldUpdateCanUpgrade
|
|
693
|
-
return
|
|
725
|
+
_shouldUpdateCanUpgrade() {
|
|
726
|
+
return (
|
|
727
|
+
this.core.state.fork === this.remoteFork &&
|
|
694
728
|
this.core.state.length > this.remoteLength &&
|
|
695
729
|
this.canUpgrade === false &&
|
|
696
730
|
this.syncsProcessing === 0
|
|
731
|
+
)
|
|
697
732
|
}
|
|
698
733
|
|
|
699
|
-
async _updateCanUpgradeAndSync
|
|
734
|
+
async _updateCanUpgradeAndSync() {
|
|
700
735
|
const { length, fork } = this.core.state
|
|
701
736
|
|
|
702
737
|
const remoteLength = this.remoteLength
|
|
703
738
|
const remoteFork = this.remoteFork
|
|
704
739
|
const canUpgrade = await this._canUpgrade(this.remoteLength, this.remoteFork)
|
|
705
740
|
|
|
706
|
-
if (
|
|
741
|
+
if (
|
|
742
|
+
this.syncsProcessing > 0 ||
|
|
743
|
+
length !== this.core.state.length ||
|
|
744
|
+
fork !== this.core.state.fork
|
|
745
|
+
) {
|
|
707
746
|
return
|
|
708
747
|
}
|
|
709
748
|
if (remoteLength !== this.remoteLength || remoteFork !== this.remoteFork) {
|
|
@@ -723,7 +762,7 @@ class Peer {
|
|
|
723
762
|
}
|
|
724
763
|
|
|
725
764
|
// Safe to call in the background - never fails
|
|
726
|
-
async _canUpgrade
|
|
765
|
+
async _canUpgrade(remoteLength, remoteFork) {
|
|
727
766
|
if (remoteFork !== this.core.state.fork) return false
|
|
728
767
|
|
|
729
768
|
if (remoteLength === 0) return true
|
|
@@ -741,7 +780,7 @@ class Peer {
|
|
|
741
780
|
}
|
|
742
781
|
}
|
|
743
782
|
|
|
744
|
-
async _getProof
|
|
783
|
+
async _getProof(batch, msg) {
|
|
745
784
|
let block = null
|
|
746
785
|
|
|
747
786
|
if (msg.block) {
|
|
@@ -755,7 +794,7 @@ class Peer {
|
|
|
755
794
|
block.catch(noop)
|
|
756
795
|
}
|
|
757
796
|
|
|
758
|
-
const manifest =
|
|
797
|
+
const manifest = msg.manifest && !this.core.compat ? this.core.header.manifest : null
|
|
759
798
|
|
|
760
799
|
try {
|
|
761
800
|
const proof = await MerkleTree.proof(this.core.state, batch, msg)
|
|
@@ -772,7 +811,7 @@ class Peer {
|
|
|
772
811
|
}
|
|
773
812
|
}
|
|
774
813
|
|
|
775
|
-
async onrequest
|
|
814
|
+
async onrequest(msg) {
|
|
776
815
|
const size = this.remoteRequests.size
|
|
777
816
|
this.remoteRequests.set(msg.id, msg)
|
|
778
817
|
|
|
@@ -792,25 +831,30 @@ class Peer {
|
|
|
792
831
|
await this._handleRequest(msg)
|
|
793
832
|
}
|
|
794
833
|
|
|
795
|
-
oncancel
|
|
834
|
+
oncancel(msg) {
|
|
796
835
|
this._cancel(msg.request)
|
|
797
836
|
}
|
|
798
837
|
|
|
799
|
-
_cancel
|
|
838
|
+
_cancel(id) {
|
|
800
839
|
this.remoteRequests.delete(id)
|
|
801
840
|
this.receiverQueue.delete(id)
|
|
802
841
|
}
|
|
803
842
|
|
|
804
|
-
ondrain
|
|
843
|
+
ondrain() {
|
|
805
844
|
return this._handleRequests()
|
|
806
845
|
}
|
|
807
846
|
|
|
808
|
-
async _handleRequests
|
|
847
|
+
async _handleRequests() {
|
|
809
848
|
if (this.receiverBusy || this.replicator.destroyed) return
|
|
810
849
|
this.receiverBusy = true
|
|
811
850
|
this.protomux.cork()
|
|
812
851
|
|
|
813
|
-
while (
|
|
852
|
+
while (
|
|
853
|
+
this.remoteOpened &&
|
|
854
|
+
this.protomux.drained &&
|
|
855
|
+
this.receiverQueue.length > 0 &&
|
|
856
|
+
!this.removed
|
|
857
|
+
) {
|
|
814
858
|
const msg = this.receiverQueue.shift()
|
|
815
859
|
await this._handleRequest(msg)
|
|
816
860
|
}
|
|
@@ -819,13 +863,14 @@ class Peer {
|
|
|
819
863
|
this.receiverBusy = false
|
|
820
864
|
}
|
|
821
865
|
|
|
822
|
-
async _handleRequest
|
|
866
|
+
async _handleRequest(msg) {
|
|
823
867
|
const batch = this.core.storage.read()
|
|
824
868
|
|
|
825
869
|
// TODO: could still be answerable if (index, fork) is an ancestor of the current fork
|
|
826
|
-
const req =
|
|
827
|
-
|
|
828
|
-
|
|
870
|
+
const req =
|
|
871
|
+
msg.fork === this.core.state.fork
|
|
872
|
+
? await this._getProof(batch, msg)
|
|
873
|
+
: new ProofRequest(msg, null, null, null)
|
|
829
874
|
|
|
830
875
|
if (req === null) {
|
|
831
876
|
this.wireNoData.send({ request: msg.id, reason: INVALID_REQUEST })
|
|
@@ -837,7 +882,7 @@ class Peer {
|
|
|
837
882
|
await this._fulfillRequest(req)
|
|
838
883
|
}
|
|
839
884
|
|
|
840
|
-
async _fulfillRequest
|
|
885
|
+
async _fulfillRequest(req) {
|
|
841
886
|
const proof = await req.fulfill()
|
|
842
887
|
|
|
843
888
|
// if cancelled do not reply
|
|
@@ -855,7 +900,15 @@ class Peer {
|
|
|
855
900
|
if (proof === null) {
|
|
856
901
|
if (req.msg.manifest && this.core.header.manifest) {
|
|
857
902
|
const manifest = this.core.header.manifest
|
|
858
|
-
this.wireData.send({
|
|
903
|
+
this.wireData.send({
|
|
904
|
+
request: req.msg.id,
|
|
905
|
+
fork: this.core.state.fork,
|
|
906
|
+
block: null,
|
|
907
|
+
hash: null,
|
|
908
|
+
seek: null,
|
|
909
|
+
upgrade: null,
|
|
910
|
+
manifest
|
|
911
|
+
})
|
|
859
912
|
incrementTx(this.stats.wireData, this.replicator.stats.wireData)
|
|
860
913
|
return
|
|
861
914
|
}
|
|
@@ -880,7 +933,7 @@ class Peer {
|
|
|
880
933
|
incrementTx(this.stats.wireData, this.replicator.stats.wireData)
|
|
881
934
|
}
|
|
882
935
|
|
|
883
|
-
_cancelRequest
|
|
936
|
+
_cancelRequest(req) {
|
|
884
937
|
if (req.priority === PRIORITY.CANCELLED) return
|
|
885
938
|
// mark as cancelled also and avoid re-entry
|
|
886
939
|
req.priority = PRIORITY.CANCELLED
|
|
@@ -898,7 +951,7 @@ class Peer {
|
|
|
898
951
|
incrementTx(this.stats.wireCancel, this.replicator.stats.wireCancel)
|
|
899
952
|
}
|
|
900
953
|
|
|
901
|
-
_checkIfConflict
|
|
954
|
+
_checkIfConflict() {
|
|
902
955
|
this.paused = true
|
|
903
956
|
|
|
904
957
|
const length = Math.min(this.core.state.length, this.remoteLength)
|
|
@@ -919,7 +972,7 @@ class Peer {
|
|
|
919
972
|
incrementTx(this.stats.wireRequest, this.replicator.stats.wireRequest)
|
|
920
973
|
}
|
|
921
974
|
|
|
922
|
-
async ondata
|
|
975
|
+
async ondata(data) {
|
|
923
976
|
// always allow a fork conflict proof to be sent
|
|
924
977
|
if (data.request === 0 && data.upgrade && data.upgrade.start === 0) {
|
|
925
978
|
if (await this.core.checkConflict(data, this)) return
|
|
@@ -991,7 +1044,7 @@ class Peer {
|
|
|
991
1044
|
}
|
|
992
1045
|
}
|
|
993
1046
|
|
|
994
|
-
onnodata
|
|
1047
|
+
onnodata({ request, reason }) {
|
|
995
1048
|
const req = request > 0 ? this.replicator._inflight.get(request) : null
|
|
996
1049
|
if (req === null || req.peer !== this) return
|
|
997
1050
|
|
|
@@ -999,7 +1052,7 @@ class Peer {
|
|
|
999
1052
|
this.replicator._onnodata(this, req, reason)
|
|
1000
1053
|
}
|
|
1001
1054
|
|
|
1002
|
-
_onrequestroundtrip
|
|
1055
|
+
_onrequestroundtrip(req) {
|
|
1003
1056
|
if (req.priority === PRIORITY.CANCELLED) return
|
|
1004
1057
|
// to avoid re-entry we also just mark it as cancelled
|
|
1005
1058
|
req.priority = PRIORITY.CANCELLED
|
|
@@ -1012,18 +1065,18 @@ class Peer {
|
|
|
1012
1065
|
for (const id of flushed) this.replicator._inflight.reusable(id)
|
|
1013
1066
|
}
|
|
1014
1067
|
|
|
1015
|
-
onwant
|
|
1068
|
+
onwant({ start, length }) {
|
|
1016
1069
|
const i = Math.floor(start / DEFAULT_SEGMENT_SIZE)
|
|
1017
1070
|
if (this.remoteSegmentsWanted.size >= MAX_REMOTE_SEGMENTS) this.remoteSegmentsWanted.clear() // just in case of abuse
|
|
1018
1071
|
this.remoteSegmentsWanted.add(i)
|
|
1019
1072
|
this.replicator._onwant(this, start, length)
|
|
1020
1073
|
}
|
|
1021
1074
|
|
|
1022
|
-
onunwant
|
|
1075
|
+
onunwant() {
|
|
1023
1076
|
// TODO
|
|
1024
1077
|
}
|
|
1025
1078
|
|
|
1026
|
-
onbitfield
|
|
1079
|
+
onbitfield({ start, bitfield }) {
|
|
1027
1080
|
if (start < this._remoteContiguousLength) this._remoteContiguousLength = start // bitfield is always the truth
|
|
1028
1081
|
this.remoteBitfield.insert(start, bitfield)
|
|
1029
1082
|
this.missingBlocks.insert(start, bitfield)
|
|
@@ -1031,7 +1084,7 @@ class Peer {
|
|
|
1031
1084
|
this._update()
|
|
1032
1085
|
}
|
|
1033
1086
|
|
|
1034
|
-
_clearLocalRange
|
|
1087
|
+
_clearLocalRange(start, length) {
|
|
1035
1088
|
const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield
|
|
1036
1089
|
|
|
1037
1090
|
if (length === 1) {
|
|
@@ -1064,12 +1117,12 @@ class Peer {
|
|
|
1064
1117
|
}
|
|
1065
1118
|
}
|
|
1066
1119
|
|
|
1067
|
-
_resetMissingBlock
|
|
1120
|
+
_resetMissingBlock(index) {
|
|
1068
1121
|
const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield
|
|
1069
1122
|
this.missingBlocks.set(index, this._remoteHasBlock(index) && !bitfield.get(index))
|
|
1070
1123
|
}
|
|
1071
1124
|
|
|
1072
|
-
_unclearLocalRange
|
|
1125
|
+
_unclearLocalRange(start, length) {
|
|
1073
1126
|
if (length === 1) {
|
|
1074
1127
|
this._resetMissingBlock(start)
|
|
1075
1128
|
return
|
|
@@ -1096,7 +1149,7 @@ class Peer {
|
|
|
1096
1149
|
this._clearLocalRange(fixedStart, length)
|
|
1097
1150
|
}
|
|
1098
1151
|
|
|
1099
|
-
onrange
|
|
1152
|
+
onrange({ drop, start, length }) {
|
|
1100
1153
|
const has = drop === false
|
|
1101
1154
|
|
|
1102
1155
|
if (drop === true && start < this._remoteContiguousLength) {
|
|
@@ -1123,17 +1176,17 @@ class Peer {
|
|
|
1123
1176
|
if (drop === false) this._update()
|
|
1124
1177
|
}
|
|
1125
1178
|
|
|
1126
|
-
onreorghint
|
|
1179
|
+
onreorghint() {
|
|
1127
1180
|
// TODO
|
|
1128
1181
|
}
|
|
1129
1182
|
|
|
1130
|
-
_update
|
|
1183
|
+
_update() {
|
|
1131
1184
|
// TODO: if this is in a batch or similar it would be better to defer it
|
|
1132
1185
|
// we could do that with nextTick/microtick mb? (combined with a property on the session to signal read buffer mb)
|
|
1133
1186
|
this.replicator.updatePeer(this)
|
|
1134
1187
|
}
|
|
1135
1188
|
|
|
1136
|
-
async _onconflict
|
|
1189
|
+
async _onconflict() {
|
|
1137
1190
|
this.protomux.cork()
|
|
1138
1191
|
if (this.remoteLength > 0 && this.core.state.fork === this.remoteFork) {
|
|
1139
1192
|
await this.onrequest({
|
|
@@ -1152,7 +1205,7 @@ class Peer {
|
|
|
1152
1205
|
this.protomux.uncork()
|
|
1153
1206
|
}
|
|
1154
1207
|
|
|
1155
|
-
_makeRequest
|
|
1208
|
+
_makeRequest(needsUpgrade, priority, minLength) {
|
|
1156
1209
|
if (needsUpgrade === true && this.replicator._shouldUpgrade(this) === false) {
|
|
1157
1210
|
return null
|
|
1158
1211
|
}
|
|
@@ -1174,9 +1227,10 @@ class Peer {
|
|
|
1174
1227
|
block: null,
|
|
1175
1228
|
hash: null,
|
|
1176
1229
|
seek: null,
|
|
1177
|
-
upgrade:
|
|
1178
|
-
|
|
1179
|
-
|
|
1230
|
+
upgrade:
|
|
1231
|
+
needsUpgrade === false
|
|
1232
|
+
? null
|
|
1233
|
+
: { start: this.core.state.length, length: this.remoteLength - this.core.state.length },
|
|
1180
1234
|
// remote manifest check can be removed eventually...
|
|
1181
1235
|
manifest: this.core.header.manifest === null && this.remoteHasManifest === true,
|
|
1182
1236
|
priority,
|
|
@@ -1185,12 +1239,12 @@ class Peer {
|
|
|
1185
1239
|
}
|
|
1186
1240
|
}
|
|
1187
1241
|
|
|
1188
|
-
_requestManifest
|
|
1242
|
+
_requestManifest() {
|
|
1189
1243
|
const req = this._makeRequest(false, 0, 0)
|
|
1190
1244
|
this._send(req)
|
|
1191
1245
|
}
|
|
1192
1246
|
|
|
1193
|
-
_requestUpgrade
|
|
1247
|
+
_requestUpgrade(u) {
|
|
1194
1248
|
const req = this._makeRequest(true, 0, 0)
|
|
1195
1249
|
if (req === null) return false
|
|
1196
1250
|
|
|
@@ -1199,7 +1253,7 @@ class Peer {
|
|
|
1199
1253
|
return true
|
|
1200
1254
|
}
|
|
1201
1255
|
|
|
1202
|
-
_requestSeek
|
|
1256
|
+
_requestSeek(s) {
|
|
1203
1257
|
// if replicator is updating the seeks etc, bail and wait for it to drain
|
|
1204
1258
|
if (this.replicator._updatesPending > 0) return false
|
|
1205
1259
|
|
|
@@ -1213,7 +1267,9 @@ class Peer {
|
|
|
1213
1267
|
// We need an upgrade for the seek, if non can be provided, skip
|
|
1214
1268
|
if (req === null) return false
|
|
1215
1269
|
|
|
1216
|
-
req.seek = this.remoteSupportsSeeks
|
|
1270
|
+
req.seek = this.remoteSupportsSeeks
|
|
1271
|
+
? { bytes: s.seeker.bytes, padding: s.seeker.padding }
|
|
1272
|
+
: null
|
|
1217
1273
|
|
|
1218
1274
|
s.inflight.push(req)
|
|
1219
1275
|
this._send(req)
|
|
@@ -1246,7 +1302,9 @@ class Peer {
|
|
|
1246
1302
|
const nodes = flatTree.depth(s.seeker.start + s.seeker.end - 1)
|
|
1247
1303
|
|
|
1248
1304
|
req.hash = { index: 2 * index, nodes }
|
|
1249
|
-
req.seek = this.remoteSupportsSeeks
|
|
1305
|
+
req.seek = this.remoteSupportsSeeks
|
|
1306
|
+
? { bytes: s.seeker.bytes, padding: s.seeker.padding }
|
|
1307
|
+
: null
|
|
1250
1308
|
|
|
1251
1309
|
s.inflight.push(req)
|
|
1252
1310
|
h.inflight.push(req)
|
|
@@ -1259,19 +1317,20 @@ class Peer {
|
|
|
1259
1317
|
return false
|
|
1260
1318
|
}
|
|
1261
1319
|
|
|
1262
|
-
_canRequest
|
|
1320
|
+
_canRequest(index) {
|
|
1263
1321
|
if (!(index >= 0)) throw ASSERTION('bad index to _canRequest: ' + index)
|
|
1264
1322
|
if (this.remoteLength >= this.core.state.length) return true
|
|
1265
|
-
if (index < this.lastUpgradableLength && this.lastUpgradableFork === this.core.state.fork)
|
|
1323
|
+
if (index < this.lastUpgradableLength && this.lastUpgradableFork === this.core.state.fork)
|
|
1324
|
+
return true
|
|
1266
1325
|
if (this.canUpgrade && this.syncsProcessing === 0) return true
|
|
1267
1326
|
return false
|
|
1268
1327
|
}
|
|
1269
1328
|
|
|
1270
|
-
_remoteHasBlock
|
|
1329
|
+
_remoteHasBlock(index) {
|
|
1271
1330
|
return index < this._remoteContiguousLength || this.remoteBitfield.get(index) === true
|
|
1272
1331
|
}
|
|
1273
1332
|
|
|
1274
|
-
_sendBlockRequest
|
|
1333
|
+
_sendBlockRequest(req, b) {
|
|
1275
1334
|
req.block = { index: b.index, nodes: 0 }
|
|
1276
1335
|
this.replicator._markInflight(b.index)
|
|
1277
1336
|
|
|
@@ -1280,7 +1339,7 @@ class Peer {
|
|
|
1280
1339
|
this._send(req)
|
|
1281
1340
|
}
|
|
1282
1341
|
|
|
1283
|
-
_requestBlock
|
|
1342
|
+
_requestBlock(b) {
|
|
1284
1343
|
const { length, fork } = this.core.state
|
|
1285
1344
|
|
|
1286
1345
|
if (this._remoteHasBlock(b.index) === false || fork !== this.remoteFork) {
|
|
@@ -1298,7 +1357,7 @@ class Peer {
|
|
|
1298
1357
|
return true
|
|
1299
1358
|
}
|
|
1300
1359
|
|
|
1301
|
-
_requestRangeBlock
|
|
1360
|
+
_requestRangeBlock(index, length) {
|
|
1302
1361
|
if (this.core.bitfield.get(index) === true || !this._canRequest(index)) return false
|
|
1303
1362
|
|
|
1304
1363
|
const b = this.replicator._blocks.add(index, PRIORITY.NORMAL)
|
|
@@ -1323,7 +1382,7 @@ class Peer {
|
|
|
1323
1382
|
return true
|
|
1324
1383
|
}
|
|
1325
1384
|
|
|
1326
|
-
_findNext
|
|
1385
|
+
_findNext(i) {
|
|
1327
1386
|
if (i < this._remoteContiguousLength) {
|
|
1328
1387
|
if (this.core.skipBitfield === null) this.replicator._openSkipBitfield()
|
|
1329
1388
|
i = this.core.skipBitfield.findFirst(false, i)
|
|
@@ -1334,7 +1393,7 @@ class Peer {
|
|
|
1334
1393
|
return this.missingBlocks.findFirst(true, i)
|
|
1335
1394
|
}
|
|
1336
1395
|
|
|
1337
|
-
_requestRange
|
|
1396
|
+
_requestRange(r) {
|
|
1338
1397
|
if (this.syncsProcessing > 0) return false
|
|
1339
1398
|
|
|
1340
1399
|
const { length, fork } = this.core.state
|
|
@@ -1357,11 +1416,17 @@ class Peer {
|
|
|
1357
1416
|
|
|
1358
1417
|
// if we can upgrade the remote, or the remote is ahead, then all the remotes blocks are valid
|
|
1359
1418
|
// otherwise truncate to the last length the remote has acked for us
|
|
1360
|
-
const maxLocalLength =
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1419
|
+
const maxLocalLength =
|
|
1420
|
+
this.canUpgrade || this.remoteLength >= this.core.state.length
|
|
1421
|
+
? this.core.state.length
|
|
1422
|
+
: fork === this.lastUpgradableFork
|
|
1423
|
+
? Math.min(this.lastUpgradableLength, this.core.state.length)
|
|
1424
|
+
: 0
|
|
1425
|
+
|
|
1426
|
+
const end = Math.min(
|
|
1427
|
+
maxLocalLength,
|
|
1428
|
+
Math.min(r.end === -1 ? this.remoteLength : r.end, this.remoteLength)
|
|
1429
|
+
)
|
|
1365
1430
|
if (end <= r.start || fork !== this.remoteFork) return false
|
|
1366
1431
|
|
|
1367
1432
|
const len = end - r.start
|
|
@@ -1393,7 +1458,7 @@ class Peer {
|
|
|
1393
1458
|
return false
|
|
1394
1459
|
}
|
|
1395
1460
|
|
|
1396
|
-
_requestForkProof
|
|
1461
|
+
_requestForkProof(f) {
|
|
1397
1462
|
if (!this.remoteLength) return
|
|
1398
1463
|
|
|
1399
1464
|
const req = this._makeRequest(false, 0, 0)
|
|
@@ -1405,7 +1470,7 @@ class Peer {
|
|
|
1405
1470
|
this._send(req)
|
|
1406
1471
|
}
|
|
1407
1472
|
|
|
1408
|
-
_requestForkRange
|
|
1473
|
+
_requestForkRange(f) {
|
|
1409
1474
|
if (f.fork !== this.remoteFork || f.batch.want === null) return false
|
|
1410
1475
|
|
|
1411
1476
|
const end = Math.min(f.batch.want.end, this.remoteLength)
|
|
@@ -1434,7 +1499,7 @@ class Peer {
|
|
|
1434
1499
|
return false
|
|
1435
1500
|
}
|
|
1436
1501
|
|
|
1437
|
-
_maybeWant
|
|
1502
|
+
_maybeWant(start, length = 1) {
|
|
1438
1503
|
if (start + length <= this.remoteContiguousLength) return
|
|
1439
1504
|
|
|
1440
1505
|
let i = Math.floor(start / DEFAULT_SEGMENT_SIZE)
|
|
@@ -1452,12 +1517,12 @@ class Peer {
|
|
|
1452
1517
|
}
|
|
1453
1518
|
}
|
|
1454
1519
|
|
|
1455
|
-
isActive
|
|
1520
|
+
isActive() {
|
|
1456
1521
|
if (this.paused || this.removed || this.core.header.frozen) return false
|
|
1457
1522
|
return true
|
|
1458
1523
|
}
|
|
1459
1524
|
|
|
1460
|
-
async _send
|
|
1525
|
+
async _send(req) {
|
|
1461
1526
|
const fork = this.core.state.fork
|
|
1462
1527
|
|
|
1463
1528
|
this.inflight++
|
|
@@ -1470,11 +1535,19 @@ class Peer {
|
|
|
1470
1535
|
|
|
1471
1536
|
try {
|
|
1472
1537
|
if (req.block !== null && req.fork === fork) {
|
|
1473
|
-
req.block.nodes = await MerkleTree.missingNodes(
|
|
1538
|
+
req.block.nodes = await MerkleTree.missingNodes(
|
|
1539
|
+
this.core.state,
|
|
1540
|
+
2 * req.block.index,
|
|
1541
|
+
this.core.state.length
|
|
1542
|
+
)
|
|
1474
1543
|
if (req.priority === PRIORITY.CANCELLED) return
|
|
1475
1544
|
}
|
|
1476
1545
|
if (req.hash !== null && req.fork === fork && req.hash.nodes === 0) {
|
|
1477
|
-
req.hash.nodes = await MerkleTree.missingNodes(
|
|
1546
|
+
req.hash.nodes = await MerkleTree.missingNodes(
|
|
1547
|
+
this.core.state,
|
|
1548
|
+
req.hash.index,
|
|
1549
|
+
this.core.state.length
|
|
1550
|
+
)
|
|
1478
1551
|
if (req.priority === PRIORITY.CANCELLED) return
|
|
1479
1552
|
|
|
1480
1553
|
// nodes === 0, we already have it, bail
|
|
@@ -1497,12 +1570,15 @@ class Peer {
|
|
|
1497
1570
|
module.exports = class Replicator {
|
|
1498
1571
|
static Peer = Peer // hack to be able to access Peer from outside this module
|
|
1499
1572
|
|
|
1500
|
-
constructor
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1573
|
+
constructor(
|
|
1574
|
+
core,
|
|
1575
|
+
{
|
|
1576
|
+
notDownloadingLinger = NOT_DOWNLOADING_SLACK,
|
|
1577
|
+
eagerUpgrade = true,
|
|
1578
|
+
allowFork = true,
|
|
1579
|
+
inflightRange = null
|
|
1580
|
+
} = {}
|
|
1581
|
+
) {
|
|
1506
1582
|
this.core = core
|
|
1507
1583
|
this.eagerUpgrade = eagerUpgrade
|
|
1508
1584
|
this.allowFork = allowFork
|
|
@@ -1557,21 +1633,21 @@ module.exports = class Replicator {
|
|
|
1557
1633
|
const self = this
|
|
1558
1634
|
this._onstreamclose = onstreamclose
|
|
1559
1635
|
|
|
1560
|
-
function onstreamclose
|
|
1636
|
+
function onstreamclose() {
|
|
1561
1637
|
self.detachFrom(this.userData)
|
|
1562
1638
|
}
|
|
1563
1639
|
}
|
|
1564
1640
|
|
|
1565
|
-
updateActivity
|
|
1641
|
+
updateActivity(inc, session) {
|
|
1566
1642
|
this.activeSessions += inc
|
|
1567
1643
|
this.setDownloading(this.activeSessions !== 0, session)
|
|
1568
1644
|
}
|
|
1569
1645
|
|
|
1570
|
-
isDownloading
|
|
1646
|
+
isDownloading() {
|
|
1571
1647
|
return this.downloading || !this._inflight.idle
|
|
1572
1648
|
}
|
|
1573
1649
|
|
|
1574
|
-
setDownloading
|
|
1650
|
+
setDownloading(downloading) {
|
|
1575
1651
|
clearTimeout(this._downloadingTimer)
|
|
1576
1652
|
|
|
1577
1653
|
if (this.destroyed) return
|
|
@@ -1580,11 +1656,16 @@ module.exports = class Replicator {
|
|
|
1580
1656
|
return
|
|
1581
1657
|
}
|
|
1582
1658
|
|
|
1583
|
-
this._downloadingTimer = setTimeout(
|
|
1659
|
+
this._downloadingTimer = setTimeout(
|
|
1660
|
+
setDownloadingLater,
|
|
1661
|
+
this._notDownloadingLinger,
|
|
1662
|
+
this,
|
|
1663
|
+
downloading
|
|
1664
|
+
)
|
|
1584
1665
|
if (this._downloadingTimer.unref) this._downloadingTimer.unref()
|
|
1585
1666
|
}
|
|
1586
1667
|
|
|
1587
|
-
setDownloadingNow
|
|
1668
|
+
setDownloadingNow(downloading) {
|
|
1588
1669
|
this._downloadingTimer = null
|
|
1589
1670
|
if (this.downloading === downloading) return
|
|
1590
1671
|
this.downloading = downloading
|
|
@@ -1592,7 +1673,8 @@ module.exports = class Replicator {
|
|
|
1592
1673
|
|
|
1593
1674
|
for (const peer of this.peers) peer.signalUpgrade()
|
|
1594
1675
|
|
|
1595
|
-
if (downloading) {
|
|
1676
|
+
if (downloading) {
|
|
1677
|
+
// restart channel if needed...
|
|
1596
1678
|
for (const protomux of this._attached) {
|
|
1597
1679
|
if (!protomux.stream.handshakeHash) continue
|
|
1598
1680
|
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.core.discoveryKey })) continue
|
|
@@ -1605,21 +1687,21 @@ module.exports = class Replicator {
|
|
|
1605
1687
|
if (this.ondownloading !== null && downloading) this.ondownloading()
|
|
1606
1688
|
}
|
|
1607
1689
|
|
|
1608
|
-
cork
|
|
1690
|
+
cork() {
|
|
1609
1691
|
for (const peer of this.peers) peer.protomux.cork()
|
|
1610
1692
|
}
|
|
1611
1693
|
|
|
1612
|
-
uncork
|
|
1694
|
+
uncork() {
|
|
1613
1695
|
for (const peer of this.peers) peer.protomux.uncork()
|
|
1614
1696
|
}
|
|
1615
1697
|
|
|
1616
1698
|
// Called externally when a range of new blocks has been processed/removed
|
|
1617
|
-
onhave
|
|
1699
|
+
onhave(start, length, drop = false) {
|
|
1618
1700
|
for (const peer of this.peers) peer.broadcastRange(start, length, drop)
|
|
1619
1701
|
}
|
|
1620
1702
|
|
|
1621
1703
|
// Called externally when a truncation upgrade has been processed
|
|
1622
|
-
ontruncate
|
|
1704
|
+
ontruncate(newLength, truncated) {
|
|
1623
1705
|
const notify = []
|
|
1624
1706
|
|
|
1625
1707
|
for (const blk of this._blocks) {
|
|
@@ -1638,7 +1720,7 @@ module.exports = class Replicator {
|
|
|
1638
1720
|
}
|
|
1639
1721
|
|
|
1640
1722
|
// Called externally when a upgrade has been processed
|
|
1641
|
-
onupgrade
|
|
1723
|
+
onupgrade() {
|
|
1642
1724
|
for (const peer of this.peers) peer.signalUpgrade()
|
|
1643
1725
|
if (this._blocks.isEmpty() === false) this._resolveBlocksLocally()
|
|
1644
1726
|
if (this._upgrade !== null) this._resolveUpgradeRequest(null)
|
|
@@ -1648,7 +1730,7 @@ module.exports = class Replicator {
|
|
|
1648
1730
|
}
|
|
1649
1731
|
|
|
1650
1732
|
// Called externally when a conflict has been detected and verified
|
|
1651
|
-
async onconflict
|
|
1733
|
+
async onconflict() {
|
|
1652
1734
|
const all = []
|
|
1653
1735
|
for (const peer of this.peers) {
|
|
1654
1736
|
all.push(peer._onconflict())
|
|
@@ -1656,7 +1738,7 @@ module.exports = class Replicator {
|
|
|
1656
1738
|
await Promise.allSettled(all)
|
|
1657
1739
|
}
|
|
1658
1740
|
|
|
1659
|
-
async applyPendingReorg
|
|
1741
|
+
async applyPendingReorg() {
|
|
1660
1742
|
if (this._applyingReorg !== null) {
|
|
1661
1743
|
await this._applyingReorg
|
|
1662
1744
|
return true
|
|
@@ -1673,7 +1755,7 @@ module.exports = class Replicator {
|
|
|
1673
1755
|
return false
|
|
1674
1756
|
}
|
|
1675
1757
|
|
|
1676
|
-
addUpgrade
|
|
1758
|
+
addUpgrade(session) {
|
|
1677
1759
|
if (this._upgrade !== null) {
|
|
1678
1760
|
const ref = this._upgrade.attach(session)
|
|
1679
1761
|
this._checkUpgradeIfAvailable()
|
|
@@ -1687,7 +1769,7 @@ module.exports = class Replicator {
|
|
|
1687
1769
|
return ref
|
|
1688
1770
|
}
|
|
1689
1771
|
|
|
1690
|
-
addBlock
|
|
1772
|
+
addBlock(session, index) {
|
|
1691
1773
|
const b = this._blocks.add(index, PRIORITY.HIGH)
|
|
1692
1774
|
const ref = b.attach(session)
|
|
1693
1775
|
|
|
@@ -1697,7 +1779,7 @@ module.exports = class Replicator {
|
|
|
1697
1779
|
return ref
|
|
1698
1780
|
}
|
|
1699
1781
|
|
|
1700
|
-
addSeek
|
|
1782
|
+
addSeek(session, seeker) {
|
|
1701
1783
|
const s = new SeekRequest(this, this._seeks, seeker)
|
|
1702
1784
|
const ref = s.attach(session)
|
|
1703
1785
|
|
|
@@ -1707,8 +1789,19 @@ module.exports = class Replicator {
|
|
|
1707
1789
|
return ref
|
|
1708
1790
|
}
|
|
1709
1791
|
|
|
1710
|
-
addRange
|
|
1711
|
-
|
|
1792
|
+
addRange(
|
|
1793
|
+
session,
|
|
1794
|
+
{
|
|
1795
|
+
start = 0,
|
|
1796
|
+
end = -1,
|
|
1797
|
+
length = toLength(start, end),
|
|
1798
|
+
blocks = null,
|
|
1799
|
+
linear = false,
|
|
1800
|
+
ifAvailable = false
|
|
1801
|
+
} = {}
|
|
1802
|
+
) {
|
|
1803
|
+
if (blocks !== null) {
|
|
1804
|
+
// if using blocks, start, end just acts as frames around the blocks array
|
|
1712
1805
|
start = 0
|
|
1713
1806
|
end = length = blocks.length
|
|
1714
1807
|
}
|
|
@@ -1741,11 +1834,11 @@ module.exports = class Replicator {
|
|
|
1741
1834
|
return ref
|
|
1742
1835
|
}
|
|
1743
1836
|
|
|
1744
|
-
cancel
|
|
1837
|
+
cancel(ref) {
|
|
1745
1838
|
ref.context.detach(ref, null)
|
|
1746
1839
|
}
|
|
1747
1840
|
|
|
1748
|
-
static clearRequests
|
|
1841
|
+
static clearRequests(session, err) {
|
|
1749
1842
|
if (session.length === 0) return
|
|
1750
1843
|
|
|
1751
1844
|
const updated = new Set()
|
|
@@ -1761,7 +1854,7 @@ module.exports = class Replicator {
|
|
|
1761
1854
|
}
|
|
1762
1855
|
}
|
|
1763
1856
|
|
|
1764
|
-
clearRequests
|
|
1857
|
+
clearRequests(session, err = null) {
|
|
1765
1858
|
let cleared = false
|
|
1766
1859
|
while (session.length > 0) {
|
|
1767
1860
|
const ref = session[session.length - 1]
|
|
@@ -1772,14 +1865,14 @@ module.exports = class Replicator {
|
|
|
1772
1865
|
if (cleared) this.updateAll()
|
|
1773
1866
|
}
|
|
1774
1867
|
|
|
1775
|
-
_addUpgradeMaybe
|
|
1868
|
+
_addUpgradeMaybe() {
|
|
1776
1869
|
return this.eagerUpgrade === true ? this._addUpgrade() : this._upgrade
|
|
1777
1870
|
}
|
|
1778
1871
|
|
|
1779
1872
|
// TODO: this function is OVER called atm, at each updatePeer/updateAll
|
|
1780
1873
|
// instead its more efficient to only call it when the conditions in here change - ie on sync/add/remove peer
|
|
1781
1874
|
// Do this when we have more tests.
|
|
1782
|
-
_checkUpgradeIfAvailable
|
|
1875
|
+
_checkUpgradeIfAvailable() {
|
|
1783
1876
|
if (this._ifAvailable > 0 && this.peers.length < MAX_PEERS_UPGRADE) return
|
|
1784
1877
|
if (this._upgrade === null || this._upgrade.refs.length === 0) return
|
|
1785
1878
|
if (this._hadPeers === false && this.findingPeers > 0) return
|
|
@@ -1795,11 +1888,13 @@ module.exports = class Replicator {
|
|
|
1795
1888
|
|
|
1796
1889
|
if (this.core.state.length === 0 && peer.remoteLength > 0) return
|
|
1797
1890
|
|
|
1798
|
-
if (peer.remoteLength <= this._upgrade.length || peer.remoteFork !== this._upgrade.fork)
|
|
1891
|
+
if (peer.remoteLength <= this._upgrade.length || peer.remoteFork !== this._upgrade.fork)
|
|
1892
|
+
continue
|
|
1799
1893
|
|
|
1800
1894
|
if (peer.syncsProcessing > 0) return
|
|
1801
1895
|
|
|
1802
|
-
if (peer.lengthAcked !== this.core.state.length && peer.remoteFork === this.core.state.fork)
|
|
1896
|
+
if (peer.lengthAcked !== this.core.state.length && peer.remoteFork === this.core.state.fork)
|
|
1897
|
+
return
|
|
1803
1898
|
if (peer.remoteCanUpgrade === true) return
|
|
1804
1899
|
}
|
|
1805
1900
|
|
|
@@ -1825,7 +1920,7 @@ module.exports = class Replicator {
|
|
|
1825
1920
|
u.resolve(false)
|
|
1826
1921
|
}
|
|
1827
1922
|
|
|
1828
|
-
_addUpgrade
|
|
1923
|
+
_addUpgrade() {
|
|
1829
1924
|
if (this._upgrade !== null) return this._upgrade
|
|
1830
1925
|
|
|
1831
1926
|
// TODO: needs a reorg: true/false flag to indicate if the user requested a reorg
|
|
@@ -1834,7 +1929,7 @@ module.exports = class Replicator {
|
|
|
1834
1929
|
return this._upgrade
|
|
1835
1930
|
}
|
|
1836
1931
|
|
|
1837
|
-
_addReorg
|
|
1932
|
+
_addReorg(fork, peer) {
|
|
1838
1933
|
if (this.allowFork === false) return null
|
|
1839
1934
|
|
|
1840
1935
|
// TODO: eager gc old reorgs from the same peer
|
|
@@ -1864,31 +1959,37 @@ module.exports = class Replicator {
|
|
|
1864
1959
|
return f
|
|
1865
1960
|
}
|
|
1866
1961
|
|
|
1867
|
-
_shouldUpgrade
|
|
1962
|
+
_shouldUpgrade(peer) {
|
|
1868
1963
|
if (this._upgrade !== null && this._upgrade.inflight.length > 0) return false
|
|
1869
|
-
return
|
|
1964
|
+
return (
|
|
1965
|
+
peer.remoteCanUpgrade === true &&
|
|
1870
1966
|
peer.remoteLength > this.core.state.length &&
|
|
1871
1967
|
peer.lengthAcked === this.core.state.length
|
|
1968
|
+
)
|
|
1872
1969
|
}
|
|
1873
1970
|
|
|
1874
|
-
_autoUpgrade
|
|
1875
|
-
return
|
|
1971
|
+
_autoUpgrade(peer) {
|
|
1972
|
+
return (
|
|
1973
|
+
this._upgrade !== null &&
|
|
1974
|
+
peer.remoteFork === this.core.state.fork &&
|
|
1975
|
+
this._shouldUpgrade(peer)
|
|
1976
|
+
)
|
|
1876
1977
|
}
|
|
1877
1978
|
|
|
1878
|
-
_addPeer
|
|
1979
|
+
_addPeer(peer) {
|
|
1879
1980
|
this._hadPeers = true
|
|
1880
1981
|
this.peers.push(peer)
|
|
1881
1982
|
this.updatePeer(peer)
|
|
1882
1983
|
this._onpeerupdate(true, peer)
|
|
1883
1984
|
}
|
|
1884
1985
|
|
|
1885
|
-
_requestDone
|
|
1986
|
+
_requestDone(id, roundtrip) {
|
|
1886
1987
|
this._inflight.remove(id, roundtrip)
|
|
1887
1988
|
if (this.isDownloading() === true) return
|
|
1888
1989
|
for (const peer of this.peers) peer.signalUpgrade()
|
|
1889
1990
|
}
|
|
1890
1991
|
|
|
1891
|
-
_removePeer
|
|
1992
|
+
_removePeer(peer) {
|
|
1892
1993
|
this.peers.splice(this.peers.indexOf(peer), 1)
|
|
1893
1994
|
|
|
1894
1995
|
if (this._manifestPeer === peer) this._manifestPeer = null
|
|
@@ -1903,20 +2004,20 @@ module.exports = class Replicator {
|
|
|
1903
2004
|
this.updateAll()
|
|
1904
2005
|
}
|
|
1905
2006
|
|
|
1906
|
-
_queueBlock
|
|
2007
|
+
_queueBlock(b) {
|
|
1907
2008
|
if (b.inflight.length > 0 || b.queued === true) return
|
|
1908
2009
|
b.queued = true
|
|
1909
2010
|
this._queued.push(b)
|
|
1910
2011
|
}
|
|
1911
2012
|
|
|
1912
|
-
_resolveHashLocally
|
|
2013
|
+
_resolveHashLocally(peer, req) {
|
|
1913
2014
|
this._requestDone(req.id, false)
|
|
1914
2015
|
this._resolveBlockRequest(this._hashes, req.hash.index / 2, null, req)
|
|
1915
2016
|
this.updatePeer(peer)
|
|
1916
2017
|
}
|
|
1917
2018
|
|
|
1918
2019
|
// Runs in the background - not allowed to throw
|
|
1919
|
-
async _resolveBlocksLocally
|
|
2020
|
+
async _resolveBlocksLocally() {
|
|
1920
2021
|
// TODO: check if fork compat etc. Requires that we pass down truncation info
|
|
1921
2022
|
|
|
1922
2023
|
const clear = []
|
|
@@ -1941,7 +2042,7 @@ module.exports = class Replicator {
|
|
|
1941
2042
|
}
|
|
1942
2043
|
}
|
|
1943
2044
|
|
|
1944
|
-
async _resolveLocalBlock
|
|
2045
|
+
async _resolveLocalBlock(b, reader, resolved) {
|
|
1945
2046
|
try {
|
|
1946
2047
|
b.resolve(await reader.getBlock(b.index))
|
|
1947
2048
|
} catch (err) {
|
|
@@ -1952,7 +2053,7 @@ module.exports = class Replicator {
|
|
|
1952
2053
|
resolved.push(b)
|
|
1953
2054
|
}
|
|
1954
2055
|
|
|
1955
|
-
_resolveBlockRequest
|
|
2056
|
+
_resolveBlockRequest(tracker, index, value, req) {
|
|
1956
2057
|
const b = tracker.remove(index)
|
|
1957
2058
|
if (b === null) return false
|
|
1958
2059
|
|
|
@@ -1962,7 +2063,8 @@ module.exports = class Replicator {
|
|
|
1962
2063
|
|
|
1963
2064
|
b.resolve(value)
|
|
1964
2065
|
|
|
1965
|
-
if (b.inflight.length > 0) {
|
|
2066
|
+
if (b.inflight.length > 0) {
|
|
2067
|
+
// if anything is still inflight, cancel it
|
|
1966
2068
|
for (let i = b.inflight.length - 1; i >= 0; i--) {
|
|
1967
2069
|
const req = b.inflight[i]
|
|
1968
2070
|
req.peer._cancelRequest(req)
|
|
@@ -1972,10 +2074,14 @@ module.exports = class Replicator {
|
|
|
1972
2074
|
return true
|
|
1973
2075
|
}
|
|
1974
2076
|
|
|
1975
|
-
_resolveUpgradeRequest
|
|
2077
|
+
_resolveUpgradeRequest(req) {
|
|
1976
2078
|
if (req !== null) removeInflight(this._upgrade.inflight, req)
|
|
1977
2079
|
|
|
1978
|
-
if (
|
|
2080
|
+
if (
|
|
2081
|
+
this.core.state.length === this._upgrade.length &&
|
|
2082
|
+
this.core.state.fork === this._upgrade.fork
|
|
2083
|
+
)
|
|
2084
|
+
return false
|
|
1979
2085
|
|
|
1980
2086
|
const u = this._upgrade
|
|
1981
2087
|
this._upgrade = null
|
|
@@ -1984,7 +2090,7 @@ module.exports = class Replicator {
|
|
|
1984
2090
|
return true
|
|
1985
2091
|
}
|
|
1986
2092
|
|
|
1987
|
-
_resolveRangeRequest
|
|
2093
|
+
_resolveRangeRequest(req, index) {
|
|
1988
2094
|
const head = this._ranges.pop()
|
|
1989
2095
|
|
|
1990
2096
|
if (index < this._ranges.length) this._ranges[index] = head
|
|
@@ -1992,7 +2098,7 @@ module.exports = class Replicator {
|
|
|
1992
2098
|
req.resolve(true)
|
|
1993
2099
|
}
|
|
1994
2100
|
|
|
1995
|
-
_clearInflightBlock
|
|
2101
|
+
_clearInflightBlock(tracker, req) {
|
|
1996
2102
|
const isBlock = tracker === this._blocks
|
|
1997
2103
|
const index = isBlock === true ? req.block.index : req.hash.index / 2
|
|
1998
2104
|
const b = tracker.get(index)
|
|
@@ -2011,25 +2117,25 @@ module.exports = class Replicator {
|
|
|
2011
2117
|
b.gc()
|
|
2012
2118
|
}
|
|
2013
2119
|
|
|
2014
|
-
_clearInflightUpgrade
|
|
2120
|
+
_clearInflightUpgrade(req) {
|
|
2015
2121
|
if (removeInflight(this._upgrade.inflight, req) === false) return
|
|
2016
2122
|
this._upgrade.gc()
|
|
2017
2123
|
}
|
|
2018
2124
|
|
|
2019
|
-
_clearInflightSeeks
|
|
2125
|
+
_clearInflightSeeks(req) {
|
|
2020
2126
|
for (const s of this._seeks) {
|
|
2021
2127
|
if (removeInflight(s.inflight, req) === false) continue
|
|
2022
2128
|
s.gc()
|
|
2023
2129
|
}
|
|
2024
2130
|
}
|
|
2025
2131
|
|
|
2026
|
-
_clearInflightReorgs
|
|
2132
|
+
_clearInflightReorgs(req) {
|
|
2027
2133
|
for (const r of this._reorgs) {
|
|
2028
2134
|
removeInflight(r.inflight, req)
|
|
2029
2135
|
}
|
|
2030
2136
|
}
|
|
2031
2137
|
|
|
2032
|
-
_clearOldReorgs
|
|
2138
|
+
_clearOldReorgs(fork) {
|
|
2033
2139
|
for (let i = 0; i < this._reorgs.length; i++) {
|
|
2034
2140
|
const f = this._reorgs[i]
|
|
2035
2141
|
if (f.fork >= fork) continue
|
|
@@ -2040,7 +2146,7 @@ module.exports = class Replicator {
|
|
|
2040
2146
|
}
|
|
2041
2147
|
|
|
2042
2148
|
// "slow" updates here - async but not allowed to ever throw
|
|
2043
|
-
async _updateNonPrimary
|
|
2149
|
+
async _updateNonPrimary(updateAll) {
|
|
2044
2150
|
// Check if running, if so skip it and the running one will issue another update for us (debounce)
|
|
2045
2151
|
while (++this._updatesPending === 1) {
|
|
2046
2152
|
let len = Math.min(MAX_RANGES, this._ranges.length)
|
|
@@ -2089,7 +2195,7 @@ module.exports = class Replicator {
|
|
|
2089
2195
|
if (this._inflight.idle || updateAll) this.updateAll()
|
|
2090
2196
|
}
|
|
2091
2197
|
|
|
2092
|
-
_maybeResolveIfAvailableRanges
|
|
2198
|
+
_maybeResolveIfAvailableRanges() {
|
|
2093
2199
|
if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return
|
|
2094
2200
|
|
|
2095
2201
|
for (let i = 0; i < this.peers.length; i++) {
|
|
@@ -2105,7 +2211,7 @@ module.exports = class Replicator {
|
|
|
2105
2211
|
}
|
|
2106
2212
|
}
|
|
2107
2213
|
|
|
2108
|
-
_clearRequest
|
|
2214
|
+
_clearRequest(peer, req) {
|
|
2109
2215
|
if (req.block !== null) {
|
|
2110
2216
|
this._clearInflightBlock(this._blocks, req)
|
|
2111
2217
|
this._unmarkInflight(req.block.index)
|
|
@@ -2128,7 +2234,7 @@ module.exports = class Replicator {
|
|
|
2128
2234
|
}
|
|
2129
2235
|
}
|
|
2130
2236
|
|
|
2131
|
-
_onnodata
|
|
2237
|
+
_onnodata(peer, req, reason) {
|
|
2132
2238
|
if (reason === INVALID_REQUEST) {
|
|
2133
2239
|
peer.stats.backoffs++
|
|
2134
2240
|
this.stats.backoffs++
|
|
@@ -2142,7 +2248,7 @@ module.exports = class Replicator {
|
|
|
2142
2248
|
this.updateAll()
|
|
2143
2249
|
}
|
|
2144
2250
|
|
|
2145
|
-
_openSkipBitfield
|
|
2251
|
+
_openSkipBitfield() {
|
|
2146
2252
|
// technically the skip bitfield gets bits cleared if .clear() is called
|
|
2147
2253
|
// also which might be in inflight also, but that just results in that section being overcalled shortly
|
|
2148
2254
|
// worst case, so ok for now
|
|
@@ -2154,7 +2260,7 @@ module.exports = class Replicator {
|
|
|
2154
2260
|
}
|
|
2155
2261
|
}
|
|
2156
2262
|
|
|
2157
|
-
_markProcessing
|
|
2263
|
+
_markProcessing(index) {
|
|
2158
2264
|
const b = this._blocks.get(index)
|
|
2159
2265
|
if (b) {
|
|
2160
2266
|
b.processing = true
|
|
@@ -2165,7 +2271,7 @@ module.exports = class Replicator {
|
|
|
2165
2271
|
if (h) h.processing = true
|
|
2166
2272
|
}
|
|
2167
2273
|
|
|
2168
|
-
_markProcessed
|
|
2274
|
+
_markProcessed(index) {
|
|
2169
2275
|
const b = this._blocks.get(index)
|
|
2170
2276
|
if (b) return b.processed()
|
|
2171
2277
|
|
|
@@ -2173,22 +2279,23 @@ module.exports = class Replicator {
|
|
|
2173
2279
|
if (h) h.processed()
|
|
2174
2280
|
}
|
|
2175
2281
|
|
|
2176
|
-
_markInflight
|
|
2282
|
+
_markInflight(index) {
|
|
2177
2283
|
if (this.core.skipBitfield !== null) this.core.skipBitfield.set(index, true)
|
|
2178
2284
|
for (const peer of this.peers) peer._markInflight(index)
|
|
2179
2285
|
}
|
|
2180
2286
|
|
|
2181
|
-
_unmarkInflight
|
|
2182
|
-
if (this.core.skipBitfield !== null)
|
|
2287
|
+
_unmarkInflight(index) {
|
|
2288
|
+
if (this.core.skipBitfield !== null)
|
|
2289
|
+
this.core.skipBitfield.set(index, this.core.bitfield.get(index))
|
|
2183
2290
|
for (const peer of this.peers) peer._resetMissingBlock(index)
|
|
2184
2291
|
}
|
|
2185
2292
|
|
|
2186
|
-
fullyDownloaded
|
|
2293
|
+
fullyDownloaded() {
|
|
2187
2294
|
if (!this.core.state.length) return false
|
|
2188
2295
|
return this.core.state.length === this.core.header.hints.contiguousLength
|
|
2189
2296
|
}
|
|
2190
2297
|
|
|
2191
|
-
_ondata
|
|
2298
|
+
_ondata(peer, req, data) {
|
|
2192
2299
|
req.elapsed = Date.now() - req.timestamp
|
|
2193
2300
|
if (data.block !== null) {
|
|
2194
2301
|
this._resolveBlockRequest(this._blocks, data.block.index, data.block.value, req)
|
|
@@ -2215,16 +2322,17 @@ module.exports = class Replicator {
|
|
|
2215
2322
|
this._manifestPeer = null
|
|
2216
2323
|
}
|
|
2217
2324
|
|
|
2218
|
-
if (this._seeks.length > 0 || this._ranges.length > 0)
|
|
2325
|
+
if (this._seeks.length > 0 || this._ranges.length > 0)
|
|
2326
|
+
this._updateNonPrimary(this._seeks.length > 0)
|
|
2219
2327
|
this.updatePeer(peer)
|
|
2220
2328
|
}
|
|
2221
2329
|
|
|
2222
|
-
_onwant
|
|
2330
|
+
_onwant(peer, start, length) {
|
|
2223
2331
|
if (!peer.isActive()) return
|
|
2224
2332
|
|
|
2225
2333
|
const contig = Math.min(this.core.state.length, this.core.header.hints.contiguousLength)
|
|
2226
2334
|
|
|
2227
|
-
if (start + length < contig ||
|
|
2335
|
+
if (start + length < contig || this.core.state.length === contig) {
|
|
2228
2336
|
peer.wireRange.send({
|
|
2229
2337
|
drop: false,
|
|
2230
2338
|
start: 0,
|
|
@@ -2246,8 +2354,8 @@ module.exports = class Replicator {
|
|
|
2246
2354
|
peer.protomux.uncork()
|
|
2247
2355
|
}
|
|
2248
2356
|
|
|
2249
|
-
async _onreorgdata
|
|
2250
|
-
const newBatch = data.upgrade && await this.core.verifyReorg(data)
|
|
2357
|
+
async _onreorgdata(peer, req, data) {
|
|
2358
|
+
const newBatch = data.upgrade && (await this.core.verifyReorg(data))
|
|
2251
2359
|
const f = this._addReorg(data.fork, peer)
|
|
2252
2360
|
|
|
2253
2361
|
if (f === null) {
|
|
@@ -2276,7 +2384,7 @@ module.exports = class Replicator {
|
|
|
2276
2384
|
}
|
|
2277
2385
|
|
|
2278
2386
|
// Never throws, allowed to run in the background
|
|
2279
|
-
async _applyReorg
|
|
2387
|
+
async _applyReorg(f) {
|
|
2280
2388
|
// TODO: more optimal here to check if potentially a better reorg
|
|
2281
2389
|
// is available, ie higher fork, and request that one first.
|
|
2282
2390
|
// This will request that one after this finishes, which is fine, but we
|
|
@@ -2311,16 +2419,20 @@ module.exports = class Replicator {
|
|
|
2311
2419
|
this.updateAll()
|
|
2312
2420
|
}
|
|
2313
2421
|
|
|
2314
|
-
_maybeUpdate
|
|
2422
|
+
_maybeUpdate() {
|
|
2315
2423
|
return this._upgrade !== null && this._upgrade.inflight.length === 0
|
|
2316
2424
|
}
|
|
2317
2425
|
|
|
2318
|
-
_maybeRequestManifest
|
|
2426
|
+
_maybeRequestManifest() {
|
|
2319
2427
|
return this.core.header.manifest === null && this._manifestPeer === null
|
|
2320
2428
|
}
|
|
2321
2429
|
|
|
2322
|
-
_updateFork
|
|
2323
|
-
if (
|
|
2430
|
+
_updateFork(peer) {
|
|
2431
|
+
if (
|
|
2432
|
+
this._applyingReorg !== null ||
|
|
2433
|
+
this.allowFork === false ||
|
|
2434
|
+
peer.remoteFork <= this.core.state.fork
|
|
2435
|
+
) {
|
|
2324
2436
|
return false
|
|
2325
2437
|
}
|
|
2326
2438
|
|
|
@@ -2334,7 +2446,7 @@ module.exports = class Replicator {
|
|
|
2334
2446
|
return false
|
|
2335
2447
|
}
|
|
2336
2448
|
|
|
2337
|
-
_updateHotswap
|
|
2449
|
+
_updateHotswap(peer) {
|
|
2338
2450
|
const maxHotswaps = peer.getMaxHotswapInflight()
|
|
2339
2451
|
if (!peer.isActive() || peer.inflight >= maxHotswaps) return
|
|
2340
2452
|
|
|
@@ -2346,13 +2458,17 @@ module.exports = class Replicator {
|
|
|
2346
2458
|
}
|
|
2347
2459
|
}
|
|
2348
2460
|
|
|
2349
|
-
_updatePeer
|
|
2461
|
+
_updatePeer(peer) {
|
|
2350
2462
|
if (!peer.isActive() || peer.inflight >= peer.getMaxInflight() || !peer.remoteUploading) {
|
|
2351
2463
|
return false
|
|
2352
2464
|
}
|
|
2353
2465
|
|
|
2354
2466
|
// Eagerly request the manifest even if the remote length is 0. If not 0 we'll get as part of the upgrade request...
|
|
2355
|
-
if (
|
|
2467
|
+
if (
|
|
2468
|
+
this._maybeRequestManifest() === true &&
|
|
2469
|
+
peer.remoteLength === 0 &&
|
|
2470
|
+
peer.remoteHasManifest === true
|
|
2471
|
+
) {
|
|
2356
2472
|
this._manifestPeer = peer
|
|
2357
2473
|
peer._requestManifest()
|
|
2358
2474
|
}
|
|
@@ -2378,7 +2494,7 @@ module.exports = class Replicator {
|
|
|
2378
2494
|
return false
|
|
2379
2495
|
}
|
|
2380
2496
|
|
|
2381
|
-
_updatePeerNonPrimary
|
|
2497
|
+
_updatePeerNonPrimary(peer) {
|
|
2382
2498
|
if (!peer.isActive() || peer.inflight >= peer.getMaxInflight() || !peer.remoteUploading) {
|
|
2383
2499
|
return false
|
|
2384
2500
|
}
|
|
@@ -2408,7 +2524,7 @@ module.exports = class Replicator {
|
|
|
2408
2524
|
return false
|
|
2409
2525
|
}
|
|
2410
2526
|
|
|
2411
|
-
updatePeer
|
|
2527
|
+
updatePeer(peer) {
|
|
2412
2528
|
// Quick shortcut to wait for flushing reorgs - not needed but less waisted requests
|
|
2413
2529
|
if (this._applyingReorg !== null) return
|
|
2414
2530
|
|
|
@@ -2423,7 +2539,7 @@ module.exports = class Replicator {
|
|
|
2423
2539
|
this._maybeResolveIfAvailableRanges()
|
|
2424
2540
|
}
|
|
2425
2541
|
|
|
2426
|
-
updateAll
|
|
2542
|
+
updateAll() {
|
|
2427
2543
|
// Quick shortcut to wait for flushing reorgs - not needed but less waisted requests
|
|
2428
2544
|
if (this._applyingReorg !== null) return
|
|
2429
2545
|
|
|
@@ -2451,15 +2567,15 @@ module.exports = class Replicator {
|
|
|
2451
2567
|
this._maybeResolveIfAvailableRanges()
|
|
2452
2568
|
}
|
|
2453
2569
|
|
|
2454
|
-
onpeerdestroy
|
|
2570
|
+
onpeerdestroy() {
|
|
2455
2571
|
if (--this._active === 0) this.core.checkIfIdle()
|
|
2456
2572
|
}
|
|
2457
2573
|
|
|
2458
|
-
attached
|
|
2574
|
+
attached(protomux) {
|
|
2459
2575
|
return this._attached.has(protomux)
|
|
2460
2576
|
}
|
|
2461
2577
|
|
|
2462
|
-
attachTo
|
|
2578
|
+
attachTo(protomux) {
|
|
2463
2579
|
if (this.core.closed) return
|
|
2464
2580
|
|
|
2465
2581
|
const makePeer = this._makePeer.bind(this, protomux)
|
|
@@ -2483,18 +2599,18 @@ module.exports = class Replicator {
|
|
|
2483
2599
|
})
|
|
2484
2600
|
}
|
|
2485
2601
|
|
|
2486
|
-
detachFrom
|
|
2602
|
+
detachFrom(protomux) {
|
|
2487
2603
|
if (this._attached.delete(protomux)) {
|
|
2488
2604
|
protomux.stream.removeListener('close', this._onstreamclose)
|
|
2489
2605
|
protomux.unpair({ protocol: 'hypercore/alpha', id: this.core.discoveryKey })
|
|
2490
2606
|
}
|
|
2491
2607
|
}
|
|
2492
2608
|
|
|
2493
|
-
idle
|
|
2609
|
+
idle() {
|
|
2494
2610
|
return this.peers.length === 0 && this._active === 0
|
|
2495
2611
|
}
|
|
2496
2612
|
|
|
2497
|
-
close
|
|
2613
|
+
close() {
|
|
2498
2614
|
const waiting = []
|
|
2499
2615
|
|
|
2500
2616
|
for (const peer of this.peers) {
|
|
@@ -2505,7 +2621,7 @@ module.exports = class Replicator {
|
|
|
2505
2621
|
return Promise.all(waiting)
|
|
2506
2622
|
}
|
|
2507
2623
|
|
|
2508
|
-
destroy
|
|
2624
|
+
destroy() {
|
|
2509
2625
|
if (this.destroyed) return
|
|
2510
2626
|
this.destroyed = true
|
|
2511
2627
|
|
|
@@ -2525,9 +2641,10 @@ module.exports = class Replicator {
|
|
|
2525
2641
|
}
|
|
2526
2642
|
}
|
|
2527
2643
|
|
|
2528
|
-
_makePeer
|
|
2644
|
+
_makePeer(protomux) {
|
|
2529
2645
|
const replicator = this
|
|
2530
|
-
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.core.discoveryKey }))
|
|
2646
|
+
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.core.discoveryKey }))
|
|
2647
|
+
return onnochannel()
|
|
2531
2648
|
|
|
2532
2649
|
const channel = protomux.createChannel({
|
|
2533
2650
|
userData: null,
|
|
@@ -2565,12 +2682,12 @@ module.exports = class Replicator {
|
|
|
2565
2682
|
|
|
2566
2683
|
return true
|
|
2567
2684
|
|
|
2568
|
-
function onnochannel
|
|
2685
|
+
function onnochannel() {
|
|
2569
2686
|
return false
|
|
2570
2687
|
}
|
|
2571
2688
|
}
|
|
2572
2689
|
|
|
2573
|
-
_onpeerupdate
|
|
2690
|
+
_onpeerupdate(added, peer) {
|
|
2574
2691
|
const name = added ? 'peer-add' : 'peer-remove'
|
|
2575
2692
|
const sessions = this.core.monitors
|
|
2576
2693
|
|
|
@@ -2585,7 +2702,7 @@ module.exports = class Replicator {
|
|
|
2585
2702
|
}
|
|
2586
2703
|
}
|
|
2587
2704
|
|
|
2588
|
-
_ondownload
|
|
2705
|
+
_ondownload(index, byteLength, from, req) {
|
|
2589
2706
|
const sessions = this.core.monitors
|
|
2590
2707
|
|
|
2591
2708
|
for (let i = sessions.length - 1; i >= 0; i--) {
|
|
@@ -2594,7 +2711,7 @@ module.exports = class Replicator {
|
|
|
2594
2711
|
}
|
|
2595
2712
|
}
|
|
2596
2713
|
|
|
2597
|
-
_onupload
|
|
2714
|
+
_onupload(index, byteLength, from) {
|
|
2598
2715
|
const sessions = this.core.monitors
|
|
2599
2716
|
|
|
2600
2717
|
for (let i = sessions.length - 1; i >= 0; i--) {
|
|
@@ -2603,7 +2720,7 @@ module.exports = class Replicator {
|
|
|
2603
2720
|
}
|
|
2604
2721
|
}
|
|
2605
2722
|
|
|
2606
|
-
_oninvaliddata
|
|
2723
|
+
_oninvaliddata(err, req, res, from) {
|
|
2607
2724
|
const sessions = this.core.monitors
|
|
2608
2725
|
|
|
2609
2726
|
this.stats.invalidData++
|
|
@@ -2613,7 +2730,7 @@ module.exports = class Replicator {
|
|
|
2613
2730
|
}
|
|
2614
2731
|
}
|
|
2615
2732
|
|
|
2616
|
-
_oninvalidrequest
|
|
2733
|
+
_oninvalidrequest(err, req, from) {
|
|
2617
2734
|
const sessions = this.core.monitors
|
|
2618
2735
|
|
|
2619
2736
|
from.stats.invalidRequests++
|
|
@@ -2624,21 +2741,22 @@ module.exports = class Replicator {
|
|
|
2624
2741
|
}
|
|
2625
2742
|
}
|
|
2626
2743
|
|
|
2627
|
-
function matchingRequest
|
|
2628
|
-
if (data.block !== null && (req.block === null || req.block.index !== data.block.index))
|
|
2744
|
+
function matchingRequest(req, data) {
|
|
2745
|
+
if (data.block !== null && (req.block === null || req.block.index !== data.block.index))
|
|
2746
|
+
return false
|
|
2629
2747
|
if (data.hash !== null && (req.hash === null || req.hash.index !== data.hash.index)) return false
|
|
2630
2748
|
if (data.seek !== null && (req.seek === null || req.seek.bytes !== data.seek.bytes)) return false
|
|
2631
2749
|
if (data.upgrade !== null && req.upgrade === null) return false
|
|
2632
2750
|
return req.fork === data.fork
|
|
2633
2751
|
}
|
|
2634
2752
|
|
|
2635
|
-
function removeHotswap
|
|
2753
|
+
function removeHotswap(block) {
|
|
2636
2754
|
if (block.hotswap === null) return false
|
|
2637
2755
|
block.hotswap.ref.remove(block)
|
|
2638
2756
|
return true
|
|
2639
2757
|
}
|
|
2640
2758
|
|
|
2641
|
-
function removeInflight
|
|
2759
|
+
function removeInflight(inf, req) {
|
|
2642
2760
|
const i = inf.indexOf(req)
|
|
2643
2761
|
if (i === -1) return false
|
|
2644
2762
|
if (i < inf.length - 1) inf[i] = inf.pop()
|
|
@@ -2646,11 +2764,11 @@ function removeInflight (inf, req) {
|
|
|
2646
2764
|
return true
|
|
2647
2765
|
}
|
|
2648
2766
|
|
|
2649
|
-
function toLength
|
|
2650
|
-
return end === -1 ? -1 :
|
|
2767
|
+
function toLength(start, end) {
|
|
2768
|
+
return end === -1 ? -1 : end < start ? 0 : end - start
|
|
2651
2769
|
}
|
|
2652
2770
|
|
|
2653
|
-
function clampRange
|
|
2771
|
+
function clampRange(core, r) {
|
|
2654
2772
|
if (r.blocks === null) {
|
|
2655
2773
|
const start = core.bitfield.firstUnset(r.start)
|
|
2656
2774
|
|
|
@@ -2670,111 +2788,111 @@ function clampRange (core, r) {
|
|
|
2670
2788
|
}
|
|
2671
2789
|
}
|
|
2672
2790
|
|
|
2673
|
-
function onrequesttimeout
|
|
2791
|
+
function onrequesttimeout(req) {
|
|
2674
2792
|
if (req.context) req.context.detach(req, REQUEST_TIMEOUT())
|
|
2675
2793
|
}
|
|
2676
2794
|
|
|
2677
|
-
function destroyRequestTimeout
|
|
2795
|
+
function destroyRequestTimeout(req) {
|
|
2678
2796
|
if (req.timeout !== null) {
|
|
2679
2797
|
clearTimeout(req.timeout)
|
|
2680
2798
|
req.timeout = null
|
|
2681
2799
|
}
|
|
2682
2800
|
}
|
|
2683
2801
|
|
|
2684
|
-
function isCriticalError
|
|
2802
|
+
function isCriticalError(err) {
|
|
2685
2803
|
// TODO: expose .critical or similar on the hypercore errors that are critical (if all not are)
|
|
2686
2804
|
return err.name === 'HypercoreError'
|
|
2687
2805
|
}
|
|
2688
2806
|
|
|
2689
|
-
function onwireopen
|
|
2807
|
+
function onwireopen(m, c) {
|
|
2690
2808
|
return c.userData.onopen(m)
|
|
2691
2809
|
}
|
|
2692
2810
|
|
|
2693
|
-
function onwireclose
|
|
2811
|
+
function onwireclose(isRemote, c) {
|
|
2694
2812
|
return c.userData.onclose(isRemote)
|
|
2695
2813
|
}
|
|
2696
2814
|
|
|
2697
|
-
function onwiredestroy
|
|
2815
|
+
function onwiredestroy(c) {
|
|
2698
2816
|
c.userData.replicator.onpeerdestroy()
|
|
2699
2817
|
}
|
|
2700
2818
|
|
|
2701
|
-
function onwiredrain
|
|
2819
|
+
function onwiredrain(c) {
|
|
2702
2820
|
return c.userData.ondrain()
|
|
2703
2821
|
}
|
|
2704
2822
|
|
|
2705
|
-
function onwiresync
|
|
2823
|
+
function onwiresync(m, c) {
|
|
2706
2824
|
incrementRx(c.userData.stats.wireSync, c.userData.replicator.stats.wireSync)
|
|
2707
2825
|
return c.userData.onsync(m)
|
|
2708
2826
|
}
|
|
2709
2827
|
|
|
2710
|
-
function onwirerequest
|
|
2828
|
+
function onwirerequest(m, c) {
|
|
2711
2829
|
incrementRx(c.userData.stats.wireRequest, c.userData.replicator.stats.wireRequest)
|
|
2712
2830
|
return c.userData.onrequest(m)
|
|
2713
2831
|
}
|
|
2714
2832
|
|
|
2715
|
-
function onwirecancel
|
|
2833
|
+
function onwirecancel(m, c) {
|
|
2716
2834
|
incrementRx(c.userData.stats.wireCancel, c.userData.replicator.stats.wireCancel)
|
|
2717
2835
|
return c.userData.oncancel(m)
|
|
2718
2836
|
}
|
|
2719
2837
|
|
|
2720
|
-
function onwiredata
|
|
2838
|
+
function onwiredata(m, c) {
|
|
2721
2839
|
incrementRx(c.userData.stats.wireData, c.userData.replicator.stats.wireData)
|
|
2722
2840
|
return c.userData.ondata(m)
|
|
2723
2841
|
}
|
|
2724
2842
|
|
|
2725
|
-
function onwirenodata
|
|
2843
|
+
function onwirenodata(m, c) {
|
|
2726
2844
|
return c.userData.onnodata(m)
|
|
2727
2845
|
}
|
|
2728
2846
|
|
|
2729
|
-
function onwirewant
|
|
2847
|
+
function onwirewant(m, c) {
|
|
2730
2848
|
incrementRx(c.userData.stats.wireWant, c.userData.replicator.stats.wireWant)
|
|
2731
2849
|
return c.userData.onwant(m)
|
|
2732
2850
|
}
|
|
2733
2851
|
|
|
2734
|
-
function onwireunwant
|
|
2852
|
+
function onwireunwant(m, c) {
|
|
2735
2853
|
return c.userData.onunwant(m)
|
|
2736
2854
|
}
|
|
2737
2855
|
|
|
2738
|
-
function onwirebitfield
|
|
2856
|
+
function onwirebitfield(m, c) {
|
|
2739
2857
|
incrementRx(c.userData.stats.wireBitfield, c.userData.replicator.stats.wireBitfield)
|
|
2740
2858
|
return c.userData.onbitfield(m)
|
|
2741
2859
|
}
|
|
2742
2860
|
|
|
2743
|
-
function onwirerange
|
|
2861
|
+
function onwirerange(m, c) {
|
|
2744
2862
|
incrementRx(c.userData.stats.wireRange, c.userData.replicator.stats.wireRange)
|
|
2745
2863
|
return c.userData.onrange(m)
|
|
2746
2864
|
}
|
|
2747
2865
|
|
|
2748
|
-
function onwireextension
|
|
2866
|
+
function onwireextension(m, c) {
|
|
2749
2867
|
incrementRx(c.userData.stats.wireExtension, c.userData.replicator.stats.wireExtension)
|
|
2750
2868
|
return c.userData.onextension(m)
|
|
2751
2869
|
}
|
|
2752
2870
|
|
|
2753
|
-
function setDownloadingLater
|
|
2871
|
+
function setDownloadingLater(repl, downloading, session) {
|
|
2754
2872
|
repl.setDownloadingNow(downloading, session)
|
|
2755
2873
|
}
|
|
2756
2874
|
|
|
2757
|
-
function isBlockRequest
|
|
2875
|
+
function isBlockRequest(req) {
|
|
2758
2876
|
return req !== null && req.block !== null
|
|
2759
2877
|
}
|
|
2760
2878
|
|
|
2761
|
-
function isUpgradeRequest
|
|
2879
|
+
function isUpgradeRequest(req) {
|
|
2762
2880
|
return req !== null && req.upgrade !== null
|
|
2763
2881
|
}
|
|
2764
2882
|
|
|
2765
|
-
function incrementTx
|
|
2883
|
+
function incrementTx(stats1, stats2) {
|
|
2766
2884
|
stats1.tx++
|
|
2767
2885
|
stats2.tx++
|
|
2768
2886
|
}
|
|
2769
2887
|
|
|
2770
|
-
function incrementRx
|
|
2888
|
+
function incrementRx(stats1, stats2) {
|
|
2771
2889
|
stats1.rx++
|
|
2772
2890
|
stats2.rx++
|
|
2773
2891
|
}
|
|
2774
2892
|
|
|
2775
|
-
function noop
|
|
2893
|
+
function noop() {}
|
|
2776
2894
|
|
|
2777
|
-
function backoff
|
|
2895
|
+
function backoff(times) {
|
|
2778
2896
|
const sleep = times < 2 ? 200 : times < 5 ? 500 : times < 40 ? 1000 : 5000
|
|
2779
|
-
return new Promise(resolve => setTimeout(resolve, sleep))
|
|
2897
|
+
return new Promise((resolve) => setTimeout(resolve, sleep))
|
|
2780
2898
|
}
|