hypercore 10.0.0-alpha.19 → 10.0.0-alpha.22

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/index.js CHANGED
@@ -108,6 +108,7 @@ module.exports = class Hypercore extends EventEmitter {
108
108
 
109
109
  if (!noiseStream.userData) {
110
110
  const protocol = Replicator.createProtocol(noiseStream)
111
+ if (opts.keepAlive !== false) protocol.setKeepAlive(true)
111
112
  noiseStream.userData = protocol
112
113
  noiseStream.on('error', noop) // All noise errors already propagate through outerStream
113
114
  }
@@ -230,6 +231,8 @@ module.exports = class Hypercore extends EventEmitter {
230
231
  this.storage = Hypercore.defaultStorage(opts.storage || storage)
231
232
 
232
233
  this.core = await Core.open(this.storage, {
234
+ createIfMissing: opts.createIfMissing,
235
+ overwrite: opts.overwrite,
233
236
  keyPair,
234
237
  crypto: this.crypto,
235
238
  onupdate: this._oncoreupdate.bind(this)
package/lib/protocol.js CHANGED
@@ -2,9 +2,19 @@ const { uint, from: fromEncoding } = require('compact-encoding')
2
2
  const b4a = require('b4a')
3
3
  const safetyCatch = require('safety-catch')
4
4
  const codecs = require('codecs')
5
+ const sodium = require('sodium-universal')
5
6
 
6
7
  const messages = require('./messages')
7
8
 
9
+ const slab = b4a.alloc(96)
10
+ const NS = slab.subarray(0, 32)
11
+ const NS_HYPERCORE_INITIATOR = slab.subarray(32, 64)
12
+ const NS_HYPERCORE_RESPONDER = slab.subarray(64, 96)
13
+
14
+ sodium.crypto_generichash(NS, b4a.from('hypercore'))
15
+ sodium.crypto_generichash(NS_HYPERCORE_INITIATOR, b4a.from([0]), NS)
16
+ sodium.crypto_generichash(NS_HYPERCORE_RESPONDER, b4a.from([1]), NS)
17
+
8
18
  class Extension {
9
19
  constructor (protocol, type, name, handlers) {
10
20
  this.protocol = protocol
@@ -256,11 +266,17 @@ module.exports = class Protocol {
256
266
  this._localExtensions = 128
257
267
  this._remoteExtensions = []
258
268
  this._extensions = new Map()
269
+ this._keepAliveInterval = null
270
+ this._pendingCaps = []
259
271
 
260
272
  this._destroyer = this._safeDestroy.bind(this)
261
273
  this.noiseStream.on('data', this.onmessage.bind(this))
262
274
  this.noiseStream.on('end', this.noiseStream.end) // no half open
275
+ this.noiseStream.on('finish', () => {
276
+ this.setKeepAlive(false)
277
+ })
263
278
  this.noiseStream.on('close', () => {
279
+ this.setKeepAlive(false)
264
280
  // TODO: If the stream was destroyed with an error, we probably want to forward it here
265
281
  for (const peer of this._peers.values()) {
266
282
  peer.destroy(null)
@@ -270,6 +286,18 @@ module.exports = class Protocol {
270
286
  this._sendHandshake()
271
287
  }
272
288
 
289
+ setKeepAlive (enable) {
290
+ if (enable) {
291
+ if (this._keepAliveInterval) return
292
+ this._keepAliveInterval = setInterval(this.ping.bind(this), 5000)
293
+ if (this._keepAliveInterval.unref) this._keepAliveInterval.unref()
294
+ } else {
295
+ if (!this._keepAliveInterval) return
296
+ clearInterval(this._keepAliveInterval)
297
+ this._keepAliveInterval = null
298
+ }
299
+ }
300
+
273
301
  _sendHandshake () {
274
302
  const m = { protocolVersion: this.protocolVersion, userAgent: this.userAgent }
275
303
  const state = { start: 0, end: 0, buffer: null }
@@ -332,6 +360,11 @@ module.exports = class Protocol {
332
360
 
333
361
  if (batch.length === 0) return
334
362
 
363
+ while (this._pendingCaps.length > 0) {
364
+ const [key, cap] = this._pendingCaps.pop()
365
+ hypercoreCapability(this.noiseStream.isInitiator, this.noiseStream.handshakeHash, key, cap)
366
+ }
367
+
335
368
  const state = { start: 0, end: 0, buffer: null }
336
369
  const lens = new Array(batch.length)
337
370
 
@@ -372,14 +405,24 @@ module.exports = class Protocol {
372
405
  }
373
406
 
374
407
  _announceCore (alias, key, discoveryKey) {
408
+ const cap = b4a.alloc(32)
409
+
410
+ if (!this.noiseStream.handshakeHash) {
411
+ this._pendingCaps.push([key, cap]) // encode it later...
412
+ } else {
413
+ hypercoreCapability(this.noiseStream.isInitiator, this.noiseStream.handshakeHash, key, cap)
414
+ }
415
+
375
416
  this.send(2, messages.core, -1, {
376
417
  alias: alias,
377
418
  discoveryKey: discoveryKey,
378
- capability: b4a.alloc(32) // TODO
419
+ capability: cap
379
420
  })
380
421
  }
381
422
 
382
423
  _decode (buffer) {
424
+ if (buffer.byteLength === 0) return
425
+
383
426
  const state = { start: 0, end: buffer.length, buffer }
384
427
 
385
428
  if (this._firstMessage === true) {
@@ -453,7 +496,11 @@ module.exports = class Protocol {
453
496
  if (m.alias === this._remoteAliases.length) this._remoteAliases.push(null)
454
497
 
455
498
  if (peer) {
456
- // TODO: check cap
499
+ const expectedCap = hypercoreCapability(!this.noiseStream.isInitiator, this.noiseStream.handshakeHash, peer.key)
500
+ if (!b4a.equals(expectedCap, m.capability)) {
501
+ this.destroy(new Error('Remote sent an invalid capability'))
502
+ return
503
+ }
457
504
 
458
505
  if (m.alias >= this._remoteAliases.length) {
459
506
  this.destroy(new Error('Remote alias out of bounds'))
@@ -508,6 +555,11 @@ module.exports = class Protocol {
508
555
  return this.noiseStream.write(state.buffer)
509
556
  }
510
557
 
558
+ ping () {
559
+ const empty = this.noiseStream.alloc(0)
560
+ this.noiseStream.write(empty)
561
+ }
562
+
511
563
  destroy (err) {
512
564
  return this.noiseStream.destroy(err)
513
565
  }
@@ -523,3 +575,9 @@ function noop () {}
523
575
  function isPromise (p) {
524
576
  return !!p && typeof p.then === 'function'
525
577
  }
578
+
579
+ function hypercoreCapability (initiator, handshakeHash, key, cap = b4a.alloc(32)) {
580
+ const ns = initiator ? NS_HYPERCORE_INITIATOR : NS_HYPERCORE_RESPONDER
581
+ sodium.crypto_generichash_batch(cap, [handshakeHash, key], ns)
582
+ return cap
583
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.0.0-alpha.19",
3
+ "version": "10.0.0-alpha.22",
4
4
  "description": "Hypercore 10",
5
5
  "main": "index.js",
6
6
  "scripts": {