# Manage Connection

The **VPN SDK** provides a set of APIs to allow your users to establish and teardown a VPN connection with a server.

## Establish a Connection

A connection to a server is established by calling the connect to server API using a server selected from the list servers API call.

{% hint style="info" %}
In order to establish a connection, a [SudoVPNServer](/guides/virtual-private-network/manage-servers.md#retrieving-servers) is required.
{% endhint %}

### Connection Configuration

Connection configuration is decided at the time of calling the connect API. It is up to you to build up a `SudoVPNConfiguration` object.

#### SudoVPNConfiguration

| Property     | Description                                                                                                  |
| ------------ | ------------------------------------------------------------------------------------------------------------ |
| server       | The [SudoVPNServer](/guides/virtual-private-network/manage-servers.md) that the client will/is connected to. |
| protocolType | The [SudoVPNProtocol](#protocol-types) that the client will/is using to connect to the VPN.                  |

{% hint style="info" %}
When the disconnect API is called, the configured server will be set back to undefined.
{% endhint %}

Both `server` and `protocolType` can be left as undefined. In the case that `server` is left undefined, the best server will be attempted to connect to, using the user's current geographical location. If `protocolType` is left undefined, the default protocol (`IPSec (IKEv2)` on mobile) will be used.

#### Protocol Types

When connecting to a VPN, a couple of different Protocol types are available. Depending on the platform, only a subset of these types may be supported.

{% hint style="warning" %}
In a scenario where network is lost whilst connected to an IPSec (IKEv2) or UDP protocol, the VPN tunnel will remain open. This allows the connection to stay open if there are changes in the network (i.e. moving from Wi-Fi to Mobile Data).
{% endhint %}

<table><thead><tr><th>Protocol</th><th>Description</th><th width="104.27734375">iOS</th><th>Android</th><th>macOS</th><th>Windows</th></tr></thead><tbody><tr><td>L2TP</td><td><a href="https://en.wikipedia.org/wiki/Layer_2_Tunneling_Protocol">Layer 2 Tunnel Protocol</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td></tr><tr><td>PPTP</td><td><a href="https://en.wikipedia.org/wiki/Point-to-Point_Tunneling_Protocol">Point-To-Point Tunnelling Protocol</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td></tr><tr><td>IPSec</td><td><a href="https://en.wikipedia.org/wiki/IPsec">Internet Protocol Security</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td></tr><tr><td>IPSec (IKEv2)</td><td><a href="https://en.wikipedia.org/wiki/Internet_Key_Exchange#Improvements_with_IKEv2">Internet Key Exchange V2</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td></tr><tr><td>OpenVPN UDP</td><td><a href="https://en.wikipedia.org/wiki/OpenVPN">Open VPN over UDP</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td></tr><tr><td>OpenVPN TCP</td><td><a href="https://en.wikipedia.org/wiki/OpenVPN">Open VPN over TCP</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td></tr><tr><td>WireGuard</td><td><a href="https://en.wikipedia.org/wiki/WireGuard">Wire Guard</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td><td><a href="https://emojipedia.org/cross-mark/">❌</a></td><td><a href="https://emojipedia.org/check-mark-button/">✅</a></td></tr></tbody></table>

{% tabs %}
{% tab title="iOS" %}
In order to see which protocols are currently available via the client, use the `supportedProtocols()` method. This method returns the list of supported protocols mentioned above currently available to the device calling the method.

An example implementation is:

```swift
let supportedProtocols = vpnClient.supportedProtocols()
/// `supportedProtocols` contains an array of the protocols that can be used.
```

{% endtab %}

{% tab title="Android" %}
The `listSupportedProtocols` method is used to return a list of of supported protocols used as part of configuring a connection that are currently available to the client calling the method.

An example implementation of this is:

```kotlin
val supportedProtocols = vpnClient.listSupportedProtocols()
// [supportedProtocols] contains a list of protocols that can be used to configure a connection.
```

{% endtab %}

{% tab title="TypeScript" %}

The `listSupportedProtocols` method is used to return a list of of supported protocols used as part of configuring a connection that are currently available to the client calling the method.

An example implementation of this is:

```typescript
const supportedProtocols = vpnClient.listSupportedProtocols()
// [supportedProtocols] contains a list of protocols that can be used to configure a connection
```

Note that the set of protocols supported on Windows is different than macOS.
{% endtab %}
{% endtabs %}

### Connect to the VPN

{% tabs %}
{% tab title="iOS" %}
To connect to the VPN, use the `connect(withConfiguration:completion:)` method. The `completion` will be called either when the connection process has successfully begun, or an error occurred while attempting to do so.

{% hint style="info" %}
If `configuration` is `nil`, the best server, and default protocol type will be used.
{% endhint %}

An example implementation of calling the connect method is:

```swift
vpnClient.connect { result in
    switch result {
    case let .failure(cause):
        /// Handle/notify user of error.
    case .success:
        /// Successfully begun connection. 
}
```

To watch for connection state events to see when the client has successfully connected (or failed to connect), see [Connection Events](/guides/virtual-private-network/observe-vpn-related-events.md#connection-events).

#### Fetch the Last Disconnect Error

If a VPN connection disconnects unexpectedly, you can retrieve the most recent disconnect error using the `fetchLastDisconnectError()` method. This can help diagnose connection failures, authentication issues, or tunnel provider errors.&#x20;

For system-managed VPN protocol types such as IKEv2 or IPSec, the returned error will typically belong to the `NEVPNErrorDomain`.

For custom tunnel-based VPN implementations such as WireGuard, the returned error will be the `NSError` provided by the tunnel provider when the VPN disconnected.
{% endtab %}

{% tab title="Android" %}
The `connect(notification, revokedNotification)` method is used to establish a connection to the VPN network. The `notification` parameter allows you to attach a persistent notification once a connection is established whereas the `revokedNotification` parameter allows you to emit a notification when the VPN is revoked.

{% hint style="info" %}
Before establishing a connection, the `configuration`client property must be set. If `configuration` is `null`, the best server, and default protocol type will be used.
{% endhint %}

Android requires that the application request permission from the user the first time that the application attempts to create a connection with a VPN network.

Before attempting to connect to a VPN network. The `prepare(fragment: Fragment)` / `prepare(activity: Activity)` method must be called. This method will launch an intent containing a VPN connection permission dialogue requiring user action with the result coming back via the fragment or activity `onActivityForResult` method which can be overridden. If the result is `RESULT_OK`, the application is considered prepared. The `isPrepared` method is used to indicate whether the user has previously given permission to connect to VPN networks.

{% hint style="warning" %}
The execution of the prepare method is required in order to perform any VPN connection operations.
{% endhint %}

An example implementation of connecting to a selected server is:

```kotlin
class ConnectionFragment : Fragment(), CoroutineScope {

    companion object {
        private const val VPN_PREPARE = 1000
        private const val NOTIFICATION_ID_VPN_STATUS = 1
        private const val NOTIFICATION_ID_VPN_REVOKED = 2
    }

    // val server: SudoVPNServer // Retrieved via the list servers API
    private fun connect() {
        try {
            if (sudoVPNClient.isPrepared()) {

                // Set the configuration client property with selected [server].
                sudoVPNClient.configuration = SudoVPNConfiguration(server, SudoVPNProtocol.IKEV2, false)

                // Build SudoVPNNotification objects.
                val vpnConnectionNotification = NotificationCompat.Builder(
                    requireContext(),
                    "vpnNotificationChannel"
                )
                    .setSmallIcon(R.drawable.vpn_logo)
                    .build()
                val vpnRevokedNotification = NotificationCompat.Builder(
                    requireContext(),
                    "vpnNotificationChannel"
                )
                    .setSmallIcon(R.drawable.vpn_logo)
                    .build()
                val sudoNotification = SudoVPNNotification(NOTIFICATION_ID_VPN_STATUS, vpnConnectionNotification)
                val sudoRevokedNotification = SudoVPNNotification(NOTIFICATION_ID_VPN_REVOKED, vpnRevokedNotification)

                launch {
                    try {
                        withContext(Dispatchers.IO) {
                            sudoVPNClient.connect(sudoNotification, sudoRevokedNotification)
                        }
                    } catch (e: SudoVPNException) {
                        // Handle/notify user of exception
                    }
                }
            } else {
                sudoVPNClient.prepare(this)
            }
        } catch (e: ActivityNotFoundException) {
            // Handle/notify user if prepare method could not be executed.
        }
    }

    // Handle result from calling [sudoVPNClient.prepare] method.
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == RESULT_OK && requestCode == VPN_PREPARE) {
            connect()
        }
    }
}
```

To watch for connection state events to see when the client has successfully connected (or failed to connect), see Setting up a Subscription in the Android section of the [Observe VPN Related Events](/guides/virtual-private-network/observe-vpn-related-events.md) page.
{% endtab %}

{% tab title="Typescript" %}
To connect to the VPN, use the `connect(configuration?: SudoVPNConfiguration)` method. This method operates synchronously and will return on completion.

{% hint style="info" %}
If `configuration` is undefined, or does not specify a server location or a protocol, the fastest available server, and default protocol type will be used.
{% endhint %}

An example implementation of calling the connect method is:

<pre class="language-typescript"><code class="lang-typescript">try {
    await vpnClient.connect()
} catch (err) {
    // log error and/or retry/recover
}
<strong>if(await vpnClient.getState() == SudoVPNConnectionStatus.connected) {
</strong><strong>    // vpn is connected
</strong><strong>}
</strong></code></pre>

To determine whether the VPN is connected, use the `getState()` method.
{% endtab %}
{% endtabs %}

### Retrieve the Connected Date

After establishing a VPN connection, you can retrieve the timestamp of when the connection was successfully established. This timestamp is useful for displaying connection duration and validating active connections.

{% tabs %}
{% tab title="iOS" %}
The connected date can be retrieved by accessing the `connectedDate` property on the `SudoVPNClient` . A value of `nil` will be returned if the VPN is not connected.

```swift
if let connectedDate = await vpnClient.connectedDate {
    // `connectedDate` is the value of the connection timestamp, or `nil` if not connected.
}
```

{% endtab %}

{% tab title="Android" %}
The connected date can be accessed via the `connectedDate` property on the `SudoVPNClient` . A value of `null` will be returned if the VPN is not connected.

```kotlin
if (vpnClient.connectedDate != null) {
    // `connectedDate` is the value of the connection timestamp, or `null` if not connected.
}
```

{% endtab %}

{% tab title="Typescript" %}
The `getConnectedDate()` method is used to retrieve the timestamp of the active VPN connection. This will return `undefined`  if the VPN is not connected.

```typescript
try {
    const connectedDate = await vpnClient.getConnectedDate()
    // // `connectedDate` is the value of the connection timestamp, or `undefined` if not connected.
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}
{% endtabs %}

## Disconnect from an Established Connection

Once already connected, a user may want to deliberately disconnect, or close the connection as part of a process.

{% tabs %}
{% tab title="iOS" %}
To disconnect from an already established connection, use the `disconnect(completion:)` method.

An example implementation of calling the disconnect method is:

```swift
vpnClient.disconnect { result in
    switch result {
    case let .failure(cause):
        /// Handle/notify user of error.
    case .success:
        /// Successfully disconnected. 
}
```

To watch for connection state events to see when the client has successfully disconnected (or failed to disconnect), see [Connection Events](/guides/virtual-private-network/observe-vpn-related-events.md#connection-events).
{% endtab %}

{% tab title="Android" %}
Disconnecting from an already established connection is performed by calling the `disconnect` method.

An example implementation of performing a disconnection is:

```kotlin
 launch {
     try {
         withContext(Dispatchers.IO) {
            sudoVPNClient.disconnect()
        }
        // The disconnection process has begun.
     } catch (e: SudoVPNException) {
         // Handle/notify user of exception
     }
 }
```

To watch for connection state events to see when the client has successfully disconnected (or failed to disconnect), see Setting up a Subscription in the Android section of the [Observe VPN Related Events](/guides/virtual-private-network/observe-vpn-related-events.md) page.
{% endtab %}

{% tab title="Typescript" %}
Disconnecting from an already established connection is performed by calling the `disconnect` method.

An example implementation of performing a disconnection is:

```typescript
 try {
     await vpnClient.disconnect()
 } catch (err) {
     // Handle/notify user of exception
 }
 if (await vpnClient.getState() == SudoVPNConnectionStatus.disconnected) {
    // vpn is disconnected
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sudoplatform.com/guides/virtual-private-network/manage-connection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
