hypercore-protocol
Advanced tools
Comparing version 7.5.0 to 7.6.0
46
index.js
@@ -7,13 +7,24 @@ const SHP = require('simple-hypercore-protocol') | ||
const pretty = require('pretty-hash') | ||
const Message = require('abstract-extension') | ||
const { Duplex } = require('streamx') | ||
class StreamExtension extends Message { | ||
send (message) { | ||
const stream = this.local.handlers | ||
if (stream._changes !== this.local.changes) { | ||
stream._changes = this.local.changes | ||
stream.state.options(0, { extensions: this.local.names() }) | ||
} | ||
return stream.state.extension(0, this.id, this.encode(message)) | ||
} | ||
} | ||
class Channelizer { | ||
constructor (stream, encrypted, keyPair, userData) { | ||
constructor (stream, encrypted, keyPair) { | ||
this.stream = stream | ||
this.created = new Map() | ||
this.local = [] | ||
this.remote = [] | ||
this.local = [null] | ||
this.remote = [null] | ||
this.encrypted = encrypted !== false | ||
this.keyPair = keyPair | ||
this.userData = userData || null | ||
} | ||
@@ -23,3 +34,3 @@ | ||
const id = this.local.indexOf(null) | ||
if (id > -1) return id | ||
if (id > 0) return id | ||
this.local.push(null) | ||
@@ -89,2 +100,3 @@ return this.local.length - 1 | ||
if (ch && ch.handlers && ch.handlers.onoptions) ch.handlers.onoptions(message) | ||
else if (channelId === 0 && !ch) this.stream._updateExtensions(message.extensions) | ||
} | ||
@@ -135,2 +147,3 @@ | ||
if (ch && ch.handlers && ch.handlers.onextension) ch.handlers.onextension(id, buf) | ||
else if (channelId === 0 && !ch) this.stream.remoteExtensions.onmessage(id, buf) | ||
} | ||
@@ -281,3 +294,3 @@ | ||
this.handlers = handlers | ||
this.channelizer = new Channelizer(this, handlers.encrypted, handlers.keyPair, handlers.userData) | ||
this.channelizer = new Channelizer(this, handlers.encrypted, handlers.keyPair) | ||
this.state = new SHP(initiator, this.channelizer) | ||
@@ -290,4 +303,7 @@ this.live = !!handlers.live | ||
this.bytesReceived = 0 | ||
this.extensions = StreamExtension.createLocal(this) | ||
this.remoteExtensions = this.extensions.remote() | ||
this._utp = null | ||
this._changes = 0 | ||
@@ -304,2 +320,6 @@ this.once('finish', this.push.bind(this, null)) | ||
registerExtension (name, handlers) { | ||
return this.extensions.add(name, handlers) | ||
} | ||
[inspect] (depth, opts) { | ||
@@ -340,10 +360,2 @@ let indent = '' | ||
get userData () { | ||
return this.state.userData | ||
} | ||
get remoteUserData () { | ||
return this.state.remoteUserData | ||
} | ||
_onpipe (dest) { | ||
@@ -388,2 +400,8 @@ if (typeof dest.setContentSize === 'function') this._utp = dest | ||
_updateExtensions (names) { | ||
this.remoteExtensions.update(names) | ||
if (this.handlers.onextensions) this.handlers.onextensions(names) | ||
this.emit('extensions', names) | ||
} | ||
remoteOpened (key) { | ||
@@ -390,0 +408,0 @@ const ch = this.channelizer.getChannel(crypto.discoveryKey(key)) |
{ | ||
"name": "hypercore-protocol", | ||
"version": "7.5.0", | ||
"version": "7.6.0", | ||
"description": "Stream that implements the hypercore protocol", | ||
"main": "index.js", | ||
"dependencies": { | ||
"abstract-extension": "^3.0.1", | ||
"hypercore-crypto": "^1.0.0", | ||
@@ -8,0 +9,0 @@ "inspect-custom-symbol": "^1.1.0", |
@@ -26,3 +26,3 @@ # hypercore-protocol | ||
const key = Buffer.from('deadbeefdeadbeefdeadbeefdeadbeef') | ||
const feed = streamA.open(key) | ||
const channel = streamA.open(key) | ||
const remoteFeed = streamB.open(key, { | ||
@@ -36,3 +36,3 @@ // listen for data in remote feed | ||
// add data to feed | ||
feed.data({ index: 1, value: '{ block: 42 }'}) | ||
channel.data({ index: 1, value: '{ block: 42 }'}) | ||
@@ -59,3 +59,3 @@ streamA.pipe(streamB).pipe(streamA) | ||
onhandshake () { }, // function called when the stream handshake has finished | ||
ondiscoverykey (discoveryKey) { }, // function called when the remote stream opens a feed you have not | ||
ondiscoverykey (discoveryKey) { }, // function called when the remote stream opens a channel you have not | ||
onchannelclose (discoveryKey, publicKey) { } // function called when a feed-channel closes | ||
@@ -135,27 +135,27 @@ } | ||
#### `feed.options(message)` | ||
#### `channel.options(message)` | ||
Send an `options` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L13) | ||
#### `feed.handlers.onoptions(message)` | ||
#### `channel.handlers.onoptions(message)` | ||
Called when a options message has been received. | ||
#### `feed.status(message)` | ||
#### `channel.status(message)` | ||
Send an `status` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L20) | ||
#### `feed.handlers.onstatus(message)` | ||
#### `channel.handlers.onstatus(message)` | ||
Called when a status message has been received. | ||
#### `feed.have(message)` | ||
#### `channel.have(message)` | ||
Send a `have` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L26) | ||
#### `feed.handlers.onhave(message)` | ||
#### `channel.handlers.onhave(message)` | ||
Called when a `have` message has been received. | ||
#### `feed.unhave(message)` | ||
#### `channel.unhave(message)` | ||
@@ -165,23 +165,23 @@ Send a `unhave` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L34) | ||
#### `feed.handlers.onunhave(message)` | ||
#### `channel.handlers.onunhave(message)` | ||
Called when a `unhave` message has been received. | ||
#### `feed.want(want)` | ||
#### `channel.want(want)` | ||
Send a `want` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L40) | ||
#### `feed.handlers.onwant(want)` | ||
#### `channel.handlers.onwant(want)` | ||
Called when a `want` message has been received. | ||
#### `feed.unwant(unwant)` | ||
#### `channel.unwant(unwant)` | ||
Send a `unwant` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L46) | ||
#### `feed.handlers.onunwant(unwant)` | ||
#### `channel.handlers.onunwant(unwant)` | ||
Called when a `unwant` message has been received. | ||
#### `feed.request(request)` | ||
#### `channel.request(request)` | ||
@@ -191,42 +191,63 @@ Send a `request` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L52) | ||
#### `feed.handlers.onrequest(request)` | ||
#### `channel.handlers.onrequest(request)` | ||
Called when a `request` message has been received. | ||
#### `feed.cancel(cancel)` | ||
#### `channel.cancel(cancel)` | ||
Send a `cancel` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L60) | ||
#### `feed.handlers.oncancel(cancel)` | ||
#### `channel.handlers.oncancel(cancel)` | ||
Called when a `cancel` message has been received. | ||
#### `feed.data(data)` | ||
#### `channel.data(data)` | ||
Send a `data` message. [See the protobuf schema for more info on this messsage](https://github.com/mafintosh/simple-hypercore-protocol/blob/master/schema.proto#L67) | ||
#### `feed.handlers.ondata(data)` | ||
#### `channel.handlers.ondata(data)` | ||
Called when a `data` message has been received. | ||
#### `feed.extension(id, buffer)` | ||
#### `channel.extension(id, buffer)` | ||
Send an `extension` message. `id` should be the index an extension name in the `extensions` list sent in a previous `options` message for this channel. | ||
#### `feed.handlers.onextension(id, buffer)` | ||
#### `channel.handlers.onextension(id, buffer)` | ||
Called when an `extension` message has been received. `id` is the index of an extension name received in an extension list in a previous `options` message for this channel. | ||
#### `feed.close()` | ||
#### `channel.close()` | ||
Close this feed. You only need to call this if you are sharing a lot of feeds and want to garbage collect some old unused ones. | ||
Close this channel. You only need to call this if you are sharing a lot of feeds and want to garbage collect some old unused ones. | ||
#### `feed.handlers.onclose()` | ||
#### `channel.handlers.onclose()` | ||
Called when this feed has been closed. All feeds are automatically closed when the stream ends or is destroyed. | ||
#### `feed.destroy(err)` | ||
#### `channel.destroy(err)` | ||
An alias to `stream.destroy`. | ||
## Stream message extensions | ||
You can also send custom messages over the stream unrelated to any channel or hypercore feed. | ||
You usually don't need this but can be useful if you are bootstrapping a specific protocol on top. | ||
#### `const ext = stream.registerExtension(name, handlers)` | ||
Register a new stream extension named `name`. | ||
* `handlers.onmessage(message)` is called when an unchanneled extension message is received for this extension. | ||
* `handlers.onerror(error)` in case there was an encoding error. | ||
* `handlers.encoding` can be set to `json`, `utf-8`, `binary` or any abstract encoding to automatically decode/encode messages. | ||
#### `ext.send(message)` | ||
Send an extension message. | ||
#### `ext.destroy()` | ||
Destroy this extension. Unregisters it from the stream as well. | ||
## Wire protocol | ||
@@ -233,0 +254,0 @@ |
36
test.js
@@ -542,25 +542,29 @@ const tape = require('tape') | ||
tape('userData', function (t) { | ||
t.plan(4) | ||
tape('stream extension', function (t) { | ||
const a = new Protocol(true, { | ||
userData: { | ||
type: 'a type', | ||
value: Buffer.from('a value') | ||
onextensions (names) { | ||
t.same(names, ['test', 'z']) | ||
} | ||
}) | ||
const b = new Protocol(false) | ||
const b = new Protocol(false, { | ||
onextensions (names) { | ||
t.same(names, ['a', 'test']) | ||
} | ||
}) | ||
a.pipe(b).pipe(a) | ||
a.on('handshake', function () { | ||
t.same(a.userData, { type: 'a type', value: Buffer.from('a value') }) | ||
t.same(a.remoteUserData, null) | ||
a.registerExtension('a') | ||
a.registerExtension('test', { | ||
encoding: 'json', | ||
onmessage (message) { | ||
t.same(message, { hello: 'world' }) | ||
t.end() | ||
} | ||
}) | ||
b.on('handshake', function () { | ||
t.same(b.userData, null) | ||
t.same(b.remoteUserData, { type: 'a type', value: Buffer.from('a value') }) | ||
}) | ||
b.registerExtension('z') | ||
const ext = b.registerExtension('test', { encoding: 'json' }) | ||
ext.send({ hello: 'world' }) | ||
a.pipe(b).pipe(a) | ||
}) |
38106
939
280
8
+ Addedabstract-extension@^3.0.1
+ Addedabstract-extension@3.1.1(transitive)
+ Addedcodecs@2.2.0(transitive)