// vpn_bridge_mock.dart — 假内核实现,供 UI 层先行联调 // // 行为: // start() → 立即 emit connecting,[connectDelay] 后 emit on,启动统计计时器 // stop() → 立即 emit off,停止统计计时器 // stats → on 状态下按 [statsInterval] 周期推假数据帧 // // 用法示例(UI 联调): // final bridge = VpnBridgeMock(); // // 用法示例(测试): // final bridge = VpnBridgeMock( // connectDelay: Duration(milliseconds: 50), // statsInterval: Duration(milliseconds: 50), // ); import 'dart:async'; import 'dart:math'; import 'vpn_bridge.dart'; class VpnBridgeMock implements VpnBridge { VpnBridgeMock({ this.connectDelay = const Duration(milliseconds: 1500), this.statsInterval = const Duration(seconds: 1), }); final Duration connectDelay; final Duration statsInterval; // 内部状态 VpnStatus _status = VpnStatus.off; String _activeOutbound = 'auto'; bool _killSwitch = false; final _statusCtrl = StreamController.broadcast(); final _statsCtrl = StreamController.broadcast(); Timer? _connectTimer; Timer? _statsTimer; int _tickCount = 0; final _rng = Random(); // ── helpers ─────────────────────────────────────────────────── void _emitStatus(VpnStatus s) { _status = s; if (!_statusCtrl.isClosed) _statusCtrl.add(s); } void _startStats() { _tickCount = 0; _statsTimer?.cancel(); _statsTimer = Timer.periodic(statsInterval, (_) { _tickCount++; if (!_statsCtrl.isClosed) _statsCtrl.add(_fakeTick(_tickCount)); }); } VpnStatsEvent _fakeTick(int t) { // 模拟稳定带宽 + 微抖动 final upSpeed = 10240.0 + _rng.nextDouble() * 2048; final downSpeed = 51200.0 + _rng.nextDouble() * 8192; return VpnStatsEvent( uploadBytes: (upSpeed * t * statsInterval.inMilliseconds / 1000).round(), downloadBytes: (downSpeed * t * statsInterval.inMilliseconds / 1000).round(), uploadSpeed: upSpeed, downloadSpeed: downSpeed, urltestResults: const [ UrltestResult(tag: 'hk-01', delayMs: 18), UrltestResult(tag: 'jp-01', delayMs: 32), UrltestResult(tag: 'sg-01', delayMs: 54), ], ); } // ── VpnBridge methods ───────────────────────────────────────── @override Future start(String configJson) async { _connectTimer?.cancel(); _statsTimer?.cancel(); _emitStatus(VpnStatus.connecting); _connectTimer = Timer(connectDelay, () { _emitStatus(VpnStatus.on); _startStats(); }); } @override Future stop() async { _connectTimer?.cancel(); _statsTimer?.cancel(); _connectTimer = null; _statsTimer = null; _emitStatus(VpnStatus.off); } @override Future getStatus() async => _status; @override Future selectOutbound(String tag) async { _activeOutbound = tag; // 切换出口时模拟短暂重连 if (_status == VpnStatus.on) { _statsTimer?.cancel(); _emitStatus(VpnStatus.connecting); _connectTimer = Timer(connectDelay ~/ 2, () { _emitStatus(VpnStatus.on); _startStats(); }); } } @override Future getActiveOutbound() async => _activeOutbound; @override Future setKillSwitch({required bool on}) async { _killSwitch = on; } /// 测试可读:mock 记录的 kill-switch 状态。 bool get killSwitchEnabled => _killSwitch; @override Stream get statusStream => _statusCtrl.stream; @override Stream get statsStream => _statsCtrl.stream; @override void dispose() { _connectTimer?.cancel(); _statsTimer?.cancel(); _statusCtrl.close(); _statsCtrl.close(); } }