tor lifecycle management

This commit is contained in:
Fabian Freund
2025-03-16 20:55:33 +01:00
parent 6830d94bac
commit 9bc9c53559
10 changed files with 176 additions and 24 deletions
@@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:ui';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:lensai/features/geckoview/features/browser/domain/providers/lifecycle.dart';
import 'package:lensai/features/tor/utils/tor_entrypoint.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:rxdart/rxdart.dart';
@@ -18,6 +20,14 @@ class _TorService {
await service.startService();
}
Future<void> requestSync() async {
service.invoke("sync");
}
Future<void> sendHeartbeat() async {
service.invoke("heartbeat");
}
Future<void> stop() async {
service.invoke("stop");
}
@@ -39,9 +49,9 @@ class _TorService {
});
}
void dispose() {
unawaited(stop());
unawaited(_portSubject.close());
Future<void> dispose() async {
await stop();
await _portSubject.close();
}
}
@@ -49,17 +59,44 @@ class _TorService {
class TorProxyService extends _$TorProxyService {
final _tor = _TorService();
Timer? _heartbeatUpdate;
//This is managed by widget state changes to resume a timer
bool _timerPaused = false;
void _enableHeartbeatTimer() {
_heartbeatUpdate?.cancel();
_timerPaused = false;
_heartbeatUpdate = Timer.periodic(const Duration(seconds: 30), (
timer,
) async {
await _tor.sendHeartbeat();
});
}
Future<void> connect({bool forceReconnect = false}) async {
final currentPort = _tor.portStream.valueOrNull;
final currentPort = await requestSync();
if (currentPort == null || forceReconnect) {
state = const AsyncLoading();
await _tor.start();
_enableHeartbeatTimer();
}
}
Future<int?> requestSync() async {
final nextPortUpdate = _tor.portStream.first;
await _tor.requestSync();
return nextPortUpdate;
}
Future<void> disconnect() async {
state = const AsyncLoading();
_heartbeatUpdate?.cancel();
_heartbeatUpdate = null;
_timerPaused = false;
await _tor.stop();
}
@@ -71,9 +108,31 @@ class TorProxyService extends _$TorProxyService {
await _tor.initializeService();
ref.listen(browserViewLifecycleProvider, (previous, next) {
switch (next) {
case AppLifecycleState.resumed:
if (_timerPaused) {
_enableHeartbeatTimer();
}
case AppLifecycleState.detached:
case AppLifecycleState.inactive:
case AppLifecycleState.hidden:
case AppLifecycleState.paused:
case null:
if (_heartbeatUpdate?.isActive == true) {
_heartbeatUpdate?.cancel();
_timerPaused = true;
}
}
});
ref.onDispose(() async {
_heartbeatUpdate?.cancel();
_heartbeatUpdate = null;
_timerPaused = false;
await portSub.cancel();
_tor.dispose();
await _tor.dispose();
});
return _tor.portStream.valueOrNull;
@@ -6,7 +6,7 @@ part of 'tor_proxy.dart';
// RiverpodGenerator
// **************************************************************************
String _$torProxyServiceHash() => r'782708b8e5159931cecf8d32b843cb96a929fb1f';
String _$torProxyServiceHash() => r'1f0c7611fd939ff25ad0acbdbd205b7e6e83067c';
/// See also [TorProxyService].
@ProviderFor(TorProxyService)