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 log: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = ClashMetaConfig.generateInitConfig()
|
|
||||||
|
|
||||||
Logger.log("Trying start meta core")
|
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),
|
guard let jsonData = string.data(using: .utf8),
|
||||||
let res = try? JSONDecoder().decode(StartProxyResp.self, from: jsonData) else {
|
let res = try? JSONDecoder().decode(StartProxyResp.self, from: jsonData) else {
|
||||||
return string == "" ? "unknown error" : string
|
return string == "" ? "unknown error" : string
|
||||||
|
@ -577,6 +578,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
}.catch { _ in }
|
}.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> {
|
func startMeta(_ config: ClashMetaConfig.Config) -> Promise<String> {
|
||||||
.init { resolver in
|
.init { resolver in
|
||||||
PrivilegedHelperManager.shared.helper {
|
PrivilegedHelperManager.shared.helper {
|
||||||
|
|
|
@ -78,6 +78,35 @@ class ClashMetaConfig: NSObject {
|
||||||
mixedPort = 7890
|
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 {
|
static func generateInitConfig() -> Config {
|
||||||
|
|
|
@ -82,17 +82,6 @@ class MetaTask: NSObject {
|
||||||
return
|
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
|
self.proc.arguments = args
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
var logs = [String]()
|
var logs = [String]()
|
||||||
|
@ -253,6 +242,31 @@ class MetaTask: NSObject {
|
||||||
proc.waitUntilExit()
|
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) {
|
func testListenPort(_ port: Int) -> (pid: Int32, addr: String) {
|
||||||
let proc = Process()
|
let proc = Process()
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
|
@ -275,38 +289,6 @@ class MetaTask: NSObject {
|
||||||
return (Int32(pid) ?? 0, addr)
|
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 {
|
func testExternalController(_ server: MetaServer) -> Bool {
|
||||||
let proc = Process()
|
let proc = Process()
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
|
|
|
@ -154,4 +154,8 @@ ProxyConfigRemoteProcessProtocol
|
||||||
[self.metaTask stop];
|
[self.metaTask stop];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)getUsedPorts:(stringReplyBlock)reply {
|
||||||
|
[self.metaTask getUsedPorts:reply];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -25,6 +25,8 @@ typedef void(^dictReplyBlock)(NSDictionary *);
|
||||||
ConfFilePath:(NSString *)confFilePath
|
ConfFilePath:(NSString *)confFilePath
|
||||||
result:(stringReplyBlock)reply;
|
result:(stringReplyBlock)reply;
|
||||||
|
|
||||||
|
- (void)getUsedPorts:(stringReplyBlock)reply;
|
||||||
|
|
||||||
- (void)stopMeta;
|
- (void)stopMeta;
|
||||||
|
|
||||||
- (void)getVersion:(stringReplyBlock)reply;
|
- (void)getVersion:(stringReplyBlock)reply;
|
||||||
|
|
Loading…
Reference in New Issue