# Unified SDK

Allows to use different VPN protocols inside one app and switch between them more easily.

Unified SDK provides two modes of operation:

* [Manual switching](#manual-switching)
* [Auto switching](#auto-switching)

## API Documentation

To see all available API, check [API Reference](https://pango.gitbook.io/paas/sdk/unified-vpn-sdk-for-apple/api-reference).

## Use Cases

### Integration

The Unified SDK supports all protocols available in the single protocol SDK: Hydra, IPSec, and WireGuard. To integrate the Unified SDK:

1. Configure your application target
2. Configure a separate network extension target for each protocol you want to support

### Manual switching

Manual switching mode provides ability to change VPN protocol at any moment by user requirement.

#### Configure manual switching

```swift
import VPNApplicationSDK
```

```swift
let groupData = VPNGroupData(
    groupID: "group.com.yourcompany.vpnsdk-demo",
    usesSystemExtension: false
)

let fireshieldConfig = FireshieldConfig(
    mode: .disabled,
    groupData: groupData
)

let configuration = ComposedConfiguration(
    availableTypes: [
        .hydra(extensionBundleID: "HYDRA_NETWORK_EXTENSION_BUNDLE_ID"),
        .ipsec
    ],
    carrierID: "CARRIER_ID",
    groupData: VPNGroupData(
        groupID: "group.GROUP_ID",
        usesSystemExtension: false
    ),
    trafficCountersFetchInterval: nil,
    profileName: "PROFILE_NAME",
    fireshieldConfig: fireshieldConfig,
    isVPNIconFixEnabled: true
)

let initialProtocolType = VPNProtocolType.hydra // This protocol will be set as active after SDK init

let unifiedSDK = ManualSwitchingVPNSDK(configuration: configuration, initialProtocolType: initialProtocolType)
```

Unified SDK requires that at least 2 different available SDK types should be provided to configuration. For instance, in order to use Hydra and IPSec protocols together you can specify the above configuration.

The recommended place to initialize the SDK is in your AppDelegate's `application:didFinishLaunchingWithOptions:` method.

#### Switch VPN protocol manually

You can use `func switchToProtocol(_ newProtocolType: VPNProtocolType, completion: ((_ error: Error?, _ activeSDK: VPNSDK?) -> Void)?)` method to change VPN protocol. If VPN is connected at the moment of call, it will be stopped and then reconnected to the same location after protocol change. This method also provides logic that helps to resolve some annoying problems related to protocols changing (e.g., unwanted **On Demand** functionality from old protocol).

**Important:** When calling `stop()` on the SDK, On Demand functionality is automatically disabled (sets `isOnDemandEnabled` to `false`) to ensure explicit control over VPN connections. For advanced On Demand configuration and workarounds to maintain persistent On Demand behavior, see the [Reconnection Strategy](https://pango.gitbook.io/paas/sdk/unified-vpn-sdk-for-apple/features/reconnection-strategy) documentation.

### Auto switching

Auto switching mode modifies VPN start flow in a way when it can fallback to different VPN protocols depending on provided protocol priority.

#### Configure auto switching

```swift
import VPNApplicationSDK
```

```swift
let groupData = VPNGroupData(
    groupID: "group.com.yourcompany.vpnsdk-demo",
    usesSystemExtension: false
)

let fireshieldConfig = FireshieldConfig(
    mode: .disabled,
    groupData: groupData
)

let configuration = ComposedConfiguration(
    availableTypes: [
        .hydra(extensionBundleID: "HYDRA_NETWORK_EXTENSION_BUNDLE_ID"),
        .ipsec
    ],
    carrierID: "CARRIER_ID",
    groupData: VPNGroupData(
        groupID: "group.GROUP_ID",
        usesSystemExtension: false
    ),
    trafficCountersFetchInterval: nil,
    profileName: "PROFILE_NAME",
    fireshieldConfig: fireshieldConfig,
    isVPNIconFixEnabled: true
)

let initialProtocolType = VPNProtocolType.hydra

let manualSwitchingSDK = ManualSwitchingVPNSDK(configuration: configuration, initialProtocolType: initialProtocolType)

// This closure determines the order in which VPN protocols will be attempted during connection
let priorityProvider: AutoSwitchingVPNSDK.PriorityProvider = {
    return [.hydra, .ipsec]
}

let unifiedSDK = AutoSwitchingVPNSDK(manualSwitchingSDK: manualSwitchingSDK, priorityProvider: priorityProvider)
```

Auto switching mode is built on top of manual switching and automatically switches between VPN protocols based on the provided priority configuration. To set it up, first initialize a `ManualSwitchingVPNSDK` instance, then pass it along with a priority provider to the `AutoSwitchingVPNSDK` initializer.

### Logging in

After SDK is initialized, you need to login to be able to start VPN. The recommended authentication method is **Pango Auth**, which provides managed user authentication without requiring you to deploy your own OAuth server.

For detailed information on all authentication methods, see the [Authentication](https://pango.gitbook.io/paas/sdk/unified-vpn-sdk/features/authentication) documentation.

Login example with Pango Auth:

```swift
import VPNApplicationSDK
```

```swift
let groupData = VPNGroupData(
    groupID: "group.com.yourcompany.vpnsdk-demo",
    usesSystemExtension: false
)

let fireshieldConfig = FireshieldConfig(
    mode: .disabled,
    groupData: groupData
)

let configuration = ComposedConfiguration(
    availableTypes: [
        .hydra(extensionBundleID: "HYDRA_NETWORK_EXTENSION_BUNDLE_ID"),
        .ipsec
    ],
    carrierID: "CARRIER_ID",
    groupData: VPNGroupData(
        groupID: "group.GROUP_ID",
        usesSystemExtension: false
    ),
    trafficCountersFetchInterval: nil,
    profileName: "PROFILE_NAME",
    fireshieldConfig: fireshieldConfig,
    isVPNIconFixEnabled: true
)

let initialProtocolType = VPNProtocolType.hydra

let unifiedSDK = ManualSwitchingVPNSDK(configuration: configuration, initialProtocolType: initialProtocolType)

// Pango Auth is the recommended authentication method
let authMethod = AuthMethod(type: .pango, token: "PANGO_ACCESS_TOKEN")

unifiedSDK.login(method: authMethod) { error, user in
    print("isLogged: \(error == nil)")
}
```

See `AuthMethod` in API reference for more authentication methods.

### Connecting VPN and obtaining status

To connect VPN you can use function `start(location:completion:)` (the same as for single protocol SDKs). When VPN is started or an error occurred, completion handler will be called. To obtain VPN connection status you need to subscribe to `vpnStateDidChange` notification provided by SDK. For example:

```swift
NotificationCenter.default.addObserver(forName: .vpnStateDidChange, object: nil, queue: nil) { notification in
    // ...
}
```

When you receive notification, get updated VPN status from SDK instance `state` property and handle this status as designed by your app.

### Active VPN protocol autocorrection

Sometimes you can face situation when value of active protocol type inside SDK became out of sync with actual active protocol type (for example, if you did set active protocol to `.hydra`, but then user started IPSec connection from iOS settings). In such cases SDK will automatically change value of active protocol type to the actual value.

### Detection of protocol change

You can observe VPN protocol changes (both manual and auto) by subscribing to `vpnProtocolDidChange` notification. When you receive notification, get updated protocol type from `activeProtocolType` SDK instance property.
