Skip to content

Commit

Permalink
Merge branch 'add-ui-for-blocked-state-ios-322'
Browse files Browse the repository at this point in the history
  • Loading branch information
buggmagnet committed Oct 9, 2023
2 parents bb2caa8 + 845d258 commit 2031cb2
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
//

import Foundation
import PacketTunnelCore

final class TunnelStatusNotificationProvider: NotificationProvider, InAppNotificationProvider {
private var isWaitingForConnectivity = false
private var noNetwork = false
private var packetTunnelError: String?
private var packetTunnelError: BlockedStateReason?
private var tunnelManagerError: Error?
private var tunnelObserver: TunnelBlockObserver?

Expand Down Expand Up @@ -57,7 +58,7 @@ final class TunnelStatusNotificationProvider: NotificationProvider, InAppNotific
private func handleTunnelStatus(_ tunnelStatus: TunnelStatus) {
let invalidateForTunnelError: Bool
if case let .error(blockStateReason) = tunnelStatus.state {
invalidateForTunnelError = updateLastTunnelError(blockStateReason.rawValue)
invalidateForTunnelError = updateLastTunnelError(blockStateReason)
} else {
invalidateForTunnelError = updateLastTunnelError(nil)
}
Expand All @@ -71,7 +72,7 @@ final class TunnelStatusNotificationProvider: NotificationProvider, InAppNotific
}
}

private func updateLastTunnelError(_ lastTunnelError: String?) -> Bool {
private func updateLastTunnelError(_ lastTunnelError: BlockedStateReason?) -> Bool {
if packetTunnelError != lastTunnelError {
packetTunnelError = lastTunnelError

Expand Down Expand Up @@ -120,22 +121,21 @@ final class TunnelStatusNotificationProvider: NotificationProvider, InAppNotific
return false
}

private func notificationDescription(for packetTunnelError: String) -> InAppNotificationDescriptor {
private func notificationDescription(for packetTunnelError: BlockedStateReason) -> InAppNotificationDescriptor {
InAppNotificationDescriptor(
identifier: identifier,
style: .error,
title: NSLocalizedString(
"TUNNEL_LEAKING_INAPP_NOTIFICATION_TITLE",
value: "NETWORK TRAFFIC MIGHT BE LEAKING",
"TUNNEL_BLOCKED_INAPP_NOTIFICATION_TITLE",
value: "BLOCKING INTERNET",
comment: ""
),
body: .init(string: String(
format: NSLocalizedString(
"PACKET_TUNNEL_ERROR_INAPP_NOTIFICATION_BODY",
value: "Could not configure VPN: %@",
"TUNNEL_BLOCKED_INAPP_NOTIFICATION_BODY",
value: localizedReasonForBlockedStateError(packetTunnelError),
comment: ""
),
packetTunnelError
)
))
)
}
Expand Down Expand Up @@ -220,4 +220,28 @@ final class TunnelStatusNotificationProvider: NotificationProvider, InAppNotific
)
)
}

private func localizedReasonForBlockedStateError(_ error: BlockedStateReason) -> String {
let errorString: String

switch error {
case .outdatedSchema:
errorString = "Unable to start tunnel connection after update. Please send a problem report."
case .noRelaysSatisfyingConstraints:
errorString = "No servers match your settings, try changing server or other settings."
case .invalidAccount:
errorString = "You are logged in with an invalid account number. Please log out and try another one."
case .deviceRevoked, .deviceLoggedOut:
errorString = "Unable to authenticate account. Please log out and log back in."
default:
errorString = "Unable to start tunnel connection. Please send a problem report."
}

return NSLocalizedString(
"BLOCKED_STATE_ERROR_TITLE",
tableName: "Main",
value: errorString,
comment: ""
)
}
}
35 changes: 30 additions & 5 deletions ios/MullvadVPN/TunnelManager/TunnelManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ final class TunnelManager: StorePaymentObserver {
finish(result.error)
}
} catch {
if let error = error as? NoRelaysSatisfyingConstraintsError {
_ = self.setTunnelStatus { tunnelStatus in
tunnelStatus.state = .error(.noRelaysSatisfyingConstraints)
}
}

finish(error)

return AnyCancellable()
Expand Down Expand Up @@ -703,22 +709,30 @@ final class TunnelManager: StorePaymentObserver {
lastPacketTunnelKeyRotation = newPacketTunnelKeyRotation
refreshDeviceState()
}

// TODO: handle blocked state (error state). See how handleRestError() manages invalid account or revoked device.

switch newTunnelStatus.state {
case .connecting, .reconnecting:
// Start polling tunnel status to keep the relay information up to date
// while the tunnel process is trying to connect.
startPollingTunnelStatus(interval: establishingTunnelStatusPollInterval)

case .connected, .waitingForConnectivity(.noConnection), .error:
case .connected, .waitingForConnectivity(.noConnection):
// Start polling tunnel status to keep connectivity status up to date.
startPollingTunnelStatus(interval: establishedTunnelStatusPollInterval)

case .pendingReconnect, .disconnecting, .disconnected, .waitingForConnectivity(.noNetwork):
// Stop polling tunnel status once connection moved to final state.
cancelPollingTunnelStatus()

case let .error(blockedStateReason):
switch blockedStateReason {
case .deviceRevoked, .invalidAccount:
handleBlockedState(reason: blockedStateReason)
default:
break
}

// Stop polling tunnel status once blocked state has been determined.
cancelPollingTunnelStatus()
}

DispatchQueue.main.async {
Expand Down Expand Up @@ -1084,13 +1098,24 @@ final class TunnelManager: StorePaymentObserver {
guard let restError = error as? REST.Error else { return }

if restError.compareErrorCode(.deviceNotFound) {
setDeviceState(.revoked, persist: true)
handleBlockedState(reason: .deviceRevoked)
} else if restError.compareErrorCode(.invalidAccount) {
handleBlockedState(reason: .invalidAccount)
}
}

private func handleBlockedState(reason: BlockedStateReason) {
switch reason {
case .deviceRevoked:
setDeviceState(.revoked, persist: true)
case .invalidAccount:
unsetTunnelConfiguration {
self.setDeviceState(.revoked, persist: true)
self.operationQueue.cancelAllOperations()
self.wipeAllUserData()
}
default:
break
}
}

Expand Down
19 changes: 4 additions & 15 deletions ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ private extension TunnelState {
comment: ""
)

case .waitingForConnectivity(.noConnection):
case .waitingForConnectivity(.noConnection), .error:
return NSLocalizedString(
"TUNNEL_STATE_WAITING_FOR_CONNECTIVITY",
tableName: "Main",
Expand All @@ -511,10 +511,6 @@ private extension TunnelState {
value: "No network",
comment: ""
)

case let .error(blockedStateReason):
// TODO: Fix me
return ""
}
}

Expand All @@ -535,17 +531,14 @@ private extension TunnelState {
value: "Select location",
comment: ""
)
case .connecting, .connected, .reconnecting, .waitingForConnectivity:

case .connecting, .connected, .reconnecting, .waitingForConnectivity, .error:
return NSLocalizedString(
"SWITCH_LOCATION_BUTTON_TITLE",
tableName: "Main",
value: "Switch location",
comment: ""
)

case let .error(blockedStateReason):
// TODO: Fix me
return ""
}
}

Expand Down Expand Up @@ -591,7 +584,7 @@ private extension TunnelState {
tunnelInfo.location.country
)

case .waitingForConnectivity(.noConnection):
case .waitingForConnectivity(.noConnection), .error:
return NSLocalizedString(
"TUNNEL_STATE_WAITING_FOR_CONNECTIVITY_ACCESSIBILITY_LABEL",
tableName: "Main",
Expand Down Expand Up @@ -622,10 +615,6 @@ private extension TunnelState {
value: "Reconnecting",
comment: ""
)

case let .error(blockedStateReason):
// TODO: Fix me
return ""
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import WireGuardKit
/**
Struct responsible for mapping errors that may occur in the packet tunnel to the `BlockedStateReason`.
*/
struct BlockedStateErrorMapper: BlockedStateErrorMapperProtocol {
func mapError(_ error: Error) -> BlockedStateReason {
public struct BlockedStateErrorMapper: BlockedStateErrorMapperProtocol {
public func mapError(_ error: Error) -> BlockedStateReason {
switch error {
case let error as ReadDeviceDataError:
// Such error is thrown by implementations of `SettingsReaderProtocol`.
Expand Down

0 comments on commit 2031cb2

Please sign in to comment.