147 lines
3.9 KiB
Swift
147 lines
3.9 KiB
Swift
//
|
|
// ProxyConfigHelper.swift
|
|
// com.metacubex.ClashX.ProxyConfigHelper
|
|
//
|
|
// Copyright © 2024 west2online. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
import os.log
|
|
|
|
class ProxyConfigHelper: NSObject, NSXPCListenerDelegate {
|
|
|
|
private var listener: NSXPCListener
|
|
private var connections = [NSXPCConnection]()
|
|
private var shouldQuitCheckInterval = 2.0
|
|
private var shouldQuit = false
|
|
|
|
private let metaTask = MetaTask()
|
|
private let metaDNS = MetaDNS()
|
|
|
|
override init() {
|
|
shouldQuit = false
|
|
listener = NSXPCListener(machServiceName: "com.metacubex.ClashX.ProxyConfigHelper")
|
|
super.init()
|
|
listener.delegate = self
|
|
}
|
|
|
|
func run() {
|
|
listener.resume()
|
|
os_log("ProxyConfigHelper running")
|
|
while !shouldQuit {
|
|
RunLoop.current.run(until: Date(timeIntervalSinceNow: shouldQuitCheckInterval))
|
|
}
|
|
}
|
|
|
|
|
|
// MARK: - NSXPCListenerDelegate
|
|
|
|
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
|
|
|
|
guard isValid(connection: newConnection) else {
|
|
return false
|
|
}
|
|
|
|
newConnection.exportedInterface = NSXPCInterface(with: ProxyConfigRemoteProcessProtocol.self)
|
|
newConnection.exportedObject = self
|
|
newConnection.invalidationHandler = {
|
|
guard let index = self.connections.firstIndex(of: newConnection) else { return }
|
|
self.connections.remove(at: index)
|
|
|
|
if self.connections.isEmpty {
|
|
self.shouldQuit = true
|
|
os_log("ProxyConfigHelper shouldQuit")
|
|
}
|
|
}
|
|
|
|
connections.append(newConnection)
|
|
newConnection.resume()
|
|
|
|
return true
|
|
}
|
|
|
|
private func isValid(connection: NSXPCConnection) -> Bool {
|
|
guard let app = NSRunningApplication(processIdentifier: connection.processIdentifier),
|
|
let bundleIdentifier = app.bundleIdentifier,
|
|
bundleIdentifier == "com.metacubex.ClashX.meta"
|
|
else {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
}
|
|
|
|
extension ProxyConfigHelper: ProxyConfigRemoteProcessProtocol {
|
|
func getVersion(reply: @escaping (String) -> Void) {
|
|
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "unknown"
|
|
reply(version)
|
|
}
|
|
|
|
|
|
func enableProxy(port: Int, socksPort: Int, pac: String?, filterInterface: Bool, ignoreList: [String], reply: @escaping (String?) -> Void) {
|
|
DispatchQueue.main.async {
|
|
let tool = ProxySettingTool()
|
|
tool.enableProxyWithport(Int32(port), socksPort: Int32(socksPort), pacUrl: pac ?? "", filterInterface: filterInterface, ignoreList: ignoreList)
|
|
reply(nil)
|
|
}
|
|
}
|
|
|
|
func disableProxy(filterInterface: Bool, reply: @escaping (String?) -> Void) {
|
|
DispatchQueue.main.async {
|
|
let tool = ProxySettingTool()
|
|
tool.disableProxyWithfilterInterface(filterInterface)
|
|
reply(nil)
|
|
}
|
|
}
|
|
|
|
func restoreProxy(currentPort: Int, socksPort: Int, info: [String : Any], filterInterface: Bool, reply: @escaping (String?) -> Void) {
|
|
DispatchQueue.main.async {
|
|
let tool = ProxySettingTool()
|
|
tool.restoreProxySetting(info, currentPort: Int32(currentPort), currentSocksPort: Int32(socksPort), filterInterface: filterInterface)
|
|
reply(nil)
|
|
}
|
|
}
|
|
|
|
func getCurrentProxySetting(reply: @escaping ([String : Any]) -> Void) {
|
|
DispatchQueue.main.async {
|
|
let info = ProxySettingTool.currentProxySettings()
|
|
reply(info as? [String: Any] ?? [:])
|
|
}
|
|
}
|
|
|
|
func startMeta(path: String,
|
|
confPath: String,
|
|
confFilePath: String,
|
|
confJSON: String,
|
|
reply: @escaping (String?) -> Void) {
|
|
DispatchQueue.main.async {
|
|
self.metaTask.start(path, confPath: confPath, confFilePath: confFilePath, confJSON: confJSON, result: reply)
|
|
}
|
|
}
|
|
|
|
func stopMeta() {
|
|
DispatchQueue.main.async {
|
|
self.metaTask.stop()
|
|
}
|
|
}
|
|
|
|
func getUsedPorts(reply: @escaping (String?) -> Void) {
|
|
DispatchQueue.main.async {
|
|
self.metaTask.getUsedPorts(reply)
|
|
}
|
|
}
|
|
|
|
func updateTun(state: Bool, dns: String) {
|
|
DispatchQueue.main.async {
|
|
self.metaDNS.setCustomDNS(dns)
|
|
if state {
|
|
self.metaDNS.hijackDNS()
|
|
} else {
|
|
self.metaDNS.revertDNS()
|
|
}
|
|
self.metaDNS.flushDnsCache()
|
|
}
|
|
}
|
|
}
|