Auto fix config ports.
This commit is contained in:
parent
6ef8415c94
commit
9e5fb51ec4
|
@ -539,10 +539,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
let log: String?
|
||||
}
|
||||
|
||||
let config = ClashMetaConfig.generateInitConfig()
|
||||
|
||||
Logger.log("Trying start meta core")
|
||||
startMeta(config).map { string -> String in
|
||||
|
||||
generateInitConfig().then {
|
||||
self.startMeta($0)
|
||||
}.map { string -> String in
|
||||
guard let jsonData = string.data(using: .utf8),
|
||||
let res = try? JSONDecoder().decode(StartProxyResp.self, from: jsonData) else {
|
||||
return string == "" ? "unknown error" : string
|
||||
|
@ -577,6 +578,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
}.catch { _ in }
|
||||
}
|
||||
|
||||
func generateInitConfig() -> Promise<ClashMetaConfig.Config> {
|
||||
var config = ClashMetaConfig.generateInitConfig()
|
||||
return Promise { resolver in
|
||||
PrivilegedHelperManager.shared.helper {
|
||||
resolver.fulfill(config)
|
||||
}?.getUsedPorts {
|
||||
config.updatePorts($0 ?? "")
|
||||
resolver.fulfill(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startMeta(_ config: ClashMetaConfig.Config) -> Promise<String> {
|
||||
.init { resolver in
|
||||
PrivilegedHelperManager.shared.helper {
|
||||
|
|
|
@ -78,6 +78,35 @@ class ClashMetaConfig: NSObject {
|
|||
mixedPort = 7890
|
||||
}
|
||||
}
|
||||
|
||||
mutating func updatePorts(_ usedPorts: String) {
|
||||
let usedPorts = usedPorts.split(separator: ",").compactMap {
|
||||
Int($0)
|
||||
}
|
||||
|
||||
var availablePorts = Set(1..<65534)
|
||||
availablePorts.subtract(usedPorts)
|
||||
|
||||
func update(_ port: Int?) -> Int? {
|
||||
guard let p = port, p != 0 else {
|
||||
return port
|
||||
}
|
||||
|
||||
if availablePorts.contains(p) {
|
||||
availablePorts.remove(p)
|
||||
return p
|
||||
} else if let p = Set(p..<65534).intersection(availablePorts).min() {
|
||||
availablePorts.remove(p)
|
||||
return p
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
port = update(port)
|
||||
socksPort = update(socksPort)
|
||||
mixedPort = update(mixedPort)
|
||||
}
|
||||
}
|
||||
|
||||
static func generateInitConfig() -> Config {
|
||||
|
|
|
@ -82,17 +82,6 @@ class MetaTask: NSObject {
|
|||
return
|
||||
}
|
||||
|
||||
let port = serverResult.externalController.components(separatedBy: ":").last ?? "9090"
|
||||
if let p = Int(port) {
|
||||
let newPort = self.updateExternalControllerPort(p)
|
||||
let ec = "127.0.0.1:\(newPort)"
|
||||
args.append(contentsOf: [
|
||||
"-ext-ctl",
|
||||
ec
|
||||
])
|
||||
serverResult.externalController = ec
|
||||
}
|
||||
|
||||
self.proc.arguments = args
|
||||
let pipe = Pipe()
|
||||
var logs = [String]()
|
||||
|
@ -253,6 +242,31 @@ class MetaTask: NSObject {
|
|||
proc.waitUntilExit()
|
||||
}
|
||||
|
||||
@objc func getUsedPorts(_ result: @escaping stringReplyBlock) {
|
||||
let proc = Process()
|
||||
let pipe = Pipe()
|
||||
proc.standardOutput = pipe
|
||||
proc.executableURL = .init(fileURLWithPath: "/bin/bash")
|
||||
proc.arguments = ["-c", "lsof -nP -iTCP -sTCP:LISTEN | grep LISTEN"]
|
||||
try? proc.run()
|
||||
proc.waitUntilExit()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
guard let str = String(data: data, encoding: .utf8) else {
|
||||
result("")
|
||||
return
|
||||
}
|
||||
|
||||
let usedPorts = str.split(separator: "\n").compactMap { str -> Int? in
|
||||
let line = str.split(separator: " ").map(String.init)
|
||||
guard line.count == 10,
|
||||
let port = line[8].components(separatedBy: ":").last else { return nil }
|
||||
return Int(port)
|
||||
}.map(String.init).joined(separator: ",")
|
||||
|
||||
result(usedPorts)
|
||||
}
|
||||
|
||||
func testListenPort(_ port: Int) -> (pid: Int32, addr: String) {
|
||||
let proc = Process()
|
||||
let pipe = Pipe()
|
||||
|
@ -275,38 +289,6 @@ class MetaTask: NSObject {
|
|||
return (Int32(pid) ?? 0, addr)
|
||||
}
|
||||
|
||||
func updateExternalControllerPort(_ port: Int) -> Int {
|
||||
let proc = Process()
|
||||
let pipe = Pipe()
|
||||
proc.standardOutput = pipe
|
||||
proc.executableURL = .init(fileURLWithPath: "/bin/bash")
|
||||
proc.arguments = ["-c", "lsof -nP -iTCP -sTCP:LISTEN | grep LISTEN"]
|
||||
try? proc.run()
|
||||
proc.waitUntilExit()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
guard let str = String(data: data, encoding: .utf8) else {
|
||||
return port
|
||||
}
|
||||
|
||||
let ports = str.split(separator: "\n").map {
|
||||
String($0).split(separator: " ")
|
||||
}.compactMap { re -> Int? in
|
||||
guard re.count == 10,
|
||||
let range = re[8].range(of: ":", options: .backwards) else { return nil }
|
||||
let s = re[8]
|
||||
let p = s[range.upperBound..<s.endIndex]
|
||||
return Int(p)
|
||||
}
|
||||
guard ports.contains(port) else {
|
||||
return port
|
||||
}
|
||||
|
||||
var aPorts = Set(port..<65534)
|
||||
aPorts.subtract(ports)
|
||||
return aPorts.min() ?? port
|
||||
}
|
||||
|
||||
func testExternalController(_ server: MetaServer) -> Bool {
|
||||
let proc = Process()
|
||||
let pipe = Pipe()
|
||||
|
|
|
@ -154,4 +154,8 @@ ProxyConfigRemoteProcessProtocol
|
|||
[self.metaTask stop];
|
||||
}
|
||||
|
||||
- (void)getUsedPorts:(stringReplyBlock)reply {
|
||||
[self.metaTask getUsedPorts:reply];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -25,6 +25,8 @@ typedef void(^dictReplyBlock)(NSDictionary *);
|
|||
ConfFilePath:(NSString *)confFilePath
|
||||
result:(stringReplyBlock)reply;
|
||||
|
||||
- (void)getUsedPorts:(stringReplyBlock)reply;
|
||||
|
||||
- (void)stopMeta;
|
||||
|
||||
- (void)getVersion:(stringReplyBlock)reply;
|
||||
|
|
Loading…
Reference in New Issue