1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
//
// MullvadApiContext.swift
// MullvadVPN
//
// Created by Jon Petersson on 2025-01-24.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import MullvadTypes
func onAccessChangeCallback(selfPtr: UnsafeRawPointer?, bytes: UnsafePointer<UInt8>?) {
guard let selfPtr, let bytes else { return }
let context = Unmanaged<MullvadApiContext>.fromOpaque(selfPtr).takeUnretainedValue()
let uuid = NSUUID(uuidBytes: bytes) as UUID
context.accessMethodChangeListeners.forEach { $0.accessMethodChangedTo(uuid) }
}
public class MullvadApiContext: @unchecked Sendable {
enum Error: Swift.Error {
case failedToConstructApiClient
}
public private(set) var context: SwiftApiContext!
private let shadowsocksBridgeProvider: SwiftShadowsocksBridgeProviding!
private let shadowsocksBridgeProviderWrapper: SwiftShadowsocksLoaderWrapper!
private let addressCacheWrapper: SwiftAddressCacheWrapper!
private let addressCacheProvider: AddressCacheProviding!
public let accessMethodChangeListeners: [MullvadAccessMethodChangeListening]
public init(
host: String,
address: String,
domain: String,
disableTls: Bool = false,
shadowsocksProvider: SwiftShadowsocksBridgeProviding,
accessMethodWrapper: SwiftAccessMethodSettingsWrapper,
addressCacheProvider: AddressCacheProviding,
accessMethodChangeListeners: [MullvadAccessMethodChangeListening]
) throws {
let bridgeProvider = SwiftShadowsocksBridgeProvider(provider: shadowsocksProvider)
self.shadowsocksBridgeProvider = bridgeProvider
self.shadowsocksBridgeProviderWrapper = initMullvadShadowsocksBridgeProvider(provider: bridgeProvider)
let defaultAddressCache = DefaultAddressCacheProvider(provider: addressCacheProvider)
self.addressCacheProvider = defaultAddressCache
self.addressCacheWrapper = iniSwiftAddressCacheWrapper(provider: defaultAddressCache)
self.accessMethodChangeListeners = accessMethodChangeListeners
let selfPtr = Unmanaged.passUnretained(self).toOpaque()
context =
switch disableTls {
case true:
mullvad_api_init_new_tls_disabled(
host,
address,
domain,
shadowsocksBridgeProviderWrapper,
accessMethodWrapper,
addressCacheWrapper,
onAccessChangeCallback,
selfPtr
)
case false:
mullvad_api_init_new(
host,
address,
domain,
shadowsocksBridgeProviderWrapper,
accessMethodWrapper,
addressCacheWrapper,
onAccessChangeCallback,
selfPtr
)
}
if context._0 == nil {
throw Error.failedToConstructApiClient
}
}
}
extension SwiftApiContext: @unchecked @retroactive Sendable {}
|