123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import 'dart:async';
- import 'dart:convert';
- import 'dart:io';
- import 'package:speed_safe/app/server/server_base.dart';
- import 'package:speed_safe/app/util/log.dart';
- import 'package:path/path.dart' as p;
- import 'package:speed_safe/app/util/system.dart';
- abstract class CoreBase {
- String coreName;
- List<String> coreArgs;
- late String configFileName;
- late File configFile = File(p.join(tempPath, configFileName));
- Process? coreProcess;
- bool isPreLog = true;
- final List<String> preLogList = [];
- final logStreamController = StreamController<String>.broadcast();
- late final String runningServer;
- Stream<String> get logStream => logStreamController.stream;
- CoreBase(this.coreName, this.coreArgs, this.configFileName);
- Future<void> start(String server) async {
- late final ServerBase serverBase;
- runningServer = server;
- serverBase = ServerBase.fromJson(jsonDecode(server));
- await configure(serverBase);
- logger.i('Starting core: $coreName');
- try {
- coreProcess = await Process.start(
- p.join(binPath, SystemUtil.getCoreFileName(coreName)),
- coreArgs,
- runInShell: true,
- );
- } on ProcessException catch (e) {
- logger.e('Failed to start $coreName: ${e.message}');
- throw Exception('Failed to start $coreName: ${e.message}');
- }
- if (coreProcess == null) {
- throw Exception('Core Process is null');
- }
- listenToProcessStream(coreProcess!.stdout);
- listenToProcessStream(coreProcess!.stderr);
- try {
- if (await coreProcess?.exitCode
- .timeout(const Duration(milliseconds: 500)) !=
- 0) {
- throw Exception('\n${preLogList.join('\n')}');
- }
- } on TimeoutException catch (_) {
- isPreLog = false;
- }
- }
- Future<void> stop() async {
- if (coreProcess != null) {
- logger.i('Stopping core: $coreName');
- coreProcess?.kill(ProcessSignal.sigterm);
- await coreProcess?.exitCode.timeout(const Duration(milliseconds: 500),
- onTimeout: () {
- coreProcess?.kill(ProcessSignal.sigkill);
- return Future.error(
- 'Failed to stop $coreName, force killed the process.');
- });
- coreProcess = null;
- }
- SystemUtil.deleteFileIfExists(
- configFile.path, 'Deleting config file: $configFileName');
- if (coreName == 'sing-box') {
- SystemUtil.deleteFileIfExists(
- p.join(tempPath, 'cache.db'), 'Deleting cache file: cache.db');
- }
- if (!logStreamController.isClosed) {
- await logStreamController.close();
- }
- }
- void listenToProcessStream(Stream<List<int>> stream) {
- stream.transform(utf8.decoder).listen((data) {
- if (data.trim().isNotEmpty) {
- logStreamController.add(data);
- if (isPreLog) {
- preLogList.add(data);
- }
- }
- });
- }
- Future<void> configure(ServerBase server);
- Future<String> generateConfig(ServerBase server);
- Future<void> writeConfig(String jsonString) async {
- SystemUtil.deleteFileIfExists(
- configFile.path, 'Deleting config file: $configFileName');
- await configFile.writeAsString(jsonString);
- }
- }
|