Skip to content

Commit

Permalink
Add basic experimental bus doc (#466)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylerjokiel authored Feb 21, 2023
1 parent a97b4d0 commit bfb7bb3
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 1 deletion.
8 changes: 8 additions & 0 deletions docs/common/sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ module.exports = function (opts) {
dirName: 'common/how-it-works'
}]
},
{
type: "category",
label: "Experimental",
items: [{
type: 'autogenerated',
dirName: 'experimental'
}]
},
opts.api,
"common/v3",
"common/troubleshooting"
Expand Down
4 changes: 4 additions & 0 deletions docs/ios/experimental/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Experimental",
"position": 1
}
94 changes: 94 additions & 0 deletions docs/ios/experimental/ditto-bus.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: 'Ditto Bus'
---

import SnippetGroup from '@site/src/components/SnippetGroup';

:::danger
*The Ditto Bus API is currently **Experimental** and should not be used in production scenarios*
:::

The Ditto Bus is designed to enable developers to leverage the underlying mesh network to transmit data peer-to-peer without using the Ditto Store. It can be used to send one-off messages or create continuous channels with other peers in the mesh. The Ditto bus does not persist data.

Messages are treated as opaque binary by Ditto and must be created and interpreted by your application.

## Example Use Cases

- Voice and video streaming
- Remote control systems
- Tunneling other protocols
- Gaming

## Version Support & Imports

### Version Support

The Ditto bus is included as experimental in SDK version `3.0.0` and later.

### Import

It can be imported in a file through the standard `DittoSwift` import.

```swift
import DittoSwift
```

## Getting PeerAddress

To be able to send a message or establish a connection you need to know the peer you want to connect to.

[ObservingPeers Docs](../common/mesh-network/manual#observing-peers)

<SnippetGroup
name='bus-peers-first-user'
/>

## Sending Messages

Messages can be sent as single one-off messages or through establishing a bidirectional stream with another peer. All transports are peer-to-peer and require having the address of the peer you are connecting to.

### Reliable Single Message
User1 sends a single reliable message to User2

<SnippetGroup
name='bus-single-message-receive'
/>
<SnippetGroup
name='bus-reliable-single-message-send'
/>

### Unreliable Single Message
User1 sends a single unreliable message to User2

<SnippetGroup
name='bus-single-message-receive'
/>
<SnippetGroup
name='bus-unreliable-single-message-send'
/>

### Reliable Bidirectional Stream
User1 establishes a reliable bidirectional stream with User2. Both users can enqueue messages on the stream. Messages are ordered and guarantee.

<SnippetGroup
name='bus-bidirectional-stream-handler'
/>
<SnippetGroup
name='bus-reliable-bidirectional-stream-sender'
/>
<SnippetGroup
name='bus-bidirectional-stream-common'
/>

### Unreliable Bidirectional Stream
User1 establishes an unreliable bidirectional stream with User2. Both users can enqueue messages on the stream. Messages are not ordered or guarantee.

<SnippetGroup
name='bus-bidirectional-stream-handler'
/>
<SnippetGroup
name='bus-unreliable-bidirectional-stream-sender'
/>
<SnippetGroup
name='bus-bidirectional-stream-common'
/>
11 changes: 10 additions & 1 deletion snippets.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,16 @@
"evict": "collection.find(\"owner == 'Bob'\").evict()\n\n",
"remove-query": "collection.find(\"owner == 'Bob'\").remove()\n\n",
"remove-id": "collection.findByID(docID).remove()\n\n",
"sync-basic": "try! ditto.startSync()\n\n"
"sync-basic": "try! ditto.startSync()\n\n",
"bus-peers-first-user": "// Get the DittoAddress from the first user in the peer object\nditto.presence.observe { presence in\n if !presence.remotePeers.isEmpty {\n let user2PeerAddress = presence.remotePeers[0].address\n }",
"bus-single-message-receive": "// User2 sets up a delegate to handle inbound requests\nditto.bus.delegate = SingleMessageReceivedDelegate()\n\nclass SingleMessageReceivedDelegate: DittoBusDelegate {\n var receivedMessage: Data?\n \n func dittoBus(_ bus: DittoBus, didReceiveSingleMessage message: DittoBusMessage) {\n self.receivedMessage = message.data\n }\n \n func dittoBus(_ bus: DittoBus, didReceiveIncomingStream busStream: DittoBusStream,\nfromPeer peer: DittoAddress) {\n // not implemented\n }\n}",
"bus-reliable-single-message-send": "// User1 sends data to User2. Success provides guarantee of data delivery.\nlet data = Data([1, 2, 3, 4, 5])\nditto.bus.sendSingleReliableMessage(data, to: user2PeerAddress, completion: { e in\n if let error = e {\n // success\n }\n})",
"bus-unreliable-single-message-send": "// User1 sends data to User2. Success provides guarantee of data sent.\nlet data = Data([1, 2, 3, 4, 5])\nditto.bus.sendSingleUnreliableMessage(data, to: user2PeerAddress, completion: { e in\n if let error = e {\n // success\n }\n})",
"bus-bidirectional-stream-handler": "// User2 - Create a delegate to handle inbound stream requests\nlet incomingDelegate = IncomingStreamRecievedDelegate()\n// Attach a StreamDelegate to handle messages once a connection is established\nincomingDelegate.streamDelegate = StreamDelegate()\nditto.bus.delegate = incomingDelegate\n\n// Send a message\nlet data = Data([1, 2, 3, 4, 5])\nincomingDelegate.connectedStream?.enqueueMessage(data: data)\n\n// An ID unique to the local device that can be used to track this individual stream.\nuser1Stream?.id\n\n// Close the stream\nincomingDelegate.connectedStream?.close()",
"bus-reliable-bidirectional-stream-sender":"// User1 - Reliable Bidirectional Stream\n\nditto.bus.delegate = IncomingStreamRecievedDelegate()\n\nlet streamDelegate = StreamDelegate()\nvar user1Stream: DittoBusStream?\nself.ditto1.bus.openStream(toAddress: user2PeerAddress, reliability: .reliable) { stream, err in\n user1Stream = stream\n stream?.delegate = streamDelegate\n}\n\n// Send Message\nlet data = Data([1, 2, 3, 4, 5])\nuser1Stream?.enqueueMessage(data: data)\n\n// An ID unique to the local device that can be used to track this individual stream.\nuser1Stream?.id\n\n// close\nuser1Stream?.close()",
"bus-unreliable-bidirectional-stream-sender":"// User1 - Unreliable Bidirectional Stream\n\nditto.bus.delegate = IncomingStreamRecievedDelegate()\n\nlet streamDelegate = StreamDelegate()\nvar user1Stream: DittoBusStream?\nself.ditto1.bus.openStream(toAddress: user2PeerAddress, reliability: .unreliable) { stream, err in\n user1Stream = stream\n stream?.delegate = streamDelegate\n}\n\n// Send Message\nlet data = Data([1, 2, 3, 4, 5])\nuser1Stream?.enqueueMessage(data: data)\n\n// An ID unique to the local device that can be used to track this individual stream.\nuser1Stream?.id\n\n// close\nuser1Stream?.close()",
"bus-bidirectional-stream-common":"// Common Classes\n\n// Handles new stream requests\nclass IncomingStreamRecievedDelegate: DittoBusDelegate {\n var connectedStream: DittoBusStream?\n var streamDelegate: DittoBusStreamDelegate?\n \n func dittoBus(_ bus: DittoBus, didReceiveSingleMessage message: DittoBusMessage) {}\n \n func dittoBus(_ bus: DittoBus, didReceiveIncomingStream busStream: DittoBusStream, fromPeer peer: DittoAddress) {\n self.incomingStream = busStream\n busStream.delegate = self.streamDelegate\n }\n}\n\n/// Handles opeartions/messages on a connected stream\nclass StreamDelegate: DittoBusStreamDelegate {\n \n /// A new message has been received from the specified stream.\n func dittoBusStream(_ busStream: DittoBusStream, didReceiveMessage message: Data) {\n // handle message recieved\n }\n \n /// The stream has closed. This can be triggered by calling close() or by the remote peer doing the same.\n func dittoBusStream(_ busStream: DittoBusStream, didClose error: DittoSwiftError) {\n // handle connection closed\n }\n \n // The operation to enqueue outgoing data on a stream has completed. More data may now be enqueued.\n // The message sequence number may be used to track when the remote side has fully acknowledged receipt.\n // `error` will be non-nil if the operation failed.\n func dittoBusStream(_ busStream: DittoBusStream, didEnqueueDataWithMessageSequence messageSequence: UInt64, error: DittoSwiftError?) {\n // handle did enqueue data\n }\n \n // The remote peer has acknowledged receipt of all messages up to the given sequence number.\n func dittoBusStream(_ busStream: DittoBusStream, didAcknowledgeReceipt messageSequence: UInt64) {}\n // handle did data was received \n}"

},
"cpp": {
"sync-observe-local": "// --- Register live query to update UI\nstd::shared_ptr<LiveQuery> query =\n collection.find(\"color == 'red'\")\n .observe_local([&](std::vector<Document> docs, LiveQueryEvent event) {\n\n });\n\n",
Expand Down

0 comments on commit bfb7bb3

Please sign in to comment.