blob: 7482018b97119c7a9574f30f7398ec49d86a347b (
plain)
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
|
//
// ShadowsocksConfigurationCache.swift
// MullvadTransport
//
// Created by Marco Nikic on 2023-06-05.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import Foundation
import MullvadTypes
public protocol ShadowsocksConfigurationCacheProtocol: Sendable {
func read() throws -> ShadowsocksConfiguration
func write(_ configuration: ShadowsocksConfiguration) throws
func clear() throws
}
/// Holds a shadowsocks configuration object backed by a caching mechanism shared across processes
public final class ShadowsocksConfigurationCache: ShadowsocksConfigurationCacheProtocol, @unchecked Sendable {
private let configurationLock = NSLock()
private var cachedConfiguration: ShadowsocksConfiguration?
private let fileCache: FileCache<ShadowsocksConfiguration>
public init(cacheDirectory: URL) {
fileCache = FileCache(
fileURL: cacheDirectory.appendingPathComponent("shadowsocks-cache.json", isDirectory: false)
)
}
/// Returns configuration from memory cache if available, otherwise attempts to load it from disk cache before
/// returning.
public func read() throws -> ShadowsocksConfiguration {
configurationLock.lock()
defer { configurationLock.unlock() }
if let cachedConfiguration {
return cachedConfiguration
} else {
let readConfiguration = try fileCache.read()
cachedConfiguration = readConfiguration
return readConfiguration
}
}
/// Replace memory cache with new configuration and attempt to persist it on disk.
public func write(_ configuration: ShadowsocksConfiguration) throws {
configurationLock.lock()
defer { configurationLock.unlock() }
cachedConfiguration = configuration
try fileCache.write(configuration)
}
/// Clear cached configuration.
public func clear() throws {
configurationLock.lock()
defer { configurationLock.unlock() }
cachedConfiguration = nil
try fileCache.clear()
}
}
|