---
title: Customizing Transports Configurations
slug: v4-7/sync/customizing-transport-configurations
docTags: 
createdAt: 2023-07-28T23:20:15.622Z
---

This article provides instructions on explicitly configuring your Ditto instance to listen for connections on a specific port and to connect to remote instances using a host (IP) and port.&#x20;

:::hint{type="info"}
Although Ditto automatically attempts to connect to other instances on the Local Area Network (LAN), Bluetooth Low Energy (LE), and Apple Wireless Direct Link (AWDL), supplying a `DittoTransportConfig` does *not* enable this feature by default.&#x20;

Rather, you manually enable peer-to-peer connections using `EnableAllPeerToPeer()`. (See [Enabling and Disabling Transports](./#enabling-and-disabling-transports))
:::

# Enabling and Disabling Transports

You can enable and disable transport protocols for all connected Small Peers by doing either of the following.&#x20;

- To enable all transport protocols at once, configure `EnableAllPeertoPeer( )`.
- To enable transport protocols separately, configure a transport protocol one at a time, as shown in the following example.

:::CodeblockTabs
```swift
// Create a new DittoTransportConfig()
var config = DittoTransportConfig()

//Enable all peer to peer transports
config.enableAllPeerToPeer()

//Or enable/disable each transport separately
//BluetoothLe
config.peerToPeer.bluetoothLE.isEnabled = true
//Local Area Network
config.peerToPeer.lan.isEnabled = true
//Awdl
config.peerToPeer.awdl.isEnabled = true

ditto.transportConfig = config

do {
  try ditto.startSync()
} catch (let err) {
  print(err.localizedDescription)
}
```

```kotlin
val config = DittoTransportConfig()

//Enable all peer to peer transports
config.enableAllPeerToPeer()

//Or enable/disable each transport separately
//BluetoothLe
config.peerToPeer.bluetoothLe.enabled = true
//Local Area Network
config.peerToPeer.lan.enabled = true
//Wifi Aware
config.peerToPeer.wifiAware.enabled = true

ditto.transportConfig = config

ditto.startSync()
```

```javascript
const config = new TransportConfig()

// Enable all peer to peer transports
config.setAllPeerToPeerEnabled(true)

// or enable/disable each transport separately
// BluetoothLE
config.peerToPeer.bluetoothLE.isEnabled = true

// Local Area Network
config.peerToPeer.lan.isEnabled = true

// AWDL
config.peerToPeer.awdl.isEnabled = true

ditto.setTransportConfig(config)
ditto.startSync()
```

```java
DittoTransportConfig config = new DittoTransportConfig();

//Enable all peer to peer transports
config.enableAllPeerToPeer();

//Or enable/disable each transport separately
//BluetoothLe
config.getPeerToPeer().getBluetoothLe().setEnabled(true);
//Local Area Network
config.getPeerToPeer().getLan().setEnabled(true);
//Awdl
config.getPeerToPeer().getWifiAware().setEnabled(true);

ditto.setTransportConfig(config);

try {
    ditto.startSync();
} catch(DittoError error) {
    // handle error
}
```

```csharp
DittoTransportConfig config = new DittoTransportConfig();

//Enable all peer to peer transports
config.EnableAllPeerToPeer();

//Or enable/disable each transport separately
//BluetoothLe
config.PeerToPeer.BluetoothLE.Enabled = true;
config.PeerToPeer.BluetoothLE.Enabled = true;
//Local Area Network
config.PeerToPeer.Lan.Enabled = true;
//Awdl
config.PeerToPeer.Awdl.Enabled = true;

Ditto.TransportConfig = config;

Ditto.StartSync();
```

```cpp
// Not supported.
```

```rust
// Not supported.
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Configuring Additional Settings

If you need additional connection configurations for the current Ditto instance, configure it to listen for connections on a specific port and to connect to remote instances using a host (IP) and port:

::::WorkflowBlock
:::WorkflowBlockItem
Before calling `startSync()`, create a `DittoTransportConfig` object with the desired settings.
:::

:::WorkflowBlockItem
Using the `ditto.SetTransportConfig` API method, set the created object on your Ditto instance.
:::

:::WorkflowBlockItem
Call the `startSync` method on your Ditto instance to initiate sync with the configured settings.
:::
::::

# Syncing with Big Peer

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` digital identities.

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`.

:::hint{type="info"}
By default, `enableDittoCloudSync` is set to `true`.
:::

:::CodeblockTabs
```swift
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)
}
```

```kotlin
val config = DittoTransportConfig()

//Enable all peer to peer transports
config.enableAllPeerToPeer()

//Or enable/disable each transport separately
//BluetoothLe
config.peerToPeer.bluetoothLe.enabled = true
//Local Area Network
config.peerToPeer.lan.enabled = true
//Wifi Aware
config.peerToPeer.wifiAware.enabled = true

ditto.transportConfig = config

ditto.startSync()
```

```javascript
const identity: Identity = {
  type: '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,
}
const path = './your-ditto-application-data-path'
const ditto = new Ditto(identity, path)
ditto.startSync()
```

```java
DittoIdentity identity = new DittoIdentity.OnlinePlayground(androidDependencies,
        "REPLACE_ME_WITH_YOUR_APP_ID",
        "YOUR_PLAYGROUND_TOKEN_HERE",
        // Set to false to disable syncing with the cloud
        true);

Ditto ditto = new Ditto(androidDependencies, identity);

try {
    ditto.startSync();
} catch(DittoError e) {
    //handle error
}
```

```csharp
try
{
    var ditto = new Ditto(DittoIdentity.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), path);

    ditto.StartSync();
}
catch (DittoException ex)
{
    Console.WriteLine($"Ditto Error {ex.Message}");
}
```

```cpp
// Not supported.
```

```rust
// Not supported.
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Connecting to Remote Small Peers

If you know the host and port of another remote Ditto peer and would like to connect to it, construct a `DittoTransportConfig` object and, using `string` format: `host:port` separated by a colon, add the host and port to the `DittoTransportConfig.Connect.TcpServers` property.&#x20;

For example, the following indicates there are two other Small Peers known to Ditto and provides details of their network locations, including the IP addresses and port numbers associated with each peer:

- Host IP `135.1.5.5` at port `12345`
- Host IP `185.1.5.5` at port `4567`

:::CodeblockTabs
```swift
var config = DittoTransportConfig()
// Connect explicitly to a remote devices
config.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)
}
```

```kotlin
val transportConfig = DittoTransportConfig()

transportConfig.connect.tcpServers.add("135.1.5.5:12345")
transportConfig.connect.tcpServers.add("185.1.5.5:12345")

ditto.transportConfig = transportConfig
ditto.startSync()
```

```javascript
import { TransportConfig } from '@dittolive/ditto'

const config = new TransportConfig()
config.connect.websocketURLs.push('wss://135.1.5.5:12345')
config.connect.websocketURLs.push('wss://185.1.5.5:12345')
ditto.setTransportConfig(config)
ditto.startSync()
```

```java
DittoTransportConfig config = new DittoTransportConfig();
DittoConnect connect = new DittoConnect();
connect.setTcpServers(Sets.newHashSet("135.1.5.5:12345", "185.1.5.5:12345"));
config.setConnect(connect);

try {
    ditto.startSync();
} catch(DittoError error) {
    // handle error
}
```

```csharp
DittoTransportConfig transportConfig = new DittoTransportConfig();
// Connect explicitly to a remote device on
transportConfig.Connect.TcpServers.Add("135.1.5.5:12345");
// you can add as many TcpServers as you would like.
transportConfig.Connect.TcpServers.Add("185.1.5.5:4567");
// set the transport config
Ditto.TransportConfig = transportConfig;
// now you can start ditto's sync
Ditto.StartSync();
```

```cpp
auto config = ditto::TransportConfig();
// Connect explicitly to remote devices
config.connect.tcp_servers.insert("135.1.5.5:12345");
config.connect.tcp_servers.insert("185.1.5.5:12345");

// set the transport config
ditto.set_transport_config(config);
// now you can start ditto's sync
ditto.start_sync();
```

```rust
let mut config = TransportConfig::new(); // empty

config
    .connect
    .tcp_servers
    .insert("135.1.5.5:12345".to_string()); // Custom TCP Listener
config
    .connect
    .tcp_servers
    .insert("185.1.5.5:12345".to_string()); // Custom TCP Listener
config
    .connect
    .websocket_urls
    .insert("wss://example.com".to_string()); // Custom WS endpoint

ditto.set_transport_config(config);
ditto.start_sync()?;
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Initializing WebSocket Connections

Ensure WebSocket connections are discoverable across peers within your local network:&#x20;

:::CodeblockTabs
```swift
var config = DittoTransportConfig()
config.connect.webSocketURLs.insert("ws://127.0.0.1")
ditto.transportConfig = config

do {
  try ditto.startSync()
} catch (let err) {
  print(err.localizedDescription)
}
```

```kotlin
val config = DittoTransportConfig()

config.connect.websocketUrls.add("ws://127.0.0.1")

ditto.transportConfig = config

ditto.startSync()
```

```javascript
import { TransportConfig } from '@dittolive/ditto'

const config = new TransportConfig()
config.connect.websocketURLs.push('ws://127.0.0.1')
ditto.setTransportConfig(config)
ditto.startSync()
```

```java
var config = getTransportConfig();
config.getConnect().getWebsocketUrls().add("ws://127.0.0.1");
ditto.setTransportConfig(config);

try {  
    ditto.startSync();
} catch(DittoError error) {
    System.out.println(error.getLocalizedMessage());
}
```

```csharp
DittoTransportConfig config = new DittoTransportConfig();

config.Connect.WebsocketUrls.Add("ws://127.0.0.1");

Ditto.TransportConfig = config;

Ditto.StartSync();
```

```cpp
auto config = ditto::TransportConfig();
config.connect.websocket_urls.insert("ws://127.0.0.1");
ditto.set_transport_config(config);
ditto.start_sync();
```

```rust
let mut config = TransportConfig::new();
config
	.connect
	.websocket_urls
	.insert(String::from("ws://127.0.0.1"));
ditto.set_transport_config(config);
ditto.start_sync()?;
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Listening for Connections

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**.

:::hint{type="info"}
To be safe, please do not use **localhost** when setting the IP interface. Use **"0.0.0.0"** instead.
:::

:::CodeblockTabs
```swift
var config = DittoTransportConfig()

// Listen for incoming connections on port 4000
config.listen.tcp.isEnabled = true
config.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)
}
```

```kotlin
val transportConfig = DittoTransportConfig()
transportConfig.connect.tcpServers.add("135.1.5.5:12345")
transportConfig.connect.tcpServers.add("185.1.5.5:12345")
ditto.transportConfig = transportConfig
ditto.startSync()
```

```javascript
import { TransportConfig } from '@dittolive/ditto'

const config = new TransportConfig()
config.listen.tcp.isEnabled = true
config.listen.tcp.interfaceIP = '0.0.0.0'
config.listen.tcp.port = 4000
ditto.setTransportConfig(config)
ditto.startSync()
```

```java
DittoTransportConfig config = new DittoTransportConfig();
config.enableAllPeerToPeer();

DittoListen listen = new DittoListen();
DittoTcpListenConfig tcpListenConfig = new DittoTcpListenConfig();
tcpListenConfig.setEnabled(true);
tcpListenConfig.setInterfaceIp("0.0.0.0");
tcpListenConfig.setPort(4000);
listen.setTcp(tcpListenConfig);
config.setListen(listen);

try {
    ditto.startSync();
} catch(DittoError error) {
    // handle error
}
```

```csharp
DittoTransportConfig transportConfig = new DittoTransportConfig();
transportConfig.Listen.Tcp = new DittoTcpListenConfig();
// By default Listen.Tcp.Enabled is false, be sure to set it to true.
transportConfig.Listen.Tcp.Enabled = true;
// if you want to listen on localhost, most likely you will use 0.0.0.0
// do not use "localhost" as a string
transportConfig.Listen.Tcp.InterfaceIp = "0.0.0.0";
// specify your port.
transportConfig.Listen.Tcp.Port = 4000;
Ditto.TransportConfig = transportConfig;

// now you can call `ditto.StartSync()`
Ditto.StartSync();
```

```cpp
auto config = ditto::TransportConfig();

config.listen.tcp.enabled = true;
config.listen.http.enabled = false;
config.listen.tcp.interface_ip = "0.0.0.0";
config.listen.tcp.port = 4000;

ditto.set_transport_config(config);
ditto.start_sync();
```

```rust
let mut config = TransportConfig::new(); // empty

config.listen.tcp.enabled = true;
config.listen.tcp.interface_ip = "0.0.0.0".to_string();
config.listen.tcp.port = 4000;
config.listen.http.enabled = false;

ditto.set_transport_config(config);
ditto.start_sync()?;
```

Dart (beta)

```dart
// Coming Soon
```
:::

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:

- Connect to local area network devices
- Listen for incoming remote connections
- Connect to remote devices with a known host and port.

:::CodeblockTabs
```swift
var config = DittoTransportConfig()
// 1. Enable All Peer to Peer Connections
config.enableAllPeerToPeer()

// 2. Listen for incoming connections on port 4000
config.listen.tcp.isEnabled = true
config.listen.tcp.interfaceIP = "0.0.0.0"
config.listen.tcp.port = 4000

// 3. Connect explicitly to remote devices
config.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)
}
```

```kotlin
val transportConfig = DittoTransportConfig()
// 1. Enable All Peer to Peer Connections
transportConfig.enableAllPeerToPeer()
// 2. Listen for incoming connections on port 4000
transportConfig.listen.tcp.enabled = true
transportConfig.listen.http.enabled = false
transportConfig.listen.tcp.interfaceIp = "0.0.0.0"
transportConfig.listen.tcp.port = 4000
// 3. Connect explicitly to remote devices
transportConfig.connect.tcpServers.add("135.1.5.5:12345")
transportConfig.connect.tcpServers.add("185.1.5.5:12345")

ditto.transportConfig = transportConfig
ditto.startSync()
```

```javascript
import { TransportConfig } from '@dittolive/ditto'

const config = new TransportConfig()
if (isNode() && OS === 'darwin') {
// 1. Enable All Peer to Peer Connections (not in a browser environment)
config.setAllPeerToPeerEnabled(true)
// 2. Listen for incoming connections on port 4000
config.listen.tcp.isEnabled = true
config.listen.tcp.interfaceIP = '0.0.0.0'
config.listen.tcp.port = 4000

// 3. Connect explicitly to remote devices
ditto.setTransportConfig(config)
ditto.startSync()
```

```java
DittoTransportConfig config = new DittoTransportConfig();

// 1. Enable Peer to Peer Connections
config.enableAllPeerToPeer();

// 2. Listen for incoming connections on port 4000
DittoListen listen = new DittoListen();
DittoTcpListenConfig tcpListenConfig = new DittoTcpListenConfig();
tcpListenConfig.setEnabled(true);
tcpListenConfig.setInterfaceIp("0.0.0.0");
tcpListenConfig.setPort(4000);
listen.setTcp(tcpListenConfig);
config.setListen(listen);
// 3. Connect explicitly to remote devices
DittoConnect connect = new DittoConnect();
connect.setTcpServers(Sets.newHashSet("135.1.5.5:12345", "185.1.5.5:12345"));
config.setConnect(connect);

try {
    ditto.startSync();
} catch(DittoError error) {
    // handle error
}
```

```csharp
DittoTransportConfig transportConfig = new DittoTransportConfig();

// 1. Enable Local Area Network Connections
transportConfig.EnableAllPeerToPeer();

// 2. Listen for incoming connections on port 4000
transportConfig.Listen.Tcp.Enabled = true;
transportConfig.Listen.Tcp.InterfaceIp = "0.0.0.0";
transportConfig.Listen.Tcp.Port = 4000;

// 3. Connect explicitly to remote devices
transportConfig.Connect.TcpServers.Add("135.1.5.5:12345");
transportConfig.Connect.TcpServers.Add("185.1.5.5:12345");

ditto.TransportConfig = transportConfig;

ditto.StartSync();
```

```cpp
auto config = ditto::TransportConfig();
// 1. Enable All Peer to Peer Connections
config.enable_all_peer_to_peer();

// 2. Listen for incoming connections on port 4000
config.listen.tcp.enabled = true;
config.listen.http.enabled = false;
config.listen.tcp.interface_ip = "0.0.0.0";
config.listen.tcp.port = 4000;

// 3. Connect explicitly to remote devices
config.connect.tcp_servers.insert("135.1.5.5:12345");
config.connect.tcp_servers.insert("185.1.5.5:12345");

ditto.set_transport_config(config);
ditto.start_sync();
```

```rust
let mut config = TransportConfig::new(); // empty

// 1. Enable auto-discovery of peer to peer connections
config.enable_all_peer_to_peer(); // Auto-connect via lan and bluetooth

// 2. Configure TCP Listener
config.listen.tcp.enabled = true;
config.listen.tcp.interface_ip = "0.0.0.0".to_string();
config.listen.tcp.port = 4000;
config.listen.http.enabled = false;

// 3. Configure explicit, hard coded connections
config
    .connect
    .tcp_servers
    .insert("135.1.5.5:12345".to_string()); // Custom TCP Listener
config
    .connect
    .websocket_urls
    .insert("wss://example.com".to_string()); // Custom WS endpoint

ditto.set_transport_config(config);
ditto.start_sync()?;
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Monitoring 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.

:::CodeblockTabs
```swift
// Setting up inside a ViewController
let ditto = Ditto(identity: DittoIdentity.onlinePlayground(appID: "REPLACE_ME_WITH_YOUR_APP_ID", token: "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"))
ditto.delegate = self
try! 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")
       }
   }
```

```kotlin
// ... Setting up inside an Activity
val androidDependencies = DefaultAndroidDittoDependencies(applicationContext)
val ditto = Ditto(androidDependencies, DittoIdentity.OnlinePlayground
(androidDependencies, appId = "REPLACE_WITH_APP_ID", token = "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"))
ditto.callback = this
ditto.startSync()

// Now you can observe real time changes to the transport conditions:

class MainActivity : AppCompatActivity(), DittoCallback {

    override fun transportConditionDidChange(transportId: Long, condition: TransportCondition) {
        var toastText: String? = null
        if (condition == TransportCondition.TRANSPORT_CONDITION_BLE_DISABLED) {
            toastText = "BLE disabled"
        } else if (condition == TransportCondition.TRANSPORT_CONDITION_NO_BLE_CENTRAL_PERMISSION) {
            toastText = "Permission missing for BLE"
        } else if (condition == TransportCondition.TRANSPORT_CONDITION_NO_BLE_PERIPHERAL_PERMISSION) {
            toastText = "Permission missing for BLE"
        }
        toastText?.let {
            Handler(mainLooper).post {
                Toast.makeText(this, it, Toast.LENGTH_LONG).show()
            }
        }
    }
}
```

```javascript
const transportConditionsObserver = ditto.observeTransportConditions((condition, source) => {
  if (condition === 'BLEDisabled') {
    console.log('BLE disabled')
  } else if (condition === 'NoBLECentralPermission') {
    console.log('Permission missing for BLE')
  } else if (condition === 'NoBLEPeripheralPermission') {
    console.log('Permissions missing for BLE')
  }
})
```

```java
// Setting up inside an Activity
DefaultAndroidDittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(getApplicationContext());
Ditto ditto = new Ditto(androidDependencies, new DittoIdentity.OnlinePlayground(androidDependenciesOne, "REPLACE_WITH_APP_ID"));
ditto.callback = this;
ditto.startSync();

// Now you can observe real time changes to the transport conditions:
public class MainActivity extends AppCompatActivity implements DittoCallback {
    @Override
    public void transportConditionDidChange(@NotNull DittoTransportCondition condition, @NotNull DittoConditionSource transportId) {
        String toastText = null;
        if (condition == DittoTransportCondition.BleDisabled) {
            toastText = "BLE disabled";
        } else if (condition == DittoTransportCondition.NoBleCentralPermission) {
            toastText = "Permission missing for BLE";
        } else if (condition == DittoTransportCondition.NoBlePeripheralPermission) {
            toastText = "Permission missing for BLE";
        }

        if (toastText != null) {
            String finalToastText = toastText;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, finalToastText, Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}
```

```csharp
// not supported in C#
```

```cpp
// not supported in C++
```

```rust
// not supported in Rust
```

Dart (beta)

```dart
// Coming Soon
```
:::

