Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson authored and buggmagnet committed Oct 6, 2023
1 parent 9be4c65 commit bbba866
Show file tree
Hide file tree
Showing 17 changed files with 826 additions and 91 deletions.
169 changes: 154 additions & 15 deletions ios/MullvadVPN.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@
ReferencedContainer = "container:MullvadVPN.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7A6F1A232AC57071008ACF78"
BuildableName = "PacketTunnelTests.xctest"
BlueprintName = "PacketTunnelTests"
ReferencedContainer = "container:MullvadVPN.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@
reference = "container:TestPlans/MullvadVPNCI.xctestplan">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7A6F1A232AC57071008ACF78"
BuildableName = "PacketTunnelTests.xctest"
BlueprintName = "PacketTunnelTests"
ReferencedContainer = "container:MullvadVPN.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down Expand Up @@ -80,6 +93,7 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ struct BlockedStateErrorMapper: BlockedStateErrorMapperProtocol {
// packet tunnel provider.
return .tunnelAdapter

case is PublicKeyError:
// Returned when there is an endpoint but its public key is invalid.
return .invalidPublicKey

default:
// Everything else in case we introduce new errors and forget to handle them.
return .unknown
Expand Down
57 changes: 0 additions & 57 deletions ios/PacketTunnel/PacketTunnelProvider/State+Extensions.swift

This file was deleted.

29 changes: 22 additions & 7 deletions ios/PacketTunnelCore/Actor/ConfigurationBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,44 @@ import struct WireGuardKitTypes.IPAddressRange
import class WireGuardKitTypes.PrivateKey
import class WireGuardKitTypes.PublicKey

/// Error returned when there is an endpoint but its public key is invalid.
public struct PublicKeyError: LocalizedError {
let endpoint: MullvadEndpoint

public var errorDescription: String? {
"Public key is invalid, endpoint: \(endpoint)"
}
}

/// Struct building tunnel adapter configuration.
struct ConfigurationBuilder {
var privateKey: PrivateKey
var interfaceAddresses: [IPAddressRange]
var dns: SelectedDNSServers?
var endpoint: MullvadEndpoint?

func makeConfiguration() -> TunnelAdapterConfiguration {
func makeConfiguration() throws -> TunnelAdapterConfiguration {
return TunnelAdapterConfiguration(
privateKey: privateKey,
interfaceAddresses: interfaceAddresses,
dns: dnsServers,
peer: peer
peer: try peer
)
}

private var peer: TunnelPeer? {
guard let endpoint else { return nil }
get throws {
guard let endpoint else { return nil }

return TunnelPeer(
endpoint: .ipv4(endpoint.ipv4Relay),
publicKey: PublicKey(rawValue: endpoint.publicKey)!
)
guard let publicKey = PublicKey(rawValue: endpoint.publicKey) else {
throw PublicKeyError(endpoint: endpoint)
}

return TunnelPeer(
endpoint: .ipv4(endpoint.ipv4Relay),
publicKey: publicKey
)
}
}

private var dnsServers: [IPAddress] {
Expand Down
4 changes: 2 additions & 2 deletions ios/PacketTunnelCore/Actor/PacketTunnelActor+KeyPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ extension PacketTunnelActor {
guard let self else { return }

// Wait for key to propagate across relays.
try await Task.sleepUsingContinuousClock(for: timings.wgKeyPropagationDelay)
// try await Task.sleepUsingContinuousClock(for: timings.wgKeyPropagationDelay)

// Enqueue task to change key policy.
commandChannel.send(.switchKey)
Expand Down Expand Up @@ -159,7 +159,7 @@ extension PacketTunnelActor {
/**
Internal helper that transitions key policy from `.usePrior` to `.useCurrent`.

- Parameter keyPolicy: a reference to key policy hend either in connection state or blocked state struct.
- Parameter keyPolicy: a reference to key policy held either in connection state or blocked state struct.
- Returns: `true` when the policy was modified, otherwise `false`.
*/
private func setCurrentKeyPolicy(_ keyPolicy: inout KeyPolicy) -> Bool {
Expand Down
57 changes: 57 additions & 0 deletions ios/PacketTunnelCore/Actor/State+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,60 @@ extension BlockedStateReason {
}
}
}

//
// State+Extensions.swift
// PacketTunnel
//
// Created by pronebird on 12/09/2023.
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//

import Foundation
import MullvadTypes

public extension State {
var packetTunnelStatus: PacketTunnelStatus {
var status = PacketTunnelStatus()

switch self {
case let .connecting(connState),
let .connected(connState),
let .reconnecting(connState),
let .disconnecting(connState):
switch connState.networkReachability {
case .reachable:
status.isNetworkReachable = true
case .unreachable:
status.isNetworkReachable = false
case .undetermined:
// TODO: fix me
status.isNetworkReachable = true
}

status.numberOfFailedAttempts = connState.connectionAttemptCount
status.tunnelRelay = connState.selectedRelay.packetTunnelRelay

case .disconnected, .initial:
break

case let .error(blockedState):
status.blockedStateReason = blockedState.reason
}

return status
}

var relayConstraints: RelayConstraints? {
switch self {
case let .connecting(connState), let .connected(connState), let .reconnecting(connState):
return connState.relayConstraints

case let .error(blockedState):
return blockedState.relayConstraints

case .initial, .disconnecting, .disconnected:
return nil
}
}
}
5 changes: 4 additions & 1 deletion ios/PacketTunnelCore/Actor/State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public struct ConnectionState {
/// This is primarily used by packet tunnel for updating constraints in tunnel provider.
public var relayConstraints: RelayConstraints

/// Last WG key read from setings.
/// Last WG key read from settings.
/// Can be `nil` if moved to `keyPolicy`.
public var currentKey: PrivateKey?

Expand Down Expand Up @@ -192,6 +192,9 @@ public enum BlockedStateReason: String, Codable, Equatable {
/// Tunnel adapter error.
case tunnelAdapter

/// Invalid public key.
case invalidPublicKey

/// Unidentified reason.
case unknown
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@

import Foundation
import MullvadLogging
import PacketTunnelCore

/**
Actor handling packet tunnel IPC (app) messages and patching them through to the right facility.
*/
struct AppMessageHandler {
public struct AppMessageHandler {
private let logger = Logger(label: "AppMessageHandler")
private let packetTunnelActor: PacketTunnelActor
private let urlRequestProxy: URLRequestProxy

init(packetTunnelActor: PacketTunnelActor, urlRequestProxy: URLRequestProxy) {
public init(packetTunnelActor: PacketTunnelActor, urlRequestProxy: URLRequestProxy) {
self.packetTunnelActor = packetTunnelActor
self.urlRequestProxy = urlRequestProxy
}
Expand All @@ -34,7 +33,7 @@ struct AppMessageHandler {
the acknowledgment from IPC before starting next operation, hence it's critical to return as soon as possible.
(See `TunnelManager.reconnectTunnel()`, `SendTunnelProviderMessageOperation`)
*/
func handleAppMessage(_ messageData: Data) async -> Data? {
public func handleAppMessage(_ messageData: Data) async -> Data? {
guard let message = decodeMessage(messageData) else { return nil }

logger.debug("Received app message: \(message)")
Expand All @@ -51,7 +50,7 @@ struct AppMessageHandler {
return await encodeReply(packetTunnelActor.state.packetTunnelStatus)

case .privateKeyRotation:
packetTunnelActor.notifyKeyRotation(date: nil)
packetTunnelActor.notifyKeyRotation(date: Date())
return nil

case let .reconnectTunnel(selectorResult):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation
import MullvadTypes
import PacketTunnelCore
@testable import PacketTunnelCore

/// Blocked state error mapper stub that can be configured with a block to simulate a desired behavior.
class BlockedStateErrorMapperStub: BlockedStateErrorMapperProtocol {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation
import NetworkExtension
import PacketTunnelCore
@testable import PacketTunnelCore

struct NetworkPathStub: NetworkPath {
var status: NetworkExtension.NWPathStatus = .satisfied
Expand Down
2 changes: 1 addition & 1 deletion ios/PacketTunnelCoreTests/Mocks/TunnelAdapterDummy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

import Foundation
import PacketTunnelCore
@testable import PacketTunnelCore

/// Dummy tunnel adapter that does nothing and reports no errors.
class TunnelAdapterDummy: TunnelAdapterProtocol {
Expand Down
3 changes: 2 additions & 1 deletion ios/PacketTunnelCoreTests/PingerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
//

import Network
import PacketTunnelCore
@testable import PacketTunnelCore
import WireGuardKitTypes
import XCTest

final class PingerTests: XCTestCase {
Expand Down
Loading

0 comments on commit bbba866

Please sign in to comment.