7e7f1f89f3
Support custom global-ua Update core Optimize some details
107 lines
3.0 KiB
Dart
107 lines
3.0 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:fl_clash/common/common.dart';
|
|
import 'package:fl_clash/enum/enum.dart';
|
|
import 'package:rust_api/rust_api.dart';
|
|
|
|
// ── Binary frame types (mirrors Rust ipc.rs) ────────────────────────────────
|
|
|
|
const _typeReady = 0x00;
|
|
const _typeConnected = 0x01;
|
|
const _typeDisconnected = 0x02;
|
|
const _typeData = 0x03;
|
|
const _typeError = 0x04;
|
|
|
|
class IPCCoreTransport {
|
|
final String address;
|
|
final StreamController<Uint8List> _dataController =
|
|
StreamController<Uint8List>();
|
|
StreamSubscription<Uint8List>? _subscription;
|
|
Completer<void> _completer = Completer<void>();
|
|
Completer<void> _readyCompleter = Completer<void>();
|
|
|
|
void Function()? onDisconnect;
|
|
|
|
IPCCoreTransport({required this.address});
|
|
|
|
Completer<void> get connectionCompleter => _completer;
|
|
|
|
Stream<Uint8List> get dataStream => _dataController.stream;
|
|
|
|
Future<void> init() async {
|
|
try {
|
|
final stream = restartIpcServer(name: address);
|
|
_subscription = stream.listen(
|
|
(data) {
|
|
if (data.isEmpty) return;
|
|
final type = data[0];
|
|
final payload = data.length > 1 ? data.sublist(1) : Uint8List(0);
|
|
switch (type) {
|
|
case _typeReady:
|
|
commonPrint.log('IPC Ready');
|
|
if (_readyCompleter.isCompleted) {
|
|
break;
|
|
}
|
|
_readyCompleter.complete();
|
|
break;
|
|
case _typeConnected:
|
|
commonPrint.log('IPC Connected');
|
|
if (_completer.isCompleted) {
|
|
break;
|
|
}
|
|
_completer.complete();
|
|
break;
|
|
case _typeDisconnected:
|
|
commonPrint.log('IPC Disconnected');
|
|
_completer = Completer<void>();
|
|
onDisconnect?.call();
|
|
break;
|
|
case _typeData:
|
|
_dataController.add(payload);
|
|
break;
|
|
case _typeError:
|
|
final msg = utf8.decode(payload);
|
|
commonPrint.log('IPC error: $msg', logLevel: LogLevel.error);
|
|
break;
|
|
default:
|
|
commonPrint.log(
|
|
'IPC unknown frame type: $type',
|
|
logLevel: LogLevel.warning,
|
|
);
|
|
}
|
|
},
|
|
onError: (error) {
|
|
commonPrint.log('IPC error: $error', logLevel: LogLevel.error);
|
|
},
|
|
cancelOnError: false,
|
|
);
|
|
await _readyCompleter.future;
|
|
} catch (e) {
|
|
commonPrint.log(
|
|
'Failed to start IPC server: $e',
|
|
logLevel: LogLevel.error,
|
|
);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
void send(String message) {
|
|
sendIpcMessage(data: utf8.encode(message));
|
|
}
|
|
|
|
void disconnected() {
|
|
_completer = Completer<void>();
|
|
}
|
|
|
|
Future<void> close() async {
|
|
await _subscription?.cancel();
|
|
_subscription = null;
|
|
await stopIpcServer();
|
|
_readyCompleter = Completer<void>();
|
|
_completer = Completer<void>();
|
|
await _dataController.close();
|
|
}
|
|
}
|