Skip to main content

Transport Configuration

There are instances where you may want to configure additional connections configurations for the current Ditto instance. This section will teach you how to configure your Ditto instance to listen for connections on a port explicitly and to connect to remote instances via a host (IP) and port. To do this, before you call startSync(), construct a DittoTransportConfig value and set ditto.SetTransportConfig.

Ditto will automatically attempt to connect to other ditto instances on the Local Area Network, Bluetooth, and AWDL. However, if you supply a DittoTransportConfig, this will not automatically be enabled. You'll need to remember to enable peer to peer connnections with EnableAllPeerToPeer().

Enabling/Disabling Transports

You can enable all peer to peer connections with EnableAllPeerToPeer(). You can also customize which transports are used by enabling/disabling each transport separately.

// Create a new DittoTransportConfig()var config = DittoTransportConfig()
//Enable all peer to peer transportsconfig.enableAllPeerToPeer()
//Or enable/disable each transport separately//BluetoothLeconfig.peerToPeer.bluetoothLE.isEnabled = true//Local Area Networkconfig.peerToPeer.lan.isEnabled = true//Awdlconfig.peerToPeer.awdl.isEnabled = true
ditto.transportConfig = config
do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

Sync to Ditto Cloud

The big peer generates certificates automatically for each small peer. A certificate involves an expiration date and AppID, among other credentials. Read more here about how it works.

In order to sync with other devices, a peer must connect to the Big Peer at least once. To do this, you must use either OnlinePlayground or OnlineWithAuthentication.

We recommend using OnlinePlayground for development and OnlineWithAuthentication for production apps. If you only want to use the Big Peer for authentication without syncing to the cloud, you can use enableDittoCloudSync=false. enableDittoCloudSync is set to true by default.

let ditto = Ditto(identity: .onlinePlayground(    appID: "REPLACE_ME_WITH_YOUR_APP_ID",    token: "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN",    // Set to false to disable syncing with the cloud    enableDittoCloudSync: true))do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

Observing Peers

Ditto always monitors the mesh network and can report the device names of peers it is connected to. You can manually set the device name of those peers and observe those peers in the network.

info

The device name must be set before startSync() is called.

ditto.deviceName = "Susan B."let observer = ditto.presence.observe { presence in    if !presence.remotePeers.isEmpty {        // render peers    }}
do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

If you want to observe changes made by a particular device, include the device name as a field in the document and query for that field in your ditto live query

"status == 'open' && edited_by == 'deviceC'"

Sync Groups

When peer-to-peer transports are enabled, all devices with the same App ID will form an interconnected mesh network. If you have knowledge ahead of time that devices are in distinct groups that should only sync with each other, you can optimize performance by restricting them from syncronizing with each other.

The syncGroup parameter provides this functionality. A device can only ever be in one sync group, which by default is group 0. Up to 2^32 distinct group numbers can be used in an app. Using a sync group is more performant, and is recommended in any case where this knowledge is known ahead of time.

info

For example, imagine an application that supports two different restaurant locations: 1234 and 7890. Before calling startSync(), you can use a different sync group for each location. Only devices in the same sync group will sync with eachother. This will make queries faster when sent to the same big peer.

struct User {    var id: String    var restaurantID: UInt32}let authenticatedUser = User(id: "abc123", restaurantID: 323234)
var config = DittoTransportConfig()// 1. Enable All Peer to Peer Connections config.enableAllPeerToPeer()// 2. Set sync group to an integer between 0 and 2^32config.global.syncGroup = authenticatedUser.restaurantIDditto.transportConfig = config
do {  try ditto.startSync()} catch (let error) {  print(error.localizedDescription)}
info

Note: sync groups are not a security mechanism

Sync groups are an optimization, not a security control. If a connection is created manually, such as by specifying a connect transport, then devices from different sync groups will still sync as normal. If two groups of devices are intended to have access to different data sets, this must be enforced using Ditto's permissions system.

Connecting to a Remote Ditto Peer

If you know the host and port of another remote Ditto peer and would like to connect to it, construct a DittoTransportConfig object and add the host and port to the DittoTransportConfig.Connect.TcpServers property as a string. The string format should be host:port, separated by a colon.

In the example below, we know of two other Ditto peers located on:

  • Host IP 135.1.5.5 at port 12345
  • Host IP 185.1.5.5 at port 4567
var config = DittoTransportConfig()// Connect explicitly to a remote devicesconfig.connect.tcpServers.insert("135.1.5.5:12345")config.connect.tcpServers.insert("185.1.5.5:12345")
ditto.transportConfig = config
do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

Feel free to add as many known remote host:port strings.

You can also configure your Ditto instance to connect to a websocket, which is useful to connect to one or more big peers or authentication instances.

Not supported by Swift.

Listening for Connections on a Specific Port

You can enable the Ditto instance to listen for incoming connections from other remotes Ditto peers on a specific port. You can think of this as setting up your Ditto as a "server" that can listen to connections from other peers.

In this example, we would like our Ditto instance to listen to incoming connections on port 4000 on 0.0.0.0.

info

To be safe, please do not use localhost when setting the IP interface. Use "0.0.0.0" instead.

var config = DittoTransportConfig()
// Listen for incoming connections on port 4000config.listen.tcp.isEnabled = trueconfig.listen.tcp.interfaceIP = "0.0.0.0"config.listen.tcp.port = 4000
ditto.transportConfig = config
do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

Incoming connections from other Ditto peers will be able to connect only if the port is accessible. Depending on your deployment be sure to check that external connections can reach the port that you have specified in your configuration. You may need to set up port forwarding if external ports map differently to your host.

Combining Multiple Transports

You can specify several modes of transport configuration within DittoTransportConfig. The following snippet shows you a ditto instance that can:

  1. Connect to local area network devices
  2. Listen for incoming remote connections
  3. Connect to remote devices with a known host and port.
var config = DittoTransportConfig()// 1. Enable All Peer to Peer Connectionsconfig.enableAllPeerToPeer()
// 2. Listen for incoming connections on port 4000config.listen.tcp.isEnabled = trueconfig.listen.tcp.interfaceIP = "0.0.0.0"config.listen.tcp.port = 4000
// 3. Connect explicitly to remote devicesconfig.connect.tcpServers.insert("135.1.5.5:12345")config.connect.tcpServers.insert("185.1.5.5:12345")
ditto.transportConfig = config
do {  try ditto.startSync()} catch (let err) {  print(err.localizedDescription)}

Monitoring Transport Conditions

If syncing over Bluetooth LE is a critical part of your application you may want to warn the user if they are missing the permission or if the hardware is disabled. Ditto will help you by reporting conditions via a delegate or callback object.

First, while configuring Ditto, assign a delegate or a callback to receive notifications.

// Setting up inside a ViewControllerlet ditto = Ditto(identity: DittoIdentity.onlinePlayground(appID: "REPLACE_ME_WITH_YOUR_APP_ID", token: "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"))ditto.delegate = selftry! ditto.startSync()
// Now you can observe real time changes to the transport conditions:extension ViewController: DittoDelegate {   func transportConditionDidChange(transportID: Int64, condition: TransportCondition) {       if condition == .BleDisabled {           print("BLE disabled")       } else if condition == .NoBleCentralPermission {           print("Permission missing for BLE")       } else if condition == .NoBlePeripheralPermission {           print("Permission missing for BLE")       }   }
New and Improved Docs

Ditto has a new documentation site at https://docs.ditto.live. This legacy site is preserved for historical reference, but its content is not guaranteed to be up to date or accurate.