alroyso 1 year ago
parent
commit
0c1ca74ef0

+ 13 - 6
lib/app/controller/GlobalController.dart

@@ -8,12 +8,15 @@ import 'package:naiyouwl/app/controller/controllers.dart';
 import 'package:naiyouwl/app/data/model/NodeMode.dart';
 import 'package:naiyouwl/app/network/api_service.dart';
 import 'package:naiyouwl/app/network/dio_client.dart';
+import 'package:naiyouwl/app/utils/shell.dart';
 import 'package:naiyouwl/app/utils/system_proxy.dart';
 import 'package:naiyouwl/app/utils/utils.dart';
 import 'package:proxy_manager/proxy_manager.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:tray_manager/tray_manager.dart';
 import 'package:window_manager/window_manager.dart';
+import 'package:path/path.dart' as path;
+import '../const/const.dart';
 
 class GlobalController extends GetxController {
   final proxyManager = ProxyManager();
@@ -70,9 +73,9 @@ class GlobalController extends GetxController {
     // await controllers.service.serviceModeSwitch(true);
     // init clash core
 
-    await controllers.service.initClashCoreConfig();
-    if (controllers.service.coreStatus.value != RunningState.running) return;
-    await controllers.core.updateVersion();
+    // await controllers.service.initClashCoreConfig();
+    // if (controllers.service.coreStatus.value != RunningState.running) return;
+    // await controllers.core.updateVersion();
     //initRegularlyUpdate();
   }
 
@@ -408,10 +411,14 @@ class GlobalController extends GetxController {
     proxyManager.cleanSystemProxy();
     systemProxy = false;
   }
-
-  Future<void> handleExit() async {
+  Future<void> stopAllCore() async {
     await systemProxySwitch(false);
-    await controllers.service.stopService();
+    await controllers.service.stopClashCore();
+    await killProcess(path.basename(Files.assetsCCore.path));
+    await killProcess(path.basename(Files.assetsClashService.path));
+  }
+  Future<void> handleExit() async {
+    await stopAllCore();
     await trayManager.destroy();
     await windowManager.destroy();
     // exit(0);

+ 3 - 1
lib/app/controller/config.dart

@@ -227,6 +227,7 @@ $rules
   Future<void> readClashCoreApi() async {
 
     final configStr = await File(path.join(Paths.config.path, config.value.selected)).readAsString();
+    //print("config ---- $configStr");
     // final emoji = EmojiParser();
     // final b = emoji.unemojify(_config);
     final configJson = loadYaml(configStr.replaceAll(EmojiParser.REGEX_EMOJI, 'emoji'));
@@ -234,7 +235,8 @@ $rules
     // https://github.com/dart-lang/yaml/issues/53
     // final _extControl = RegExp(r'''(?<!#\s*)external-controller:\s+['"]?([^'"]+?)['"]?\s''').firstMatch(_config)?.group(1);
     // final _secret = RegExp(r'''(?<!#\s*)secret:\s+['"]?([^'"]+?)['"]?\s''').firstMatch(_config)?.group(1);
-    clashCoreApiAddress.value = (configJson["external-controller"] ?? '127.0.0.1:9090').replaceAll('0.0.0.0', '127.0.0.1');
+    clashCoreApiAddress.value = configJson["external-controller"] ?? '127.0.0.1:9090';
+    //print("clash api address ${clashCoreApiAddress.value}");
     clashCoreApiSecret.value = (configJson["secret"] ?? '');
     clashCoreTunEnable.value = configJson["tun"]?["enable"] == true;
     clashCoreDns.value = '';

+ 6 - 3
lib/app/controller/core.dart

@@ -61,7 +61,9 @@ class CoreController extends GetxController {
   setApi(String apiAddress, String apiSecret) {
     address.value = apiAddress;
     secret.value = apiSecret;
+    // dio.close(force: true);
     dio.options.baseUrl = 'http://${address.value}';
+    print("dio baseUrl api ${dio.options.baseUrl}");
     dio.options.headers['Authorization'] = 'Bearer ${secret.value}';
   }
 
@@ -77,7 +79,7 @@ class CoreController extends GetxController {
   Future<void> updateConfig() async {
     final res = await dio.get('/configs');
     config.value = ClashCoreConfig.fromJson(res.data);
-    LogHelper().d("update-config ${config.value}");
+    //LogHelper().d("update-config ${config.value}");
   }
 
   Future<void> fetchConfigUpdate(Map<String, dynamic> config) async {
@@ -91,6 +93,7 @@ class CoreController extends GetxController {
   // }
   // https://github.com/Dreamacro/clash/blob/c231fd14666d6ea05d6a75eaba6db69f9eee5ae9/hub/route/configs.go#L95
   Future<void> fetchReloadConfig(Map<String, String> config) async {
+    print("fetchReloadConfig $config");
     await dio.put('/configs', data: config);
   }
 
@@ -152,7 +155,7 @@ class CoreController extends GetxController {
   Future<Connect> fetchConnection() async {
     final res = await dio.get('/connections');
     if(res.data !=null){
-      LogHelper().d("没有连接");
+     // LogHelper().d("没有连接");
       //return Connect();
     }
     return Connect.fromJson(res.data);
@@ -176,7 +179,7 @@ class FriendlyErrorInterceptor extends Interceptor {
     } else if (err.type == DioErrorType.other) {
       message = 'core 其他错误: ${err.message}';
     }
-    LogHelper().d(message);
+   // LogHelper().d(message);
     return DioError(error: message, requestOptions: err.requestOptions);
   }
 }

+ 37 - 29
lib/app/controller/service.dart

@@ -32,6 +32,7 @@ class ServiceController extends GetxController {
   var serviceStatus = RunningState.stoped.obs;
 
   Process? clashServiceProcess;
+  Process? clashCoreProcess;
 
   bool get isRunning => serviceStatus.value == RunningState.running && coreStatus.value == RunningState.running;
   bool get isCanOperationService =>
@@ -74,7 +75,7 @@ class ServiceController extends GetxController {
   }
 
   Future<void> isService() async {
-    controllers.global.updateMsg("判断是不是 service-mode");
+    //controllers.global.updateMsg("判断是不是 service-mode");
     //serviceStatus.value = RunningState.starting;
     if (Platform.isLinux) {
       await fixBinaryExecutePermissions(Files.assetsClashService);
@@ -242,42 +243,35 @@ class ServiceController extends GetxController {
 
     Future<void> startClashCore() async {
       try {
-        //controllers.global.updateMsg("启动内核");
+        controllers.global.updateMsg("启动内核---${controllers.config.config.value.selected}");
         if( controllers.config.config.value.selected == 'init_proxy.yaml'){
           controllers.global.updateMsg("启动内核初始化");
         } else {
           controllers.global.updateMsg("启动内核");
         }
         coreStatus.value = RunningState.starting;
-        // final res = await _dio.post<String>('/start', data: {
-        //   "args": ['-d', Paths.config.path, '-f', path.join(Paths.config.path, name)]
-        // });
-        final res = await runCCore(Files.assetsCCore.path, ['-d', Paths.config.path, '-f', path.join(Paths.config.path, controllers.config.config.value.selected)]);
-        if (res.exitCode != 0) {
-          controllers.global.updateMsg("启动内核失败");
-          coreStatus.value = RunningState.error;
-          throw res.stderr;
+        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);
+        clashCoreProcess!.exitCode.then((code) => exitCode = code);
 
-        }
-        coreStatus.value = RunningState.running;
         //await fetchStart(controllers.config.config.value.selected);
         log.debug("api${controllers.config.clashCoreApiAddress.value}");
         controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
+        if (exitCode != null)
+        {
+            controllers.global.updateMsg("启动内核错误");
+            return;
+        }
         while (true) {
+          log.debug("等待内核请动...");
           await Future.delayed(const Duration(milliseconds: 200));
-          final info = await fetchInfo();
-          if (info.status == 'running') {
-            try {
-              final ret = await controllers.core.fetchHello();
-              log.debug("请求内核结果$ret---服务器状态${info.status}...");
-             // controllers.global.updateMsg("请求内核结果$ret---服务器状态${info.status}...");
-              break;
-            } catch (_) {
-              //controllers.global.updateMsg("请求内核错误${e.toString()}---服务器状态${info.status}...");
-            }
-          } else {
-            controllers.global.updateMsg("启动内核错误---等待中...");
-            throw '启动内核错误,请检测是否被杀毒拦截,或者端口是否被占用';
+          try {
+            final ret = await controllers.core.fetchHello();
+            log.debug("请求内核结果$ret...");
+            // controllers.global.updateMsg("请求内核结果$ret---服务器状态${info.status}...");
+            break;
+          } catch (_) {
+            //controllers.global.updateMsg("请求内核错误${e.toString()}---服务器状态${info.status}...");
           }
         }
         await controllers.core.updateConfig();
@@ -302,6 +296,12 @@ class ServiceController extends GetxController {
 
     Future<void> stopClashCore() async {
       coreStatus.value = RunningState.stopping;
+      await controllers.global.closeProxy();
+      if(clashCoreProcess != null){
+        clashCoreProcess?.kill();
+      }
+
+      // killProcess(ClashName.name);
       // if (Platform.isMacOS &&
       //     controllers.service.serviceMode.value &&
       //     controllers.config.clashCoreTunEnable.value &&
@@ -309,7 +309,7 @@ class ServiceController extends GetxController {
       //   await MacSystemDns.instance.set([]);
       // }
       //if (controllers.config.config.value.setSystemProxy) await SystemProxy.instance.set(SystemProxyConfig());
-      await stopClash();
+      //await stopClash();
       //await fetchStop();
       coreStatus.value = RunningState.stoped;
     }
@@ -330,14 +330,22 @@ class ServiceController extends GetxController {
   Future<void> stopClash() async {
     controllers.config.config.value.selected = 'init_proxy.yaml';
     if( coreStatus.value == RunningState.running){
+      await controllers.config.readClashCoreApi();
+      controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
       await controllers.core.fetchReloadConfig({"path":  path.join(Paths.config.path, controllers.config.config.value.selected),"payload": ""});
     }
   }
     Future<void> reloadClashCore() async {
       controllers.config.config.value.selected = 'proxy.yaml';
-      if( coreStatus.value == RunningState.running){
-        await controllers.core.fetchReloadConfig({"path":  path.join(Paths.config.path, controllers.config.config.value.selected),"payload":""});
-      }
+      // if( coreStatus.value == RunningState.running){
+      //   controllers.global.updateMsg("重新配置...");
+      //   await controllers.config.readClashCoreApi();
+      //   controllers.global.updateMsg("${controllers.config.clashCoreApiAddress.value}...");
+      //   controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
+      //   controllers.global.updateMsg("setApi${controllers.config.clashCoreApiAddress.value}...");
+      //   await controllers.core.fetchReloadConfig({"path":  path.join(Paths.config.path, controllers.config.config.value.selected),"payload":""});
+      //   controllers.global.updateMsg("fetchReloadConfig${controllers.config.clashCoreApiAddress.value}...");
+      // }
       //BotToast.showText(text: '正在重启 Core ……');
       // controllers.global.updateMsg("停止内核...");
       // await stopClashCore();

+ 2 - 1
lib/app/controller/tray.dart

@@ -23,7 +23,8 @@ class TrayController extends GetxController with TrayListener {
 
   Future<void> updateTray() async {
     final visible = await windowManager.isVisible();
-    final disabled = !controllers.service.isRunning;
+    final disabled = controllers.service.coreStatus.value != RunningState.running;
+
     var disabledSerivce = false;
     if(Platform.isWindows){
       disabledSerivce = true;

+ 2 - 0
lib/app/modules/home/controllers/home_controller.dart

@@ -100,6 +100,7 @@ class HomeController extends GetxController {
       updateStatus(ConnectionStatus.disconnected);
       return;
     } else {
+      controllers.config.config.value.selected = 'proxy.yaml';
       controllers.global.updateMsg("开始连接...");
       await controllers.config.setBreakConnections(true);
       controllers.global.allowStatusUpdate = true;
@@ -147,6 +148,7 @@ class HomeController extends GetxController {
         }
         else{
           controllers.global.updateMsg("正在启动内核...");
+
           await controllers.service.startClashCore();
         }
 

+ 2 - 1
lib/app/modules/home/views/home_view.dart

@@ -204,12 +204,13 @@ class HomeView extends GetView<HomeController> {
                     ],
 
                   ),
-                ) : Container()
+                ) : Container(),
                 // const SizedBox(height: 20,),
                 // Align(
                 //   alignment: Alignment.center,
                 //   child:,
                 // )
+                Text(controllers.config.clashCoreApiAddress.value)
               ],
             );
           })

+ 11 - 11
lib/app/network/dio_client.dart

@@ -25,17 +25,17 @@ class DioClient {
       receiveTimeout: 3000,
     ));
 
-    // 仅在调试模式下添加日志拦截器
-    assert(() {
-      _dio.interceptors.add(LogInterceptor(
-        request: true,
-        requestBody: true,
-        responseBody: true,
-        error: true,
-        logPrint: _logger.d, // 使用 Logger 插件打印日志
-      ));
-      return true;
-    }());
+    // // 仅在调试模式下添加日志拦截器
+    // assert(() {
+    //   _dio.interceptors.add(LogInterceptor(
+    //     request: true,
+    //     requestBody: true,
+    //     responseBody: true,
+    //     error: true,
+    //     logPrint: _logger.d, // 使用 Logger 插件打印日志
+    //   ));
+    //   return true;
+    // }());
     final customInterceptor = CustomInterceptors(_dio);
     //token
     _dio.interceptors.add(TokenInterceptor());

+ 7 - 8
lib/app/utils/shell.dart

@@ -1,3 +1,4 @@
+import 'dart:ffi';
 import 'dart:io';
 
 import 'package:process_run/shell.dart';
@@ -34,17 +35,15 @@ Future<bool> isRunningAsAdmin() async {
 
   return false;
 }
-
+Future<bool> killCCoreProcess(int pid) async {
+    return Process.killPid(pid);
+}
 Future<ProcessResult> runCCore(String executable, List<String> arguments) async {
   String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
-  //executablePath = executablePath.substring(1, executablePath.length - 1);
   if (Platform.isMacOS) {
     return await Process.run(
-      'osascript',
-      [
-        '-e',
-        shellArguments(['do', 'shell', 'script', '$executablePath ${shellArguments(arguments)}', 'with', 'administrator', 'privileges']),
-      ],
+      path.join(Paths.assetsBin.path, executablePath),
+      [executable, ...arguments],
     );
   } else if (Platform.isWindows) {
     return await Process.run(
@@ -61,7 +60,7 @@ Future<ProcessResult> runCCore(String executable, List<String> arguments) async
 
 
 Future<ProcessResult> runCCoreAsAdmin(String executable, List<String> arguments) async {
-  String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
+  // String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
   return await Process.run(
     path.join(Paths.assetsBin.path, "run-as-admin.bat"),
     [executable, ...arguments],