summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-12-09 16:35:26 +0100
committerAndrej Mihajlov <and@mullvad.net>2019-12-10 11:14:56 +0100
commitde7b23a3f9d90b43dc3575c011d081e928f2e5ac (patch)
tree9e5fff2a5afd5aa94c071df30aa070ba9a5f7222
parent87eeab54df529f6129da48eba32fbbc4c196649d (diff)
downloadmullvadvpn-de7b23a3f9d90b43dc3575c011d081e928f2e5ac.tar.xz
mullvadvpn-de7b23a3f9d90b43dc3575c011d081e928f2e5ac.zip
Wireup Connect controller with the tunnel manager
-rw-r--r--ios/MullvadVPN/ConnectViewController.swift138
1 files changed, 135 insertions, 3 deletions
diff --git a/ios/MullvadVPN/ConnectViewController.swift b/ios/MullvadVPN/ConnectViewController.swift
index d7b615b3fb..8e9c4f09b7 100644
--- a/ios/MullvadVPN/ConnectViewController.swift
+++ b/ios/MullvadVPN/ConnectViewController.swift
@@ -6,27 +6,159 @@
// Copyright © 2019 Amagicom AB. All rights reserved.
//
+import Combine
import UIKit
+import NetworkExtension
+import os
-class ConnectViewController: UIViewController, RootContainment {
+class ConnectViewController: UIViewController, RootContainment, TunnelControlViewControllerDelegate {
+
+ @IBOutlet var secureLabel: UILabel!
+ @IBOutlet var countryLabel: UILabel!
+
+ private var setRelaysSubscriber: AnyCancellable?
+ private var startStopTunnelSubscriber: AnyCancellable?
+ private var tunnelStateSubscriber: AnyCancellable?
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
var preferredHeaderBarStyle: HeaderBarStyle {
- return .unsecured
+ switch tunnelState {
+ case .connecting, .reconnecting, .connected:
+ return .secured
+
+ case .disconnecting, .disconnected:
+ return .unsecured
+ }
+ }
+
+ private var tunnelState: TunnelState = .disconnected {
+ didSet {
+ setNeedsHeaderBarStyleAppearanceUpdate()
+ updateSecureLabel()
+ updateTunnelConnectionInfo()
+ }
}
override func viewDidLoad() {
super.viewDidLoad()
- // Do any additional setup after loading the view, typically from a nib.
+
+ tunnelStateSubscriber = TunnelManager.shared.$tunnelState
+ .receive(on: DispatchQueue.main)
+ .assign(to: \.tunnelState, on: self)
+ }
+
+ override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+ if case .embedTunnelControls = SegueIdentifier.Connect.from(segue: segue) {
+ let tunnelControlController = segue.destination as! TunnelControlViewController
+ tunnelControlController.view.translatesAutoresizingMaskIntoConstraints = false
+ tunnelControlController.delegate = self
+ }
+ }
+
+ // MARK: - TunnelControlViewControllerDelegate
+
+ func tunnelControlViewController(_ controller: TunnelControlViewController, handleAction action: TunnelControlAction) {
+ switch action {
+ case .connect:
+ connectTunnel()
+
+ case .disconnect:
+ disconnectTunnel()
+
+ case .selectLocation:
+ performSegue(withIdentifier: SegueIdentifier.Connect.showRelaySelector.rawValue, sender: self)
+ }
+ }
+
+ // MARK: - Private
+
+ private func updateSecureLabel() {
+ secureLabel.text = tunnelState.textForSecureLabel()
+ secureLabel.textColor = tunnelState.textColorForSecureLabel()
+ }
+
+ private func updateTunnelConnectionInfo() {
+ switch tunnelState {
+ case .connected(let connectionInfo),
+ .reconnecting(let connectionInfo):
+ countryLabel.text = "\(connectionInfo.hostname)\nIn: \(connectionInfo.ipv4Relay)"
+
+ case .connecting, .disconnected, .disconnecting:
+ countryLabel.text = ""
+ }
+ }
+
+ private func connectTunnel() {
+ startStopTunnelSubscriber = TunnelManager.shared.startTunnel()
+ .receive(on: DispatchQueue.main)
+ .sink(receiveCompletion: { (completion) in
+ if case .failure(let error) = completion {
+ os_log(.error, "Failed to start the tunnel: %{public}s", error.localizedDescription)
+ }
+ })
+ }
+
+ private func disconnectTunnel() {
+ startStopTunnelSubscriber = TunnelManager.shared.stopTunnel()
+ .receive(on: DispatchQueue.main)
+ .sink(receiveCompletion: { (_) in
+ // no-op
+ })
}
// MARK: - Actions
@IBAction func unwindFromSelectLocation(segue: UIStoryboardSegue) {
+ guard let selectLocationController = segue.source as? SelectLocationController else { return }
+ guard let selectedItem = selectLocationController.selectedItem else { return }
+
+ let relayConstraints = RelayConstraints(location: .only(selectedItem.relayLocation))
+
+ setRelaysSubscriber = TunnelManager.shared.setRelayConstraints(relayConstraints)
+ .receive(on: DispatchQueue.main)
+ .sink(receiveCompletion: { (completion) in
+ switch completion {
+ case .finished:
+ os_log(.debug, "Updated relay constraints: %{public}s", String(reflecting: relayConstraints))
+ self.connectTunnel()
+
+ case .failure(let error):
+ os_log(.error, "Failed to update relay constraints: %{public}s", error.localizedDescription)
+ }
+ })
+ }
+
+}
+
+private extension TunnelState {
+
+ func textColorForSecureLabel() -> UIColor {
+ switch self {
+ case .connecting, .reconnecting:
+ return .white
+
+ case .connected:
+ return .successColor
+
+ case .disconnecting, .disconnected:
+ return .dangerColor
+ }
+ }
+
+ func textForSecureLabel() -> String {
+ switch self {
+ case .connecting, .reconnecting:
+ return NSLocalizedString("Creating secure connection", tableName: "Connect", comment: "")
+
+ case .connected:
+ return NSLocalizedString("Secure connection", tableName: "Connect", comment: "")
+ case .disconnecting, .disconnected:
+ return NSLocalizedString("Unsecured connection", tableName: "Connect", comment: "")
+ }
}
}