Skip to content

Commit

Permalink
Merge pull request #7 from arj03/ssb-conn
Browse files Browse the repository at this point in the history
Use SSB conn to enable room support
  • Loading branch information
arj03 authored Oct 18, 2020
2 parents bdcfdb3 + f2b452f commit a01ee63
Show file tree
Hide file tree
Showing 21 changed files with 1,389 additions and 1,232 deletions.
106 changes: 34 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@
Secure scuttlebutt core (similar to [ssb-server]) in a browser.

This is a full implementation of ssb running in the browser only (but
not limited to of course). The key of your feed is stored in the
not limited to, of course). The key of your feed is stored in the
browser together with the log, indexes and smaller images. To reduce
storage and network requirements, partial replication has been
implemented. Wasm is used for crypto and is around 90% the speed of
the C implementation. A WebSocket is used to connect to pubs. The
`bundle-core.js` file in dist/ is roughly 1.8mb.
`bundle-core.js` file in dist/ is roughly 2mb.

Replication in the browser is quite a bit slower than in node, around
4-5x. There doesn't seem to be a single cause, it appears to be all
the diferrent layers that are [slower]: end-to-end encryption,
database write etc.

Partial replication [speed] on a fast laptop is roughly 414 feeds in 85
SSB conn is used for connections and rooms are supported. Partial
replication is implemented which allows two connected browsers to do a
partial sync.

Partial replication [speed] on a fast laptop is roughly 425 feeds in 56
seconds, and roughly half of that on a slow laptop or when running on
battery.

Expand All @@ -42,10 +46,6 @@ Default config options are defined in `net.js`.

## Runtime configurations

### remoteAddress

The remote server to connect to. Must be web socket.

### hops

The number of hops from which to store feeds in full. Hops + 1 will be
Expand Down Expand Up @@ -111,11 +111,15 @@ Gets the current db status, same functionality as

Returns a [jitdb] instance of the database useful for queries.

### getLast(cb)
### onDrain(cb)

Will cb when all outstanding writes for the log has been written to storage.

Returns the last index.
### getLatest(feedId, cb)

### getClock(err)
Returns the latest state ({ id (msg key), sequence, timestamp }) for a feedId.

### getDataFromAuthorSequence()

Internal method for EBT.

Expand All @@ -134,18 +138,12 @@ Returns the profiles index.

Returns all the messages for a particular root in sorted order.

### getMessagesByMention (key, cb)
### getMessagesByMention(key, cb)

Returns a sorted array messages that has a particular key in the
mentions array. This is useful for notifications for a particular
feed.

### feedSyncer.syncFeeds(cb)

Calling this will ensure that the feeds you follow are synced in full
and that feeds followed by someone you follow are synced partially,
meaning the latest 25 messages, contacts & profile information.

## net

This is the [secret-stack] module with a few extra modules
Expand All @@ -166,6 +164,15 @@ SSB.net.on('rpc:connect', (rpc) => {
})
```

### connectAndRemember(addr, data)

Will connect and store as to automatically reconnect on
reload. Options are as described in [ssb-conn].

### connect(addr, cb)

Connect to addr only once. Cb is (err, rpc)

### blobs

This is where the `blobs` api can be found. The module implements the
Expand Down Expand Up @@ -217,48 +224,11 @@ locally and used for callback, otherwise the callback will return a

The [ssb-ooo] module

### tunnelMessage

Uses a modified version of [ssb-tunnel] to send and receive end-to-end
encrypted ephemeral messages between two peers.

#### acceptMessages(confirmHandler)

Tell the pub to allow incoming connections, but call confirmHandler
with the remote feedId for manual confirmation.

#### connect(feedId, cb)

Connect to a remote feedId. When connected a message will be put in
`messages`. Takes an optional cb.

#### disconnect()

Disconnects all currently active tunnel connections.

#### sendMessage(type, data)

Send a data message to the remote user, adds the message to the local `messages` stream.

#### messages

A stream of messages consisting of type, user and data. Example usage:

```
pull(
messages(),
pull.drain((msg) => {
console.log(msg.user + "> " + msg.data)
})
)
```

### Browser specific methods on net

For partial replication a special plugin has been created, the pub
needs to have the plugin installed:

- [ssb-partial-replication]
For partial replication a special plugin has been created and
implemented in browser core, other clients such as a pub needs to have
the [ssb-partial-replication] plugin installed.

Once a rpc connection has been established, a few extra methods are
available under SSB.net.partialReplication. See plugin for
Expand All @@ -281,19 +251,13 @@ The [ssb-validate] module.
The current [state](https://github.com/ssbc/ssb-validate#state) of
known feeds.

### connected(cb)

If not connected, will connect and return. If connected, will just
return the already present rpc connection. Cb signature is (err, rpc).

### publish(msg, cb)

Validates a message and stores it in the database. See db.add for format.

### sync()
### getPeer()

Will run `feedSyncer.syncFeeds` follow by a EBT replication with the
remote server. This syncs all the feeds known in `SSB.state.feeds`.
Gets one of the connected peers that is not a room server.

### box

Expand Down Expand Up @@ -330,13 +294,11 @@ using safari.

# Building

The following patches (patch -p0 < x.patch) from the patches folder
are needed:
- ssb-tunnel.patch
- ssb-blob-files.patch
Run `npm run build` for debugging and `npm run release` for a smaller
dist file.

For a smaller bundle file, you can also apply
patches/sodium-browserify.patch
For a smaller bundle file you can apply (patch -p0 < x.patch):
- patches/sodium-browserify.patch

[ssb-server]: https://github.com/ssbc/ssb-server
[ssb-browser-demo]: https://github.com/arj03/ssb-browser-demo
Expand All @@ -345,7 +307,7 @@ patches/sodium-browserify.patch
[ssb-validate]: https://github.com/ssbc/ssb-validate
[ssb-blob-files]: https://github.com/ssbc/ssb-blob-files
[ssb-ooo]: https://github.com/ssbc/ssb-ooo
[ssb-tunnel]: https://github.com/ssbc/ssb-tunnel
[ssb-conn]: https://github.com/staltz/ssb-conn

[ssb-get-thread]: https://github.com/arj03/ssb-get-thread
[ssb-partial-replication]: https://github.com/arj03/ssb-partial-replication
Expand Down
43 changes: 19 additions & 24 deletions core-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@ const pull = require('pull-stream')
const raf = require('polyraf')
const path = require('path')

var remote

exports.connected = function(cb)
exports.getPeer = function()
{
if (!remote || remote.closed)
{
SSB.net.connect(SSB.remoteAddress, (err, rpc) => {
if (err) throw(err)
let connPeers = Array.from(SSB.net.conn.hub().entries())
connPeers = connPeers.filter(([, x]) => !!x.key).map(([address, data]) => ({ address, data }))
var goodPeer = connPeers.find(cp => cp.data.type != 'room')

remote = rpc
cb(remote)
})
} else
cb(remote)
let peers = Object.values(SSB.net.peers).flat()

if (goodPeer) return peers.find(p => p.id == goodPeer.data.key)
else if (peers.length > 0) return peers[0]
else return null
}

function deleteDatabaseFile(filename) {
Expand Down Expand Up @@ -72,23 +69,21 @@ exports.removeBlobs = function() {
})
}

exports.EBTSync = function()
exports.EBTSync = function(rpc)
{
// FIXME: should not be able to run twice
exports.connected((rpc) => {
SSB.db.contacts.getGraphForFeed(SSB.net.id, (err, graph) => {
SSB.net.ebt.updateClock(() => {
SSB.net.ebt.request(SSB.net.id, true)
graph.following.forEach(feed => SSB.net.ebt.request(feed, true))
graph.extended.forEach(feed => SSB.net.ebt.request(feed, true))
console.log("doing ebt with", rpc.id)
SSB.db.contacts.getGraphForFeed(SSB.net.id, (err, graph) => {
SSB.net.ebt.updateClock(() => {
SSB.net.ebt.request(SSB.net.id, true)
graph.following.forEach(feed => SSB.net.ebt.request(feed, true))
graph.extended.forEach(feed => SSB.net.ebt.request(feed, true))

SSB.net.ebt.startEBT(rpc)
})
SSB.net.ebt.startEBT(rpc)
})
})
}

exports.sync = function()
exports.fullSync = function(rpc)
{
SSB.db.feedSyncer.syncFeeds(exports.EBTSync)
SSB.db.feedSyncer.syncFeeds(rpc, exports.EBTSync)
}
24 changes: 17 additions & 7 deletions core.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,23 @@ exports.init = function (dir, config) {
net,
dir,

getPeer: helpers.getPeer,

validate,
state,

connected: helpers.connected,

removeDB: helpers.removeDB,
removeIndexes: helpers.removeIndexes,
removeBlobs: helpers.removeBlobs,

sync: helpers.sync,

box: require('ssb-keys').box,
blobFiles: require('ssb-blob-files'),

// sbot convenience wrappers
publish: function(msg, cb) {
state.queue = []
state = validate.appendNew(state, null, net.config.keys, msg, Date.now())
console.log(state.queue[0])
//console.log(state.queue[0])
db.add(state.queue[0].value, (err, data) => {
net.post(data.value) // tell ebt
cb(err, data)
Expand All @@ -79,10 +77,22 @@ exports.init = function (dir, config) {

// config
hops: 1, // this means download full log for hops and partial logs for hops + 1

remoteAddress: '',
})

// helper for rooms to allow connecting to friends directly
SSB.net.friends = {
hops: function(cb) {
db.contacts.getGraphForFeed(SSB.net.id, (err, graph) => {
let hops = {}
graph.following.forEach(f => hops[f] = 1)
graph.extended.forEach(f => hops[f] = 2)
cb(err, hops)
})
}
}

SSB.net.conn.start()

SSB.events.emit("SSB: loaded")
})
}
Loading

0 comments on commit a01ee63

Please sign in to comment.