passepartout-apple/Passepartout/Sources/Model/Profiles/ProviderConnectionProfile.swift
Davide De Rosa 12597d34b3 Override hostname with profile value
Now that TunnelKit uses sessionConfiguration.hostname to set
.serverAddress, it must be set no matter what.

If hostname is nil, serverAddress is set to
resolvedAddresses.first, which for host profiles is always nil.

Also reorder provider code.
2019-04-10 15:13:31 +02:00

192 lines
5.6 KiB
Swift

//
// ProviderConnectionProfile.swift
// Passepartout
//
// Created by Davide De Rosa on 9/2/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
import TunnelKit
public class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable {
public let name: Infrastructure.Name
public var infrastructure: Infrastructure {
return InfrastructureFactory.shared.get(name)
}
public var poolId: String {
didSet {
validateEndpoint()
}
}
public var pool: Pool? {
return infrastructure.pool(for: poolId) ?? infrastructure.pool(for: infrastructure.defaults.pool)
}
public var presetId: String {
didSet {
validateEndpoint()
}
}
public var preset: InfrastructurePreset? {
return infrastructure.preset(for: presetId)
}
public var manualAddress: String?
public var manualProtocol: EndpointProtocol?
public var usesProviderEndpoint: Bool {
return (manualAddress != nil) || (manualProtocol != nil)
}
public init(name: Infrastructure.Name) {
self.name = name
poolId = ""
presetId = ""
username = nil
poolId = infrastructure.defaults.pool
presetId = infrastructure.defaults.preset
}
public func pools() -> [Pool] {
return infrastructure.pools
}
private func validateEndpoint() {
guard let pool = pool, let preset = preset else {
manualAddress = nil
manualProtocol = nil
return
}
if let address = manualAddress, !pool.hasAddress(address) {
manualAddress = nil
}
if let proto = manualProtocol, !preset.hasProtocol(proto) {
manualProtocol = nil
}
}
// MARK: ConnectionProfile
public let context: Context = .provider
public var id: String {
return name.rawValue
}
public var username: String?
public var requiresCredentials: Bool {
return true
}
public func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration {
guard let pool = pool else {
preconditionFailure("Nil pool?")
}
guard let preset = preset else {
preconditionFailure("Nil preset?")
}
// assert(!pool.numericAddresses.isEmpty)
// XXX: copy paste, error prone
var builder = preset.configuration.builder()
builder.mtu = configuration.mtu
builder.shouldDebug = configuration.shouldDebug
builder.debugLogFormat = configuration.debugLogFormat
builder.masksPrivateData = configuration.masksPrivateData
if let address = manualAddress {
builder.prefersResolvedAddresses = true
builder.resolvedAddresses = [address]
} else if builder.sessionConfiguration.hostname == nil {
builder.prefersResolvedAddresses = true
builder.resolvedAddresses = pool.addresses()
} else {
builder.prefersResolvedAddresses = !preferences.resolvesHostname
builder.resolvedAddresses = pool.addresses()
}
if let proto = manualProtocol {
builder.sessionConfiguration.endpointProtocols = [proto]
} else {
// restrict "Any" protocol to UDP, unless there are no UDP endpoints
let allEndpoints = preset.configuration.sessionConfiguration.endpointProtocols
var endpoints = allEndpoints?.filter { $0.socketType == .udp }
if endpoints?.isEmpty ?? true {
endpoints = allEndpoints
}
builder.sessionConfiguration.endpointProtocols = endpoints
// builder.sessionConfiguration.endpointProtocols = [
// EndpointProtocol(.udp, 8080),
// EndpointProtocol(.tcp, 443)
// ]
}
return builder.build()
}
public func with(newId: String) -> ConnectionProfile {
fatalError("Cannot rename a ProviderConnectionProfile")
}
}
public extension ProviderConnectionProfile {
static func ==(lhs: ProviderConnectionProfile, rhs: ProviderConnectionProfile) -> Bool {
return lhs.id == rhs.id
}
}
public extension ProviderConnectionProfile {
var mainAddress: String? {
assert(pool != nil, "Getting provider main address but no pool set")
return pool?.hostname
}
var addresses: [String] {
return pool?.addresses() ?? []
}
var protocols: [EndpointProtocol] {
return preset?.configuration.sessionConfiguration.endpointProtocols ?? []
}
var canCustomizeEndpoint: Bool {
return true
}
var customAddress: String? {
return manualAddress
}
var customProtocol: EndpointProtocol? {
return manualProtocol
}
}