diff --git a/Tun/NetworkInterface.swift b/Tun/NetworkInterface.swift new file mode 100644 index 0000000..8455287 --- /dev/null +++ b/Tun/NetworkInterface.swift @@ -0,0 +1,75 @@ +// +// NetworkInterface.swift +// punchnet +// +// Created by 安礼成 on 2025/8/3. +// + + +// +// NetworkInterface.swift +// Tun +// +// Created by 安礼成 on 2024/1/19. +// + +import Foundation + +public struct NetworkInterface { + public let name: String + public let ip: String + public let netmask: String +} + +public struct NetworkInterfaceManager { + /** + 获取网卡信息, (let name: String let ip: String let netmask: String) + */ + public static func getInterfaces() -> [NetworkInterface] { + var interfaces: [NetworkInterface] = [] + + // Get list of all interfaces on the local machine: + var ifaddr : UnsafeMutablePointer? = nil + if getifaddrs(&ifaddr) == 0 { + + // For each interface ... + var ptr = ifaddr + while( ptr != nil) { + + let flags = Int32(ptr!.pointee.ifa_flags) + var addr = ptr!.pointee.ifa_addr.pointee + + // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. + if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { + if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) { + + var mask = ptr!.pointee.ifa_netmask.pointee + + // Convert interface address to a human readable string: + let zero = CChar(0) + var hostname = [CChar](repeating: zero, count: Int(NI_MAXHOST)) + var netmask = [CChar](repeating: zero, count: Int(NI_MAXHOST)) + if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count), + nil, socklen_t(0), NI_NUMERICHOST) == 0) { + let address = String(cString: hostname) + + let name = ptr!.pointee.ifa_name! + let ifname = String(cString: name) + + if (getnameinfo(&mask, socklen_t(mask.sa_len), &netmask, socklen_t(netmask.count), nil, socklen_t(0), NI_NUMERICHOST) == 0) { + let netmaskIP = String(cString: netmask) + + interfaces.append(NetworkInterface(name: ifname, ip: address, netmask: netmaskIP)) + } + } + } + } + ptr = ptr!.pointee.ifa_next + } + freeifaddrs(ifaddr) + } + + return interfaces + } + +} diff --git a/Tun/PacketTunnelProvider.swift b/Tun/PacketTunnelProvider.swift new file mode 100644 index 0000000..77d1ee6 --- /dev/null +++ b/Tun/PacketTunnelProvider.swift @@ -0,0 +1,164 @@ +// +// PacketTunnelProvider.swift +// punchnet +// +// Created by 安礼成 on 2025/8/3. +// + + +// +// PacketTunnelProvider.swift +// Tun +// +// Created by 安礼成 on 2024/1/17. +// + +import NetworkExtension +import Punchnet + +class PacketTunnelProvider: NEPacketTunnelProvider { + var context: SDLContext? + + override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) { + // host: "192.168.0.101", port: 1265 + guard let options else { + return + } + + // 如果当前在运行状态,不允许重复请求 + guard self.context == nil else { + return + } + + // let token = options["token"] as! String + let installed_channel = options["installed_channel"] as! String + let superIp = options["super_ip"] as! String + let superPort = options["super_port"] as! Int + let stunServersStr = options["stun_servers"] as! String + + let stunServers = stunServersStr.split(separator: ";").compactMap { server -> SDLConfiguration.StunServer? in + let parts = server.split(separator: ":", maxSplits: 2) + guard parts.count == 2 else { + return nil + } + + let ports = parts[1].split(separator: ",", maxSplits: 2) + guard ports.count == 2, let port1 = Int(String(ports[0])), let port2 = Int(String(ports[1])) else { + return nil + } + + return .init(host: String(parts[0]), ports: [port1, port2]) + } + + guard stunServers.count >= 2 else { + NSLog("stunServers配置错误") + return + } + + let config = SDLConfiguration(version: 1, + installedChannel: installed_channel, + superHost: superIp, + superPort: superPort, + stunServers: stunServers, + clientId: SDLContext.getUUID(), + token: "") + // 加密算法 + let rsaCipher = try! CCRSACipher(keySize: 1024) + let aesChiper = CCAESChiper() + + Task { + do { + self.context = SDLContext(provider: self, config: config, rsaCipher: rsaCipher, aesCipher: aesChiper, logger: SDLLogger(level: .warning)) + try await self.context?.start() + completionHandler(nil) + } catch let err { + completionHandler(err) + } + } + + } + + override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + // Add code here to start the process of stopping the tunnel. + Task { + await self.context?.stop() + self.context = nil + } + completionHandler() + } + + override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { + // Add code here to handle the message. + if let handler = completionHandler { + handler(messageData) + } + } + + override func sleep(completionHandler: @escaping () -> Void) { + // Add code here to get ready to sleep. + completionHandler() + } + + override func wake() { + // Add code here to wake up. + } + +} + +// 获取物理网卡ip地址 +extension PacketTunnelProvider { + + public static var viaInterface: NetworkInterface? = { + let interfaces = NetworkInterfaceManager.getInterfaces() + + return interfaces.first {$0.name == "en0"} + }() + + struct CCRSACipher: RSACipher { + var pubKey: String + let privateKeyDER: Data + + init(keySize: Int) throws { + let (privateKey, publicKey) = try Self.loadKeys(keySize: keySize) + let privKeyStr = SwKeyConvert.PrivateKey.derToPKCS1PEM(privateKey) + + self.pubKey = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey) + self.privateKeyDER = try SwKeyConvert.PrivateKey.pemToPKCS1DER(privKeyStr) + } + + public func decode(data: Data) throws -> Data { + let tag = Data() + let (decryptedData, _) = try CC.RSA.decrypt(data, derKey: self.privateKeyDER, tag: tag, padding: .pkcs1, digest: .none) + + return decryptedData + } + + private static func loadKeys(keySize: Int) throws -> (Data, Data) { + if let privateKey = UserDefaults.standard.data(forKey: "privateKey"), + let publicKey = UserDefaults.standard.data(forKey: "publicKey") { + + return (privateKey, publicKey) + } else { + let (privateKey, publicKey) = try CC.RSA.generateKeyPair(keySize) + UserDefaults.standard.setValue(privateKey, forKey: "privateKey") + UserDefaults.standard.setValue(publicKey, forKey: "publicKey") + + return (privateKey, publicKey) + } + } + } + + struct CCAESChiper: AESCipher { + func decypt(aesKey: Data, data: Data) throws -> Data { + let ivData = Data(aesKey.prefix(16)) + return try CC.crypt(.decrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: ivData) + } + + func encrypt(aesKey: Data, data: Data) throws -> Data { + let ivData = Data(aesKey.prefix(16)) + + return try CC.crypt(.encrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: ivData) + } + } + +} diff --git a/punchnet.xcodeproj/project.pbxproj b/punchnet.xcodeproj/project.pbxproj index 1cf9f0a..da85d57 100644 --- a/punchnet.xcodeproj/project.pbxproj +++ b/punchnet.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + C82EA7472E3FAA5A00DA5B3C /* Punchnet in Frameworks */ = {isa = PBXBuildFile; productRef = C82EA7462E3FAA5A00DA5B3C /* Punchnet */; }; C8A77F2A2DD1E77B00195617 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8A77F292DD1E77B00195617 /* NetworkExtension.framework */; }; C8A77F322DD1E77B00195617 /* Tun.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C8A77F272DD1E77B00195617 /* Tun.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; C8A77F792DD1E93900195617 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F782DD1E93900195617 /* NIO */; }; @@ -14,8 +15,6 @@ C8A77F7D2DD1E93900195617 /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F7C2DD1E93900195617 /* NIOCore */; }; C8A77F7F2DD1E93900195617 /* NIOEmbedded in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F7E2DD1E93900195617 /* NIOEmbedded */; }; C8A77F812DD1E93900195617 /* NIOFoundationCompat in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F802DD1E93900195617 /* NIOFoundationCompat */; }; - C8A77F832DD1E98B00195617 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F822DD1E98B00195617 /* NIO */; }; - C8A77F852DD1E99300195617 /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F842DD1E99300195617 /* NIOCore */; }; C8A77F882DD1EA0200195617 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F872DD1EA0200195617 /* SwiftProtobuf */; }; C8A77F8A2DD1EA0200195617 /* SwiftProtobufPluginLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = C8A77F892DD1EA0200195617 /* SwiftProtobufPluginLibrary */; }; /* End PBXBuildFile section */ @@ -143,10 +142,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C8A77F852DD1E99300195617 /* NIOCore in Frameworks */, C8A77F2A2DD1E77B00195617 /* NetworkExtension.framework in Frameworks */, C8A77F8A2DD1EA0200195617 /* SwiftProtobufPluginLibrary in Frameworks */, - C8A77F832DD1E98B00195617 /* NIO in Frameworks */, + C82EA7472E3FAA5A00DA5B3C /* Punchnet in Frameworks */, C8A77F882DD1EA0200195617 /* SwiftProtobuf in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -280,10 +278,9 @@ ); name = Tun; packageProductDependencies = ( - C8A77F822DD1E98B00195617 /* NIO */, - C8A77F842DD1E99300195617 /* NIOCore */, C8A77F872DD1EA0200195617 /* SwiftProtobuf */, C8A77F892DD1EA0200195617 /* SwiftProtobufPluginLibrary */, + C82EA7462E3FAA5A00DA5B3C /* Punchnet */, ); productName = Tun; productReference = C8A77F272DD1E77B00195617 /* Tun.appex */; @@ -325,8 +322,7 @@ mainGroup = C8A77EEA2DD1E6D000195617; minimizedProjectReferenceProxies = 1; packageReferences = ( - C8A77F772DD1E93900195617 /* XCLocalSwiftPackageReference "../../packages/swift-nio" */, - C8A77F862DD1EA0200195617 /* XCLocalSwiftPackageReference "../../packages/swift-protobuf" */, + C82EA7452E3FAA5A00DA5B3C /* XCRemoteSwiftPackageReference "swiftlib_sdlan" */, ); preferredProjectObjectVersion = 77; productRefGroup = C8A77EF42DD1E6D000195617 /* Products */; @@ -475,7 +471,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 15.2; + MACOSX_DEPLOYMENT_TARGET = 14.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -532,7 +528,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 15.2; + MACOSX_DEPLOYMENT_TARGET = 14.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -561,7 +557,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnet; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -593,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnet; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -612,7 +608,7 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = PF3QG837XS; GENERATE_INFOPLIST_FILE = YES; - MACOSX_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnetTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -630,7 +626,7 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = PF3QG837XS; GENERATE_INFOPLIST_FILE = YES; - MACOSX_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnetTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -647,6 +643,7 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = PF3QG837XS; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnetUITests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -663,6 +660,7 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = PF3QG837XS; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnetUITests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -691,6 +689,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnet.tun; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -721,6 +720,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 14.6; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.jihe.punchnet.tun; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -782,18 +782,23 @@ }; /* End XCConfigurationList section */ -/* Begin XCLocalSwiftPackageReference section */ - C8A77F772DD1E93900195617 /* XCLocalSwiftPackageReference "../../packages/swift-nio" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = "../../packages/swift-nio"; +/* Begin XCRemoteSwiftPackageReference section */ + C82EA7452E3FAA5A00DA5B3C /* XCRemoteSwiftPackageReference "swiftlib_sdlan" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://gitea.s5s8.com/anlicheng/swiftlib_sdlan.git"; + requirement = { + kind = exactVersion; + version = 2.2.0; + }; }; - C8A77F862DD1EA0200195617 /* XCLocalSwiftPackageReference "../../packages/swift-protobuf" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = "../../packages/swift-protobuf"; - }; -/* End XCLocalSwiftPackageReference section */ +/* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + C82EA7462E3FAA5A00DA5B3C /* Punchnet */ = { + isa = XCSwiftPackageProductDependency; + package = C82EA7452E3FAA5A00DA5B3C /* XCRemoteSwiftPackageReference "swiftlib_sdlan" */; + productName = Punchnet; + }; C8A77F782DD1E93900195617 /* NIO */ = { isa = XCSwiftPackageProductDependency; productName = NIO; @@ -814,16 +819,6 @@ isa = XCSwiftPackageProductDependency; productName = NIOFoundationCompat; }; - C8A77F822DD1E98B00195617 /* NIO */ = { - isa = XCSwiftPackageProductDependency; - package = C8A77F772DD1E93900195617 /* XCLocalSwiftPackageReference "../../packages/swift-nio" */; - productName = NIO; - }; - C8A77F842DD1E99300195617 /* NIOCore */ = { - isa = XCSwiftPackageProductDependency; - package = C8A77F772DD1E93900195617 /* XCLocalSwiftPackageReference "../../packages/swift-nio" */; - productName = NIOCore; - }; C8A77F872DD1EA0200195617 /* SwiftProtobuf */ = { isa = XCSwiftPackageProductDependency; productName = SwiftProtobuf; diff --git a/punchnet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/punchnet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 297351e..dc15e82 100644 --- a/punchnet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/punchnet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "fc5ff56467a09054cad310ea04e2207caefea4e4c42012fbd995ed64d089417b", + "originHash" : "2c771b2bd4bccdc5777d69cc734485452a1e854c0123ba591d596b3f580f4cb8", "pins" : [ { "identity" : "swift-atomics", "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-atomics.git", "state" : { - "revision" : "cd142fd2f64be2100422d658e7411e39489da985", - "version" : "1.2.0" + "revision" : "b601256eab081c0f92f059e12818ac1d4f178ff7", + "version" : "1.3.0" } }, { @@ -15,8 +15,26 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections.git", "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" + "revision" : "8c0c0a8b49e080e54e5e328cc552821ff07cd341", + "version" : "1.2.1" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "a5fea865badcb1c993c85b0f0e8d05a4bd2270fb", + "version" : "2.85.0" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "102a647b573f60f73afdce5613a51d71349fe507", + "version" : "1.30.0" } }, { @@ -24,8 +42,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", - "version" : "1.4.2" + "revision" : "b63d24d465e237966c3f59f47dcac6c70fb0bca3", + "version" : "1.6.1" + } + }, + { + "identity" : "swiftlib_sdlan", + "kind" : "remoteSourceControl", + "location" : "https://gitea.s5s8.com/anlicheng/swiftlib_sdlan.git", + "state" : { + "revision" : "2c05d71dbe3684e51e9de55910619156ebe360c6", + "version" : "2.2.0" } } ], diff --git a/punchnet/Core/PunchnetConfig.swift b/punchnet/Core/PunchnetConfig.swift deleted file mode 100644 index 0fd065f..0000000 --- a/punchnet/Core/PunchnetConfig.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// Config.swift -// punchnet -// -// Created by 安礼成 on 2025/5/14. -// -import Foundation - -enum PunchnetError: Error { - case dnsUnreachable -} - -struct PunchnetConfig { - static let server = "punchnet.aioe.tech" - static let port = 18083 - - static func getOptions() throws -> [String:NSObject] { - var options: [String: NSObject] = [:] - - if let ip = DNSResolver.resolveAddrInfos(PunchnetConfig.server).first { - options["super_ip"] = ip as NSObject - } else { - throw PunchnetError.dnsUnreachable - } - - return options - } - -} - diff --git a/punchnet/Core/SystemConfig.swift b/punchnet/Core/SystemConfig.swift index 9f00db5..66e180b 100644 --- a/punchnet/Core/SystemConfig.swift +++ b/punchnet/Core/SystemConfig.swift @@ -15,4 +15,29 @@ struct SystemConfig { // 安装渠道 static let installedChannel = "MacAppStore" + + // super 节点 + //static let superHost = "118.178.229.213" + + static let superHost = "punchnet.aioe.tech" + static let superPort = 18083 + + // stun探测服务 + static let stunServers = "118.178.229.213:1265,1266;118.178.229.213:1265,1266" + + static func getOptions(token: String) -> [String:NSObject]? { + guard let superIp = DNSResolver.resolveAddrInfos(superHost).first else { + return nil + } + + return [ + "version:": version as NSObject, + "installed_channel": installedChannel as NSObject, + "token": token as NSObject, + "super_ip": superIp as NSObject, + "super_port": superPort as NSObject, + "stun_servers": stunServers as NSObject + ] + } + } diff --git a/punchnet/VPNManager.swift b/punchnet/Core/VPNManager.swift similarity index 93% rename from punchnet/VPNManager.swift rename to punchnet/Core/VPNManager.swift index d905fab..a06e6c8 100644 --- a/punchnet/VPNManager.swift +++ b/punchnet/Core/VPNManager.swift @@ -32,10 +32,7 @@ class VPNManager: ObservableObject { try await manager.loadFromPreferences() self.addVPNStatusObserver(manager) - var configOptions = try PunchnetConfig.getOptions() - configOptions.merge(options, uniquingKeysWith: {$1}) - - try manager.connection.startVPNTunnel(options: configOptions) + try manager.connection.startVPNTunnel(options: options) } // 关闭vpn diff --git a/punchnet/AbortView.swift b/punchnet/Views/AbortView.swift similarity index 99% rename from punchnet/AbortView.swift rename to punchnet/Views/AbortView.swift index 7c05c29..36ba170 100644 --- a/punchnet/AbortView.swift +++ b/punchnet/Views/AbortView.swift @@ -9,7 +9,6 @@ import Foundation import SwiftUI struct AbortView: View { - struct AlertShow: Identifiable { enum ShowContent { case error(String) diff --git a/punchnet/ContentView.swift b/punchnet/Views/IndexView.swift similarity index 93% rename from punchnet/ContentView.swift rename to punchnet/Views/IndexView.swift index 8256770..ba7dd03 100644 --- a/punchnet/ContentView.swift +++ b/punchnet/Views/IndexView.swift @@ -9,8 +9,7 @@ import SwiftUI import SwiftData import Combine -struct ContentView: View { - +struct IndexView: View { @AppStorage("token") private var token: String = "" @State private var showToken: Bool = false @@ -191,24 +190,13 @@ struct ContentView: View { case .connected: try await vpnManager.disableVpn() case .disconnected: - /* - if self.token.isEmpty { - self.showAlert = true - return - } - */ - //print("use port: \(vpnManager.noticePort as NSObject)") - try await vpnManager.enableVpn(options: [ - "version:": SystemConfig.version as NSObject, - "installed_channel": SystemConfig.installedChannel as NSObject, - "token": self.token as NSObject - ]) + try await vpnManager.enableVpn(options: SystemConfig.getOptions(token: self.token)!) } } } #Preview { - ContentView() + IndexView() //.modelContainer(for: Item.self, inMemory: true) } diff --git a/punchnet/punchnetApp.swift b/punchnet/punchnetApp.swift index 0eb8178..b1d5e30 100644 --- a/punchnet/punchnetApp.swift +++ b/punchnet/punchnetApp.swift @@ -35,7 +35,7 @@ struct punchnetApp: App { var body: some Scene { WindowGroup(id: "mainWindow") { - ContentView() + IndexView() .frame(minWidth: 300, maxWidth: 300, minHeight: 500, maxHeight: 500) .onAppear { // 获取主屏幕的尺寸 @@ -94,11 +94,7 @@ struct punchnetApp: App { switch self.vpnManager.vpnStatus { case .disconnected: Task { - try await vpnManager.enableVpn(options: [ - "version:": SystemConfig.version as NSObject, - "installed_channel": SystemConfig.installedChannel as NSObject, - "token": token as NSObject - ]) + try await vpnManager.enableVpn(options: SystemConfig.getOptions(token: self.token)!) } case .connected: Task {