Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| edde27a0a0 | |||
| cfff596c30 | |||
| ba1c968cdf | |||
| c48406ac38 | |||
| 14437477e6 | |||
| 68d928192b | |||
| 028e76eb3f | |||
| cb0c965294 | |||
| d7ce621cb2 | |||
| a1ca4f6eb5 | |||
| 437f0dc46d | |||
| 547eabb4ae | |||
| bb16d3ebc8 | |||
| 1b6170cbc9 | |||
| 4c37a4b7a7 |
+2
-2
@@ -136,5 +136,5 @@ Here's an example WireGuard configuration payload dictionary:
|
||||
|
||||
Configurations added via .mobileconfig will not be migrated into keychain until the WireGuard application is opened once.
|
||||
|
||||
[wg-quick(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
|
||||
[wg(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
|
||||
[wg-quick(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
|
||||
[wg(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
|
||||
|
||||
@@ -18,7 +18,7 @@ $ cp WireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/
|
||||
$ vim WireGuard/WireGuard/Config/Developer.xcconfig
|
||||
```
|
||||
|
||||
- Install swiftlint and go:
|
||||
- Install swiftlint and go 1.13.4:
|
||||
|
||||
```
|
||||
$ brew install swiftlint go
|
||||
|
||||
@@ -43,7 +43,7 @@ extension Endpoint {
|
||||
|
||||
init?(from string: String) {
|
||||
// Separation of host and port is based on 'parse_endpoint' function in
|
||||
// https://git.zx2c4.com/WireGuard/tree/src/tools/config.c
|
||||
// https://git.zx2c4.com/wireguard-tools/tree/src/config.c
|
||||
guard !string.isEmpty else { return nil }
|
||||
let startOfPort: String.Index
|
||||
let hostString: String
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
VERSION_NAME = 0.0.20191012
|
||||
VERSION_ID = 14
|
||||
VERSION_NAME = 0.0.20200127
|
||||
VERSION_ID = 17
|
||||
|
||||
@@ -20,17 +20,23 @@ protocol TunnelsManagerActivationDelegate: class {
|
||||
}
|
||||
|
||||
class TunnelsManager {
|
||||
private var tunnels: [TunnelContainer]
|
||||
fileprivate var tunnels: [TunnelContainer]
|
||||
weak var tunnelsListDelegate: TunnelsManagerListDelegate?
|
||||
weak var activationDelegate: TunnelsManagerActivationDelegate?
|
||||
private var statusObservationToken: AnyObject?
|
||||
private var waiteeObservationToken: AnyObject?
|
||||
private var configurationsObservationToken: AnyObject?
|
||||
private var catalinaWorkaround: Any?
|
||||
|
||||
init(tunnelProviders: [NETunnelProviderManager]) {
|
||||
tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) }
|
||||
startObservingTunnelStatuses()
|
||||
startObservingTunnelConfigurations()
|
||||
#if os(macOS)
|
||||
if #available(macOS 10.15, *) {
|
||||
self.catalinaWorkaround = CatalinaWorkaround(tunnelsManager: self)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static func create(completionHandler: @escaping (Result<TunnelsManager, TunnelsManagerError>) -> Void) {
|
||||
@@ -75,7 +81,15 @@ class TunnelsManager {
|
||||
tunnelManagers.remove(at: index)
|
||||
}
|
||||
}
|
||||
#if os(macOS)
|
||||
if #available(macOS 10.15, *) {
|
||||
// Don't delete orphaned keychain refs. We need them to restore tunnels as a workaround.
|
||||
} else {
|
||||
Keychain.deleteReferences(except: refs)
|
||||
}
|
||||
#else
|
||||
Keychain.deleteReferences(except: refs)
|
||||
#endif
|
||||
#if os(iOS)
|
||||
RecentTunnelsTracker.cleanupTunnels(except: tunnelNames)
|
||||
#endif
|
||||
@@ -622,7 +636,7 @@ class TunnelContainer: NSObject {
|
||||
}
|
||||
|
||||
extension NETunnelProviderManager {
|
||||
private static var cachedConfigKey: UInt8 = 0
|
||||
fileprivate static var cachedConfigKey: UInt8 = 0
|
||||
|
||||
var tunnelConfiguration: TunnelConfiguration? {
|
||||
if let cached = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey) as? TunnelConfiguration {
|
||||
@@ -645,3 +659,148 @@ extension NETunnelProviderManager {
|
||||
return localizedDescription == tunnel.name && tunnelConfiguration == tunnel.tunnelConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
@available(macOS 10.15, *)
|
||||
class CatalinaWorkaround {
|
||||
|
||||
// In macOS Catalina, for some users, the tunnels get deleted arbitrarily
|
||||
// by the OS. It's not clear what triggers that.
|
||||
|
||||
// As a workaround, in macOS Catalina, when we realize that tunnels have been
|
||||
// deleted outside the app, we reinstate those tunnels using the information
|
||||
// in the keychain.
|
||||
|
||||
unowned let tunnelsManager: TunnelsManager
|
||||
private var configChangeSubscriber: Any?
|
||||
|
||||
struct ReinstationData {
|
||||
let tunnelConfiguration: TunnelConfiguration
|
||||
let keychainPasswordRef: Data
|
||||
}
|
||||
|
||||
init(tunnelsManager: TunnelsManager) {
|
||||
self.tunnelsManager = tunnelsManager
|
||||
|
||||
// Attempt reinstation when there's a change in tunnel configurations,
|
||||
// which indicates that tunnels may have been deleted outside the app.
|
||||
// We use debounce to wait for all change notifications to arrive
|
||||
// before attempting to reinstate, so that we don't have saveToPreferences
|
||||
// being called while another saveToPreferences is in progress.
|
||||
self.configChangeSubscriber = NotificationCenter.default
|
||||
.publisher(for: .NEVPNConfigurationChange, object: nil)
|
||||
.debounce(for: .seconds(1), scheduler: RunLoop.main)
|
||||
.subscribe(on: RunLoop.main)
|
||||
.sink { [weak self] _ in
|
||||
self?.reinstateTunnelsDeletedOutsideApp()
|
||||
}
|
||||
|
||||
// Attempt reinstation on app launch
|
||||
reinstateTunnelsDeletedOutsideApp()
|
||||
}
|
||||
|
||||
func reinstateTunnelsDeletedOutsideApp() {
|
||||
let rd = reinstationDataForTunnelsDeletedOutsideApp()
|
||||
reinstateTunnels(ArraySlice(rd), completionHandler: nil)
|
||||
}
|
||||
|
||||
private func reinstateTunnels(_ rdArray: ArraySlice<ReinstationData>, completionHandler: (() -> Void)?) {
|
||||
guard let head = rdArray.first else {
|
||||
completionHandler?()
|
||||
return
|
||||
}
|
||||
let tail = rdArray.dropFirst()
|
||||
self.tunnelsManager.reinstateTunnel(reinstationData: head) { _ in
|
||||
DispatchQueue.main.async {
|
||||
self.reinstateTunnels(tail, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func reinstationDataForTunnelsDeletedOutsideApp() -> [ReinstationData] {
|
||||
let knownRefs: [Data] = self.tunnelsManager.tunnels
|
||||
.compactMap { $0.tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol }
|
||||
.compactMap { $0.passwordReference }
|
||||
let knownRefsSet: Set<Data> = Set(knownRefs)
|
||||
var result: CFTypeRef?
|
||||
let ret = SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrService as String: Bundle.main.bundleIdentifier as Any,
|
||||
kSecMatchLimit as String: kSecMatchLimitAll,
|
||||
kSecReturnAttributes as String: true,
|
||||
kSecReturnPersistentRef as String: true] as CFDictionary,
|
||||
&result)
|
||||
guard ret == errSecSuccess, let resultDicts = result as? [[String: Any]] else { return [] }
|
||||
let labelPrefix = "WireGuard Tunnel: "
|
||||
var reinstationData: [ReinstationData] = []
|
||||
for resultDict in resultDicts {
|
||||
guard let ref = resultDict[kSecValuePersistentRef as String] as? Data else { continue }
|
||||
guard let label = resultDict[kSecAttrLabel as String] as? String else { continue }
|
||||
guard label.hasPrefix(labelPrefix) else { continue }
|
||||
if !knownRefsSet.contains(ref) {
|
||||
let tunnelName = String(label.dropFirst(labelPrefix.count))
|
||||
if let configStr = Keychain.openReference(called: ref),
|
||||
let config = try? TunnelConfiguration(fromWgQuickConfig: configStr, called: tunnelName) {
|
||||
reinstationData.append(ReinstationData(tunnelConfiguration: config, keychainPasswordRef: ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
return reinstationData
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if os(macOS)
|
||||
@available(macOS 10.15, *)
|
||||
extension TunnelsManager {
|
||||
fileprivate func reinstateTunnel(reinstationData: CatalinaWorkaround.ReinstationData, completionHandler: @escaping (Bool) -> Void) {
|
||||
let tunnelName = reinstationData.tunnelConfiguration.name ?? ""
|
||||
if tunnelName.isEmpty {
|
||||
completionHandler(false)
|
||||
return
|
||||
}
|
||||
|
||||
if tunnels.contains(where: { $0.name == tunnelName }) {
|
||||
completionHandler(false)
|
||||
return
|
||||
}
|
||||
|
||||
let tunnelProviderProtocol = NETunnelProviderProtocol()
|
||||
guard let appId = Bundle.main.bundleIdentifier else { fatalError() }
|
||||
tunnelProviderProtocol.providerBundleIdentifier = "\(appId).network-extension"
|
||||
tunnelProviderProtocol.passwordReference = reinstationData.keychainPasswordRef
|
||||
tunnelProviderProtocol.providerConfiguration = ["UID": getuid()]
|
||||
tunnelProviderProtocol.serverAddress = {
|
||||
let endpoints = reinstationData.tunnelConfiguration.peers.compactMap { $0.endpoint }
|
||||
if endpoints.count == 1 {
|
||||
return endpoints[0].stringRepresentation
|
||||
} else if endpoints.isEmpty {
|
||||
return "Unspecified"
|
||||
} else {
|
||||
return "Multiple endpoints"
|
||||
}
|
||||
}()
|
||||
|
||||
let tunnelProvider = NETunnelProviderManager()
|
||||
tunnelProvider.localizedDescription = tunnelName
|
||||
tunnelProvider.protocolConfiguration = tunnelProviderProtocol
|
||||
objc_setAssociatedObject(tunnelProvider, &NETunnelProviderManager.cachedConfigKey, reinstationData.tunnelConfiguration, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
tunnelProvider.isEnabled = true
|
||||
|
||||
tunnelProvider.saveToPreferences { [weak self] error in
|
||||
guard error == nil else {
|
||||
wg_log(.error, message: "Reinstate: Saving configuration failed: \(error!)")
|
||||
completionHandler(false)
|
||||
return
|
||||
}
|
||||
|
||||
guard let self = self else { return }
|
||||
|
||||
let tunnel = TunnelContainer(tunnel: tunnelProvider)
|
||||
self.tunnels.append(tunnel)
|
||||
self.tunnels.sort { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) }
|
||||
self.tunnelsListDelegate?.tunnelAdded(at: self.tunnels.firstIndex(of: tunnel)!)
|
||||
completionHandler(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
|
||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||
window.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
window.backgroundColor = .systemBackground
|
||||
} else {
|
||||
window.backgroundColor = .white
|
||||
}
|
||||
self.window = window
|
||||
|
||||
let mainVC = MainViewController()
|
||||
|
||||
@@ -9,8 +9,8 @@ class ButtonCell: UITableViewCell {
|
||||
set(value) { button.setTitle(value, for: .normal) }
|
||||
}
|
||||
var hasDestructiveAction: Bool {
|
||||
get { return button.tintColor == .red }
|
||||
set(value) { button.tintColor = value ? .red : buttonStandardTintColor }
|
||||
get { return button.tintColor == .systemRed }
|
||||
set(value) { button.tintColor = value ? .systemRed : buttonStandardTintColor }
|
||||
}
|
||||
var onTapped: (() -> Void)?
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@ class KeyValueCell: UITableViewCell {
|
||||
let keyLabel = UILabel()
|
||||
keyLabel.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
keyLabel.adjustsFontForContentSizeCategory = true
|
||||
keyLabel.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
keyLabel.textColor = .label
|
||||
} else {
|
||||
keyLabel.textColor = .black
|
||||
}
|
||||
keyLabel.textAlignment = .left
|
||||
return keyLabel
|
||||
}()
|
||||
@@ -31,7 +35,11 @@ class KeyValueCell: UITableViewCell {
|
||||
valueTextField.autocapitalizationType = .none
|
||||
valueTextField.autocorrectionType = .no
|
||||
valueTextField.spellCheckingType = .no
|
||||
valueTextField.textColor = .gray
|
||||
if #available(iOS 13.0, *) {
|
||||
valueTextField.textColor = .secondaryLabel
|
||||
} else {
|
||||
valueTextField.textColor = .gray
|
||||
}
|
||||
return valueTextField
|
||||
}()
|
||||
|
||||
@@ -56,10 +64,18 @@ class KeyValueCell: UITableViewCell {
|
||||
|
||||
var isValueValid = true {
|
||||
didSet {
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .label
|
||||
} else {
|
||||
keyLabel.textColor = .systemRed
|
||||
}
|
||||
} else {
|
||||
keyLabel.textColor = .red
|
||||
if isValueValid {
|
||||
keyLabel.textColor = .black
|
||||
} else {
|
||||
keyLabel.textColor = .red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,11 @@ class SwitchCell: UITableViewCell {
|
||||
get { return switchView.isEnabled }
|
||||
set(value) {
|
||||
switchView.isEnabled = value
|
||||
textLabel?.textColor = value ? .black : .gray
|
||||
if #available(iOS 13.0, *) {
|
||||
textLabel?.textColor = value ? .label : .secondaryLabel
|
||||
} else {
|
||||
textLabel?.textColor = value ? .black : .gray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,11 @@ class TextCell: UITableViewCell {
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
message = ""
|
||||
setTextColor(.black)
|
||||
if #available(iOS 13.0, *) {
|
||||
setTextColor(.label)
|
||||
} else {
|
||||
setTextColor(.black)
|
||||
}
|
||||
setTextAlignment(.left)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,11 @@ class TunnelEditEditableKeyValueCell: TunnelEditKeyValueCell {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
copyableGesture = false
|
||||
valueTextField.textColor = .black
|
||||
if #available(iOS 13.0, *) {
|
||||
valueTextField.textColor = .label
|
||||
} else {
|
||||
valueTextField.textColor = .black
|
||||
}
|
||||
valueTextField.isEnabled = true
|
||||
valueLabelScrollView.isScrollEnabled = false
|
||||
valueTextField.widthAnchor.constraint(equalTo: valueLabelScrollView.widthAnchor).isActive = true
|
||||
|
||||
@@ -29,9 +29,15 @@ class TunnelListCell: UITableViewCell {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
if #available(iOS 13.0, *) {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
} else {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}
|
||||
}()
|
||||
|
||||
let statusSwitch = UISwitch()
|
||||
|
||||
@@ -15,9 +15,15 @@ class LogViewController: UIViewController {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
if #available(iOS 13.0, *) {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
} else {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}
|
||||
}()
|
||||
|
||||
let paragraphStyle: NSParagraphStyle = {
|
||||
@@ -35,7 +41,11 @@ class LogViewController: UIViewController {
|
||||
|
||||
override func loadView() {
|
||||
view = UIView()
|
||||
view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
view.backgroundColor = .white
|
||||
}
|
||||
|
||||
view.addSubview(textView)
|
||||
textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -81,12 +91,18 @@ class LogViewController: UIViewController {
|
||||
let richText = NSMutableAttributedString()
|
||||
let bodyFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
|
||||
let captionFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.caption1)
|
||||
let lightGrayColor = UIColor(white: 0.88, alpha: 1.0)
|
||||
|
||||
for logEntry in fetchedLogEntries {
|
||||
let bgColor = self.isNextLineHighlighted ? lightGrayColor : UIColor.white
|
||||
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
|
||||
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
|
||||
var bgColor: UIColor
|
||||
var fgColor: UIColor
|
||||
if #available(iOS 13.0, *) {
|
||||
bgColor = self.isNextLineHighlighted ? .systemGray3 : .systemBackground
|
||||
fgColor = .label
|
||||
} else {
|
||||
bgColor = self.isNextLineHighlighted ? UIColor(white: 0.88, alpha: 1.0) : UIColor.white
|
||||
fgColor = .black
|
||||
}
|
||||
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
|
||||
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
|
||||
richText.append(timestampText)
|
||||
richText.append(messageText)
|
||||
self.isNextLineHighlighted.toggle()
|
||||
|
||||
@@ -11,7 +11,11 @@ class MainViewController: UISplitViewController {
|
||||
|
||||
init() {
|
||||
let detailVC = UIViewController()
|
||||
detailVC.view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
detailVC.view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
detailVC.view.backgroundColor = .white
|
||||
}
|
||||
let detailNC = UINavigationController(rootViewController: detailVC)
|
||||
|
||||
let masterVC = TunnelsListTableViewController()
|
||||
|
||||
@@ -176,7 +176,11 @@ extension SSIDOptionEditTableViewController {
|
||||
private func noSSIDsCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell: TextCell = tableView.dequeueReusableCell(for: indexPath)
|
||||
cell.message = tr("tunnelOnDemandNoSSIDs")
|
||||
cell.setTextColor(.gray)
|
||||
if #available(iOS 13.0, *) {
|
||||
cell.setTextColor(.secondaryLabel)
|
||||
} else {
|
||||
cell.setTextColor(.gray)
|
||||
}
|
||||
cell.setTextAlignment(.center)
|
||||
return cell
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class TunnelDetailTableViewController: UITableViewController {
|
||||
let editVC = TunnelEditTableViewController(tunnelsManager: self.tunnelsManager, tunnel: self.tunnel)
|
||||
editVC.delegate = self
|
||||
let editNC = UINavigationController(rootViewController: editVC)
|
||||
editNC.modalPresentationStyle = .formSheet
|
||||
editNC.modalPresentationStyle = .fullScreen
|
||||
self.present(editNC, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,15 @@ class TunnelsListTableViewController: UIViewController {
|
||||
}()
|
||||
|
||||
let busyIndicator: UIActivityIndicatorView = {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
if #available(iOS 13.0, *) {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .medium)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
} else {
|
||||
let busyIndicator = UIActivityIndicatorView(style: .gray)
|
||||
busyIndicator.hidesWhenStopped = true
|
||||
return busyIndicator
|
||||
}
|
||||
}()
|
||||
|
||||
var detailDisplayedTunnel: TunnelContainer?
|
||||
@@ -46,7 +52,11 @@ class TunnelsListTableViewController: UIViewController {
|
||||
|
||||
override func loadView() {
|
||||
view = UIView()
|
||||
view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
view.backgroundColor = .white
|
||||
}
|
||||
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
@@ -178,7 +188,7 @@ class TunnelsListTableViewController: UIViewController {
|
||||
func presentViewControllerForTunnelCreation(tunnelsManager: TunnelsManager) {
|
||||
let editVC = TunnelEditTableViewController(tunnelsManager: tunnelsManager)
|
||||
let editNC = UINavigationController(rootViewController: editVC)
|
||||
editNC.modalPresentationStyle = .formSheet
|
||||
editNC.modalPresentationStyle = .fullScreen
|
||||
present(editNC, animated: true)
|
||||
}
|
||||
|
||||
@@ -389,7 +399,11 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
|
||||
(splitViewController.viewControllers[0] as? UINavigationController)?.popToRootViewController(animated: false)
|
||||
} else {
|
||||
let detailVC = UIViewController()
|
||||
detailVC.view.backgroundColor = .white
|
||||
if #available(iOS 13.0, *) {
|
||||
detailVC.view.backgroundColor = .systemBackground
|
||||
} else {
|
||||
detailVC.view.backgroundColor = .white
|
||||
}
|
||||
let detailNC = UINavigationController(rootViewController: detailVC)
|
||||
splitViewController.showDetailViewController(detailNC, sender: self)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ $(GOROOT)/.prepared:
|
||||
[ -n "$(REAL_GOROOT)" ]
|
||||
mkdir -p "$(GOROOT)"
|
||||
rsync -a --delete --exclude=pkg/obj/go-build "$(REAL_GOROOT)/" "$(GOROOT)/"
|
||||
patch -p1 -f -N -r- -d "$(GOROOT)" < goruntime-boottime-over-monotonic.diff
|
||||
cat goruntime-*.diff | patch -p1 -f -N -r- -d "$(GOROOT)"
|
||||
touch "$@"
|
||||
|
||||
define libwg-go-a
|
||||
|
||||
@@ -165,6 +165,7 @@ func wgGetConfig(tunnelHandle int32) *C.char {
|
||||
writer.Flush()
|
||||
return C.CString(settings.String())
|
||||
}
|
||||
|
||||
//export wgBumpSockets
|
||||
func wgBumpSockets(tunnelHandle int32) {
|
||||
device, ok := tunnelHandles[tunnelHandle]
|
||||
|
||||
@@ -3,7 +3,8 @@ module golang.zx2c4.com/wireguard/ios
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954 // indirect
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be
|
||||
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8
|
||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad // indirect
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
|
||||
golang.zx2c4.com/wireguard v0.0.20200121
|
||||
)
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg=
|
||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191003171128-d98b1b443823 h1:Ypyv6BNJh07T1pUSrehkLemqPKXhus2MkfktJ91kRh4=
|
||||
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954 h1:JGZucVF/L/TotR719NbujzadOZ2AgnYlqphQGHDCKaU=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c h1:6Zx7DRlKXf79yfxuQ/7GqV3w2y7aDsk6bGg0MzF5RVU=
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8 h1:BqfQHKZLrdq0j5Z/R9coISbr1nYcSE+3BdyF5LidO+g=
|
||||
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
|
||||
golang.zx2c4.com/wireguard v0.0.20200121 h1:vcswa5Q6f+sylDfjqyrVNNrjsFUUbPsgAQTBCAg/Qf8=
|
||||
golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
|
||||
|
||||
Reference in New Issue
Block a user