Files
FlClash/lib/core/transport.dart
T
chen08209 7e7f1f89f3 Fix macos performance issue
Support custom global-ua

Update core

Optimize some details
2026-07-11 20:13:36 +08:00

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();
}
}