Files
MWClash/lib/plugins/proxy.dart

121 lines
3.2 KiB
Dart
Raw Normal View History

2024-04-30 23:38:49 +08:00
import 'dart:async';
2024-07-13 16:36:08 +08:00
import 'dart:convert';
import 'dart:ffi';
2024-04-30 23:38:49 +08:00
import 'dart:io';
import 'dart:isolate';
2024-07-13 16:36:08 +08:00
import 'package:fl_clash/clash/clash.dart';
2024-04-30 23:38:49 +08:00
import 'package:fl_clash/common/common.dart';
2024-07-13 16:36:08 +08:00
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart';
2024-07-15 16:14:19 +08:00
import 'package:flutter/material.dart';
2024-04-30 23:38:49 +08:00
import 'package:flutter/services.dart';
import 'package:proxy/proxy_platform_interface.dart';
class Proxy extends ProxyPlatform {
static Proxy? _instance;
late MethodChannel methodChannel;
2024-07-13 16:36:08 +08:00
ReceivePort? receiver;
ServiceMessageListener? _serviceMessageHandler;
2024-04-30 23:38:49 +08:00
Proxy._internal() {
methodChannel = const MethodChannel("proxy");
methodChannel.setMethodCallHandler((call) async {
switch (call.method) {
2024-07-13 16:36:08 +08:00
case "started":
final fd = call.arguments;
onStarted(fd);
2024-04-30 23:38:49 +08:00
break;
default:
throw MissingPluginException();
}
});
}
factory Proxy() {
_instance ??= Proxy._internal();
return _instance!;
}
Future<bool?> initService() async {
2024-07-13 16:36:08 +08:00
return await methodChannel.invokeMethod<bool>("initService");
}
handleStop() {
globalState.stopSystemProxy();
}
2024-04-30 23:38:49 +08:00
@override
Future<bool?> startProxy(port) async {
return await methodChannel.invokeMethod<bool>("startProxy", {
'port': port,
'args': json.encode(clashCore.getProps()),
});
2024-04-30 23:38:49 +08:00
}
@override
Future<bool?> stopProxy() async {
clashCore.stopTun();
2024-07-13 16:36:08 +08:00
final isStop = await methodChannel.invokeMethod<bool>("stopProxy");
2024-04-30 23:38:49 +08:00
if (isStop == true) {
startTime = null;
}
return isStop;
}
Future<bool?> setProtect(int fd) async {
2024-07-13 16:36:08 +08:00
return await methodChannel.invokeMethod<bool?>("setProtect", {'fd': fd});
2024-06-16 19:04:33 +08:00
}
2024-04-30 23:38:49 +08:00
Future<bool?> startForeground({
required String title,
required String content,
}) async {
return await methodChannel.invokeMethod<bool?>("startForeground", {
'title': title,
'content': content,
});
}
bool get isStart => startTime != null && startTime!.isBeforeNow;
2024-04-30 23:38:49 +08:00
2024-07-13 16:36:08 +08:00
onStarted(int? fd) {
2024-07-15 16:14:19 +08:00
debugPrint("onStarted ==> $fd");
2024-07-13 16:36:08 +08:00
if (fd == null) return;
if (receiver != null) {
receiver!.close();
receiver == null;
2024-04-30 23:38:49 +08:00
}
2024-07-13 16:36:08 +08:00
receiver = ReceivePort();
receiver!.listen((message) {
_handleServiceMessage(message);
});
clashCore.startTun(fd, receiver!.sendPort.nativePort);
2024-04-30 23:38:49 +08:00
}
2024-07-13 16:36:08 +08:00
updateStartTime() {
startTime = clashCore.getRunTime();
}
2024-06-16 19:04:33 +08:00
2024-07-13 16:36:08 +08:00
setServiceMessageHandler(ServiceMessageListener serviceMessageListener) {
_serviceMessageHandler = serviceMessageListener;
2024-06-16 19:04:33 +08:00
}
2024-07-13 16:36:08 +08:00
_handleServiceMessage(String message) {
final m = ServiceMessage.fromJson(json.decode(message));
debugPrint(m.toString());
2024-07-13 16:36:08 +08:00
switch (m.type) {
case ServiceMessageType.protect:
_serviceMessageHandler?.onProtect(Fd.fromJson(m.data));
case ServiceMessageType.process:
_serviceMessageHandler?.onProcess(Process.fromJson(m.data));
case ServiceMessageType.started:
_serviceMessageHandler?.onStarted(m.data);
case ServiceMessageType.loaded:
_serviceMessageHandler?.onLoaded(m.data);
}
2024-04-30 23:38:49 +08:00
}
}
final proxy = Platform.isAndroid ? Proxy() : null;