|
@@ -99,63 +99,117 @@ class ClashService extends GetxController {
|
|
|
|
|
|
}
|
|
|
|
|
|
- Future<bool> startClashCore() async {
|
|
|
- final timeout = const Duration(seconds: 30);
|
|
|
- final checkInterval = const Duration(milliseconds: 200);
|
|
|
- var startTime = DateTime.now();
|
|
|
-
|
|
|
- await controllers.config.readClashCoreApi();
|
|
|
-
|
|
|
+ // 启动普通模式的核心进程
|
|
|
+ Future<bool> startNormalCore() async {
|
|
|
try {
|
|
|
- controllers.global.updateMsg("启动内核---${controllers.config.config.value.selected}");
|
|
|
- if (controllers.config.config.value.selected == controllers.config.config.value.selected) {
|
|
|
- controllers.global.updateMsg("启动内核初始化");
|
|
|
- } else {
|
|
|
- controllers.global.updateMsg("启动内核");
|
|
|
- }
|
|
|
+ // 先停止所有现有进程
|
|
|
+ // await controllers.global.stopAllCore();
|
|
|
+
|
|
|
coreStatus.value = RunningState.starting;
|
|
|
+ controllers.global.updateMsg("启动普通模式内核...");
|
|
|
|
|
|
- int? exitCode;
|
|
|
clashCoreProcess = await Process.start(
|
|
|
- Files.assetsCCore.path,
|
|
|
- ['-d', Paths.config.path, '-f', path.join(Paths.config.path, controllers.config.config.value.selected)],
|
|
|
- mode: ProcessStartMode.inheritStdio
|
|
|
+ Files.assetsCCore.path,
|
|
|
+ ['-d', Paths.config.path, '-f', path.join(Paths.config.path, controllers.config.config.value.selected)],
|
|
|
+ mode: ProcessStartMode.inheritStdio
|
|
|
);
|
|
|
- clashCoreProcess!.exitCode.then((code) => exitCode = code);
|
|
|
- if (exitCode != null && exitCode != 0) {
|
|
|
- controllers.global.updateMsg("启动内核错误,请重启点电脑测试");
|
|
|
+
|
|
|
+ // 等待进程启动并检查API可用性
|
|
|
+ if (!await _waitForCoreReady()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
|
|
|
+ coreStatus.value = RunningState.running;
|
|
|
+ controllers.global.updateMsg("普通模式内核启动成功");
|
|
|
+ return true;
|
|
|
+ } catch (e) {
|
|
|
+ controllers.global.updateMsg("启动内核错误: $e");
|
|
|
+ coreStatus.value = RunningState.error;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- while (DateTime.now().difference(startTime) < timeout) {
|
|
|
- try {
|
|
|
- controllers.global.updateMsg("等待内核启动..");
|
|
|
- await controllers.core.fetchHello();
|
|
|
- break;
|
|
|
- } catch (_) {
|
|
|
- await Future.delayed(checkInterval);
|
|
|
- }
|
|
|
+ // 启动TUN模式的核心进程
|
|
|
+ Future<bool> startTunCore(String password) async {
|
|
|
+ Process? process;
|
|
|
+ try {
|
|
|
+ // 先停止所有现有进程
|
|
|
+ await controllers.global.stopAllCore();
|
|
|
+
|
|
|
+ coreStatus.value = RunningState.starting;
|
|
|
+ controllers.global.updateMsg("启动TUN模式内核...");
|
|
|
+
|
|
|
+ final corePath = path.join(Paths.assetsBin.path, path.basename(Files.assetsCCore.path));
|
|
|
+ final configPath = path.join(Paths.config.path, controllers.config.config.value.selected);
|
|
|
+
|
|
|
+ process = await Process.start('bash', [
|
|
|
+ '-c',
|
|
|
+ 'echo "$password" | sudo -S $corePath -d ${Paths.config.path} -f $configPath'
|
|
|
+ ], mode: ProcessStartMode.inheritStdio);
|
|
|
+
|
|
|
+ clashCoreProcess = process;
|
|
|
+
|
|
|
+ // 等待root进程启动
|
|
|
+ if (!await _waitForRootProcess()) {
|
|
|
+ throw Exception("TUN模式进程启动失败");
|
|
|
}
|
|
|
|
|
|
- if (DateTime.now().difference(startTime) >= timeout) {
|
|
|
- coreStatus.value = RunningState.error;
|
|
|
- controllers.global.updateMsg("内核启动超时,重新点击加速后尝试。");
|
|
|
- return false;
|
|
|
+ // 等待API可用
|
|
|
+ if (!await _waitForCoreReady()) {
|
|
|
+ throw Exception("TUN模式API初始化失败");
|
|
|
}
|
|
|
-
|
|
|
- await controllers.core.updateConfig();
|
|
|
+
|
|
|
coreStatus.value = RunningState.running;
|
|
|
- controllers.global.updateMsg("点击连接 ");
|
|
|
+ controllers.global.updateMsg("TUN模式内核启动成功");
|
|
|
return true;
|
|
|
} catch (e) {
|
|
|
- controllers.global.updateMsg("启动内核错误");
|
|
|
+ process?.kill();
|
|
|
+ controllers.global.updateMsg("启动TUN模式失败: $e");
|
|
|
coreStatus.value = RunningState.error;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 等待进程API就绪
|
|
|
+ Future<bool> _waitForCoreReady() async {
|
|
|
+ final timeout = const Duration(seconds: 30);
|
|
|
+ final checkInterval = const Duration(milliseconds: 200);
|
|
|
+ final startTime = DateTime.now();
|
|
|
+
|
|
|
+ controllers.core.setApi(
|
|
|
+ controllers.config.clashCoreApiAddress.value,
|
|
|
+ controllers.config.clashCoreApiSecret.value
|
|
|
+ );
|
|
|
+
|
|
|
+ while (DateTime.now().difference(startTime) < timeout) {
|
|
|
+ try {
|
|
|
+ controllers.global.updateMsg("等待内核启动..");
|
|
|
+ await controllers.core.fetchHello();
|
|
|
+ return true;
|
|
|
+ } catch (_) {
|
|
|
+ await Future.delayed(checkInterval);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 等待root进程启动
|
|
|
+ Future<bool> _waitForRootProcess() async {
|
|
|
+ int retryCount = 0;
|
|
|
+ while (retryCount < 10) {
|
|
|
+ final checkResult = await Process.run('bash', [
|
|
|
+ '-c',
|
|
|
+ 'ps -ef | grep core-darwin | grep root | grep -v grep'
|
|
|
+ ]);
|
|
|
+ if (checkResult.exitCode == 0 && checkResult.stdout.toString().isNotEmpty) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ await Future.delayed(const Duration(milliseconds: 500));
|
|
|
+ retryCount++;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
Future<void> stopClashCore() async {
|
|
|
coreStatus.value = RunningState.stopping;
|