fix lints
This commit is contained in:
@@ -258,8 +258,8 @@ class TorProxyScreen extends HookConsumerWidget {
|
|||||||
left: 56,
|
left: 56,
|
||||||
right: 24,
|
right: 24,
|
||||||
),
|
),
|
||||||
title: Text('Direct Connection'),
|
title: const Text('Direct Connection'),
|
||||||
subtitle: Text(
|
subtitle: const Text(
|
||||||
'The best way to connect to Tor if Tor is not blocked',
|
'The best way to connect to Tor if Tor is not blocked',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -285,8 +285,8 @@ class TorProxyScreen extends HookConsumerWidget {
|
|||||||
left: 56,
|
left: 56,
|
||||||
right: 24,
|
right: 24,
|
||||||
),
|
),
|
||||||
title: Text('obfs4'),
|
title: const Text('obfs4'),
|
||||||
subtitle: Text(
|
subtitle: const Text(
|
||||||
'Suitable for light censorship and high bandwidth needs',
|
'Suitable for light censorship and high bandwidth needs',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -312,8 +312,8 @@ class TorProxyScreen extends HookConsumerWidget {
|
|||||||
left: 56,
|
left: 56,
|
||||||
right: 24,
|
right: 24,
|
||||||
),
|
),
|
||||||
title: Text('Snowflake'),
|
title: const Text('Snowflake'),
|
||||||
subtitle: Text('Suitable for heavy censorship'),
|
subtitle: const Text('Suitable for heavy censorship'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
CheckboxListTile.adaptive(
|
CheckboxListTile.adaptive(
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ dependencies:
|
|||||||
text_scroll: ^0.2.1
|
text_scroll: ^0.2.1
|
||||||
timeago: ^3.7.1
|
timeago: ^3.7.1
|
||||||
tor:
|
tor:
|
||||||
path: ./packages/tor
|
path: ../packages/tor
|
||||||
universal_io: ^2.2.2
|
universal_io: ^2.2.2
|
||||||
uri_to_file:
|
uri_to_file:
|
||||||
git:
|
git:
|
||||||
|
|||||||
@@ -31,14 +31,20 @@ class MoatApi {
|
|||||||
MoatApi(this._client);
|
MoatApi(this._client);
|
||||||
|
|
||||||
Future<SettingsResponse> settings([SettingsRequest? request]) async {
|
Future<SettingsResponse> settings([SettingsRequest? request]) async {
|
||||||
final response = await _post('settings', request ?? SettingsRequest());
|
final response = await _post(
|
||||||
|
'settings',
|
||||||
|
request ?? const SettingsRequest(),
|
||||||
|
);
|
||||||
return SettingsResponse.fromJson(
|
return SettingsResponse.fromJson(
|
||||||
jsonDecode(response.body) as Map<String, dynamic>,
|
jsonDecode(response.body) as Map<String, dynamic>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SettingsResponse> defaults([SettingsRequest? request]) async {
|
Future<SettingsResponse> defaults([SettingsRequest? request]) async {
|
||||||
final response = await _post('defaults', request ?? SettingsRequest());
|
final response = await _post(
|
||||||
|
'defaults',
|
||||||
|
request ?? const SettingsRequest(),
|
||||||
|
);
|
||||||
return SettingsResponse.fromJson(
|
return SettingsResponse.fromJson(
|
||||||
jsonDecode(response.body) as Map<String, dynamic>,
|
jsonDecode(response.body) as Map<String, dynamic>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:http/io_client.dart';
|
import 'package:http/io_client.dart';
|
||||||
import 'package:pluggable_transports_proxy/pluggable_transports_proxy.dart';
|
import 'package:pluggable_transports_proxy/pluggable_transports_proxy.dart';
|
||||||
import 'package:pluggable_transports_proxy/src/data/models/moat.dart';
|
|
||||||
import 'package:pluggable_transports_proxy/src/data/service/moat_api.dart';
|
import 'package:pluggable_transports_proxy/src/data/service/moat_api.dart';
|
||||||
import 'package:socks5_proxy/socks_client.dart';
|
import 'package:socks5_proxy/socks_client.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,39 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Foundation Devices Inc.
|
# This file configures the static analysis results for your project (errors,
|
||||||
# SPDX-FileCopyrightText: 2024 Foundation Devices Inc.
|
# warnings, and lints).
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: MIT
|
# This enables the 'recommended' set of lints from `package:lints`.
|
||||||
|
# This set helps identify many issues that may lead to problems when running
|
||||||
|
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||||
|
# style and format.
|
||||||
|
#
|
||||||
|
# If you want a smaller set of lints you can change this to specify
|
||||||
|
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||||
|
# (the recommended set includes the core lints).
|
||||||
|
# The core lints are also what is used by pub.dev for scoring packages.
|
||||||
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:lint/strict.yaml
|
||||||
|
# Uncomment the following section to specify additional rules.
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
unawaited_futures: true
|
||||||
|
discarded_futures: true
|
||||||
|
collection_methods_unrelated_type: true
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
|
errors:
|
||||||
|
overridden_fields: ignore
|
||||||
|
plugins:
|
||||||
|
- custom_lint
|
||||||
exclude:
|
exclude:
|
||||||
- 'lib/generated*'
|
- "**.drift"
|
||||||
- 'cargokit'
|
- "**.g.dart"
|
||||||
|
- "**.swagger.dart"
|
||||||
|
- "**.freezed.dart"
|
||||||
|
- "**.chopper.dart"
|
||||||
|
- "lib/generated_bindings.dart"
|
||||||
|
# For more information about the core and recommended set of lints, see
|
||||||
|
# https://dart.dev/go/core-lints
|
||||||
|
|
||||||
|
# For additional information about configuring this file, see
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
|||||||
@@ -95,19 +95,28 @@ class SOCKSSocket {
|
|||||||
/// Is SSL enabled?
|
/// Is SSL enabled?
|
||||||
final bool sslEnabled;
|
final bool sslEnabled;
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
SOCKSSocket({
|
||||||
|
required this.proxyHost,
|
||||||
|
required this.proxyPort,
|
||||||
|
required this.sslEnabled,
|
||||||
|
}) {
|
||||||
|
unawaited(_init());
|
||||||
|
}
|
||||||
|
|
||||||
/// Private constructor.
|
/// Private constructor.
|
||||||
SOCKSSocket._(this.proxyHost, this.proxyPort, this.sslEnabled);
|
SOCKSSocket._(this.proxyHost, this.proxyPort, this.sslEnabled);
|
||||||
|
|
||||||
/// Provides a stream of data as List<int>.
|
/// Provides a stream of data as List`<int>`.
|
||||||
Stream<List<int>> get inputStream => sslEnabled
|
Stream<List<int>> get inputStream => sslEnabled
|
||||||
? _secureResponseController.stream
|
? _secureResponseController.stream
|
||||||
: _responseController.stream;
|
: _responseController.stream;
|
||||||
|
|
||||||
/// Provides a StreamSink compatible with List<int> for sending data.
|
/// Provides a StreamSink compatible with List`<int>` for sending data.
|
||||||
StreamSink<List<int>> get outputStream {
|
StreamSink<List<int>> get outputStream {
|
||||||
// Create a simple StreamSink wrapper for _socksSocket and
|
// Create a simple StreamSink wrapper for _socksSocket and
|
||||||
// _secureSocksSocket that accepts List<int> and forwards it to write method.
|
// _secureSocksSocket that accepts List<int> and forwards it to write method.
|
||||||
var sink = StreamController<List<int>>();
|
final sink = StreamController<List<int>>();
|
||||||
sink.stream.listen((data) {
|
sink.stream.listen((data) {
|
||||||
if (sslEnabled) {
|
if (sslEnabled) {
|
||||||
_secureSocksSocket.add(data);
|
_secureSocksSocket.add(data);
|
||||||
@@ -129,12 +138,13 @@ class SOCKSSocket {
|
|||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// A Future that resolves to a SOCKSSocket instance.
|
/// A Future that resolves to a SOCKSSocket instance.
|
||||||
static Future<SOCKSSocket> create(
|
static Future<SOCKSSocket> create({
|
||||||
{required String proxyHost,
|
required String proxyHost,
|
||||||
required int proxyPort,
|
required int proxyPort,
|
||||||
bool sslEnabled = false}) async {
|
bool sslEnabled = false,
|
||||||
|
}) async {
|
||||||
// Create a SOCKS socket instance.
|
// Create a SOCKS socket instance.
|
||||||
var instance = SOCKSSocket._(proxyHost, proxyPort, sslEnabled);
|
final instance = SOCKSSocket._(proxyHost, proxyPort, sslEnabled);
|
||||||
|
|
||||||
// Initialize the SOCKS socket.
|
// Initialize the SOCKS socket.
|
||||||
await instance._init();
|
await instance._init();
|
||||||
@@ -143,14 +153,6 @@ class SOCKSSocket {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
SOCKSSocket(
|
|
||||||
{required this.proxyHost,
|
|
||||||
required this.proxyPort,
|
|
||||||
required this.sslEnabled}) {
|
|
||||||
_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initializes the SOCKS socket.
|
/// Initializes the SOCKS socket.
|
||||||
///
|
///
|
||||||
/// This method is a private method that is called by the constructor.
|
/// This method is a private method that is called by the constructor.
|
||||||
@@ -159,10 +161,7 @@ class SOCKSSocket {
|
|||||||
/// A Future that resolves to void.
|
/// A Future that resolves to void.
|
||||||
Future<void> _init() async {
|
Future<void> _init() async {
|
||||||
// Connect to the SOCKS proxy server.
|
// Connect to the SOCKS proxy server.
|
||||||
_socksSocket = await Socket.connect(
|
_socksSocket = await Socket.connect(proxyHost, proxyPort);
|
||||||
proxyHost,
|
|
||||||
proxyPort,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Listen to the socket.
|
// Listen to the socket.
|
||||||
_subscription = _socksSocket.listen(
|
_subscription = _socksSocket.listen(
|
||||||
@@ -196,12 +195,13 @@ class SOCKSSocket {
|
|||||||
_socksSocket.add([0x05, 0x01, 0x00]);
|
_socksSocket.add([0x05, 0x01, 0x00]);
|
||||||
|
|
||||||
// Wait for server response.
|
// Wait for server response.
|
||||||
var response = await _responseController.stream.first;
|
final response = await _responseController.stream.first;
|
||||||
|
|
||||||
// Check if the connection was successful.
|
// Check if the connection was successful.
|
||||||
if (response[1] != 0x00) {
|
if (response[1] != 0x00) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'socks_socket.connect(): Failed to connect to SOCKS5 proxy.');
|
'socks_socket.connect(): Failed to connect to SOCKS5 proxy.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -217,7 +217,7 @@ class SOCKSSocket {
|
|||||||
/// A Future that resolves to void.
|
/// A Future that resolves to void.
|
||||||
Future<void> connectTo(String domain, int port) async {
|
Future<void> connectTo(String domain, int port) async {
|
||||||
// Connect command.
|
// Connect command.
|
||||||
var request = [
|
final request = [
|
||||||
0x05, // SOCKS version.
|
0x05, // SOCKS version.
|
||||||
0x01, // Connect command.
|
0x01, // Connect command.
|
||||||
0x00, // Reserved.
|
0x00, // Reserved.
|
||||||
@@ -225,19 +225,20 @@ class SOCKSSocket {
|
|||||||
domain.length,
|
domain.length,
|
||||||
...domain.codeUnits,
|
...domain.codeUnits,
|
||||||
(port >> 8) & 0xFF,
|
(port >> 8) & 0xFF,
|
||||||
port & 0xFF
|
port & 0xFF,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Send the connect command to the SOCKS proxy server.
|
// Send the connect command to the SOCKS proxy server.
|
||||||
_socksSocket.add(request);
|
_socksSocket.add(request);
|
||||||
|
|
||||||
// Wait for server response.
|
// Wait for server response.
|
||||||
var response = await _responseController.stream.first;
|
final response = await _responseController.stream.first;
|
||||||
|
|
||||||
// Check if the connection was successful.
|
// Check if the connection was successful.
|
||||||
if (response[1] != 0x00) {
|
if (response[1] != 0x00) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'socks_socket.connectTo(): Failed to connect to target through SOCKS5 proxy.');
|
'socks_socket.connectTo(): Failed to connect to target through SOCKS5 proxy.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade to SSL if needed.
|
// Upgrade to SSL if needed.
|
||||||
@@ -265,9 +266,9 @@ class SOCKSSocket {
|
|||||||
_secureResponseController.addError("$e");
|
_secureResponseController.addError("$e");
|
||||||
// TODO make sure sending error as string is acceptable.
|
// TODO make sure sending error as string is acceptable.
|
||||||
},
|
},
|
||||||
onDone: () {
|
onDone: () async {
|
||||||
// Close the response controller when the socket is closed.
|
// Close the response controller when the socket is closed.
|
||||||
_secureResponseController.close();
|
await _secureResponseController.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -288,7 +289,7 @@ class SOCKSSocket {
|
|||||||
if (object == null) return;
|
if (object == null) return;
|
||||||
|
|
||||||
// Write the data to the socket.
|
// Write the data to the socket.
|
||||||
List<int> data = utf8.encode(object.toString());
|
final List<int> data = utf8.encode(object.toString());
|
||||||
if (sslEnabled) {
|
if (sslEnabled) {
|
||||||
_secureSocksSocket.add(data);
|
_secureSocksSocket.add(data);
|
||||||
} else {
|
} else {
|
||||||
@@ -310,9 +311,9 @@ class SOCKSSocket {
|
|||||||
} finally {
|
} finally {
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
await _socksSocket.close();
|
await _socksSocket.close();
|
||||||
_responseController.close();
|
await _responseController.close();
|
||||||
if (sslEnabled) {
|
if (sslEnabled) {
|
||||||
_secureResponseController.close();
|
await _secureResponseController.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,7 +356,7 @@ class SOCKSSocket {
|
|||||||
_socksSocket.writeln(command);
|
_socksSocket.writeln(command);
|
||||||
|
|
||||||
// Wait for the response from the proxy server.
|
// Wait for the response from the proxy server.
|
||||||
var responseData = await _responseController.stream.first;
|
final responseData = await _responseController.stream.first;
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("responseData: ${utf8.decode(responseData)}");
|
print("responseData: ${utf8.decode(responseData)}");
|
||||||
}
|
}
|
||||||
@@ -364,7 +365,7 @@ class SOCKSSocket {
|
|||||||
_secureSocksSocket.writeln(command);
|
_secureSocksSocket.writeln(command);
|
||||||
|
|
||||||
// Wait for the response from the proxy server.
|
// Wait for the response from the proxy server.
|
||||||
var responseData = await _secureResponseController.stream.first;
|
final responseData = await _secureResponseController.stream.first;
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("secure responseData: ${utf8.decode(responseData)}");
|
print("secure responseData: ${utf8.decode(responseData)}");
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-49
@@ -14,7 +14,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:tor/generated_bindings.dart' as rust;
|
import 'package:tor/generated_bindings.dart' as rust;
|
||||||
|
|
||||||
DynamicLibrary load(name) {
|
DynamicLibrary load(String name) {
|
||||||
if (Platform.isAndroid || Platform.isLinux) {
|
if (Platform.isAndroid || Platform.isLinux) {
|
||||||
return DynamicLibrary.open('lib$name.so');
|
return DynamicLibrary.open('lib$name.so');
|
||||||
} else if (Platform.isIOS || Platform.isMacOS) {
|
} else if (Platform.isIOS || Platform.isMacOS) {
|
||||||
@@ -33,7 +33,9 @@ class CouldntBootstrapDirectory implements Exception {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NotSupportedPlatform implements Exception {
|
class NotSupportedPlatform implements Exception {
|
||||||
NotSupportedPlatform(String s);
|
String reason;
|
||||||
|
|
||||||
|
NotSupportedPlatform(this.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientNotActive implements Exception {}
|
class ClientNotActive implements Exception {}
|
||||||
@@ -97,8 +99,8 @@ class Tor {
|
|||||||
/// Returns a Future that completes when the Tor service has started.
|
/// Returns a Future that completes when the Tor service has started.
|
||||||
///
|
///
|
||||||
/// Throws an exception if the Tor service fails to start.
|
/// Throws an exception if the Tor service fails to start.
|
||||||
static Future<Tor> init({enabled = true}) async {
|
static Future<Tor> init({bool enabled = true}) async {
|
||||||
var singleton = Tor._instance;
|
final singleton = Tor._instance;
|
||||||
singleton._enabled = enabled;
|
singleton._enabled = enabled;
|
||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
@@ -117,15 +119,15 @@ class Tor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<int> _getRandomUnusedPort({List<int> excluded = const []}) async {
|
Future<int> _getRandomUnusedPort({List<int> excluded = const []}) async {
|
||||||
var random = Random.secure();
|
final random = Random.secure();
|
||||||
int potentialPort = 0;
|
int potentialPort = 0;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
while (potentialPort <= 0 || excluded.contains(potentialPort)) {
|
while (potentialPort <= 0 || excluded.contains(potentialPort)) {
|
||||||
potentialPort = random.nextInt(65535);
|
potentialPort = random.nextInt(65535);
|
||||||
try {
|
try {
|
||||||
var socket = await ServerSocket.bind("0.0.0.0", potentialPort);
|
final socket = await ServerSocket.bind("0.0.0.0", potentialPort);
|
||||||
socket.close();
|
await socket.close();
|
||||||
return potentialPort;
|
return potentialPort;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
continue retry;
|
continue retry;
|
||||||
@@ -142,33 +144,39 @@ class Tor {
|
|||||||
/// Throws an exception if the Tor service fails to start.
|
/// Throws an exception if the Tor service fails to start.
|
||||||
///
|
///
|
||||||
/// Returns a Future that completes when the Tor service has started.
|
/// Returns a Future that completes when the Tor service has started.
|
||||||
Future<void> start(
|
Future<void> start({
|
||||||
{int? obfs4Port, int? snowflakePort, String? bridgeLines}) async {
|
int? obfs4Port,
|
||||||
|
int? snowflakePort,
|
||||||
|
String? bridgeLines,
|
||||||
|
}) async {
|
||||||
broadcastState();
|
broadcastState();
|
||||||
|
|
||||||
// Set the state and cache directories.
|
// Set the state and cache directories.
|
||||||
final Directory appSupportDir = await getApplicationSupportDirectory();
|
final Directory appSupportDir = await getApplicationSupportDirectory();
|
||||||
final stateDir =
|
final stateDir = await Directory(
|
||||||
await Directory('${appSupportDir.path}/tor_state').create();
|
'${appSupportDir.path}/tor_state',
|
||||||
final cacheDir =
|
).create();
|
||||||
await Directory('${appSupportDir.path}/tor_cache').create();
|
final cacheDir = await Directory(
|
||||||
|
'${appSupportDir.path}/tor_cache',
|
||||||
|
).create();
|
||||||
|
|
||||||
// Generate a random port.
|
// Generate a random port.
|
||||||
int newPort = await _getRandomUnusedPort();
|
final newPort = await _getRandomUnusedPort();
|
||||||
|
|
||||||
// Start the Tor service in an isolate.
|
// Start the Tor service in an isolate.
|
||||||
final tor = await Isolate.run(() async {
|
final tor = await Isolate.run(() {
|
||||||
// Load the Tor library.
|
// Load the Tor library.
|
||||||
var lib = rust.NativeLibrary(load(libName));
|
final lib = rust.NativeLibrary(load(libName));
|
||||||
|
|
||||||
// Start the Tor service.
|
// Start the Tor service.
|
||||||
final tor = lib.tor_start(
|
final tor = lib.tor_start(
|
||||||
newPort,
|
newPort,
|
||||||
stateDir.path.toNativeUtf8() as Pointer<Char>,
|
stateDir.path.toNativeUtf8() as Pointer<Char>,
|
||||||
cacheDir.path.toNativeUtf8() as Pointer<Char>,
|
cacheDir.path.toNativeUtf8() as Pointer<Char>,
|
||||||
obfs4Port ?? -1,
|
obfs4Port ?? -1,
|
||||||
snowflakePort ?? -1,
|
snowflakePort ?? -1,
|
||||||
bridgeLines?.toNativeUtf8() as Pointer<Char>? ?? nullptr);
|
bridgeLines?.toNativeUtf8() as Pointer<Char>? ?? nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
// Throw an exception if the Tor service fails to start.
|
// Throw an exception if the Tor service fails to start.
|
||||||
if (tor.client == nullptr) {
|
if (tor.client == nullptr) {
|
||||||
@@ -190,24 +198,30 @@ class Tor {
|
|||||||
broadcastState();
|
broadcastState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> reconfigure(
|
Future<void> reconfigure({
|
||||||
{int? obfs4Port, int? snowflakePort, String? bridgeLines}) async {
|
int? obfs4Port,
|
||||||
|
int? snowflakePort,
|
||||||
|
String? bridgeLines,
|
||||||
|
}) async {
|
||||||
final lib = rust.NativeLibrary(_lib);
|
final lib = rust.NativeLibrary(_lib);
|
||||||
|
|
||||||
// Set the state and cache directories.
|
// Set the state and cache directories.
|
||||||
final Directory appSupportDir = await getApplicationSupportDirectory();
|
final Directory appSupportDir = await getApplicationSupportDirectory();
|
||||||
final stateDir =
|
final stateDir = await Directory(
|
||||||
await Directory('${appSupportDir.path}/tor_state').create();
|
'${appSupportDir.path}/tor_state',
|
||||||
final cacheDir =
|
).create();
|
||||||
await Directory('${appSupportDir.path}/tor_cache').create();
|
final cacheDir = await Directory(
|
||||||
|
'${appSupportDir.path}/tor_cache',
|
||||||
|
).create();
|
||||||
|
|
||||||
final reconfigured = lib.tor_reconfigure(
|
final reconfigured = lib.tor_reconfigure(
|
||||||
_clientPtr,
|
_clientPtr,
|
||||||
stateDir.path.toNativeUtf8() as Pointer<Char>,
|
stateDir.path.toNativeUtf8() as Pointer<Char>,
|
||||||
cacheDir.path.toNativeUtf8() as Pointer<Char>,
|
cacheDir.path.toNativeUtf8() as Pointer<Char>,
|
||||||
obfs4Port ?? -1,
|
obfs4Port ?? -1,
|
||||||
snowflakePort ?? -1,
|
snowflakePort ?? -1,
|
||||||
bridgeLines?.toNativeUtf8() as Pointer<Char>? ?? nullptr);
|
bridgeLines?.toNativeUtf8() as Pointer<Char>? ?? nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
if (!reconfigured) {
|
if (!reconfigured) {
|
||||||
throwRustException(lib);
|
throwRustException(lib);
|
||||||
@@ -270,25 +284,29 @@ class Tor {
|
|||||||
|
|
||||||
Future<void> isReady() async {
|
Future<void> isReady() async {
|
||||||
return await Future.doWhile(
|
return await Future.doWhile(
|
||||||
() => Future.delayed(const Duration(seconds: 1)).then((_) {
|
() => Future.delayed(const Duration(seconds: 1)).then((_) {
|
||||||
// We are waiting and making absolutely no request unless:
|
// We are waiting and making absolutely no request unless:
|
||||||
// Tor is disabled
|
// Tor is disabled
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...or Tor circuit is established
|
// ...or Tor circuit is established
|
||||||
if (bootstrapped) {
|
if (bootstrapped) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This way we avoid making clearnet req's while Tor is initialising
|
// This way we avoid making clearnet req's while Tor is initialising
|
||||||
return true;
|
return true;
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static throwRustException(rust.NativeLibrary lib) {
|
static void throwRustException(rust.NativeLibrary lib) {
|
||||||
String rustError = lib.tor_last_error_message().cast<Utf8>().toDartString();
|
final String rustError = lib
|
||||||
|
.tor_last_error_message()
|
||||||
|
.cast<Utf8>()
|
||||||
|
.toDartString();
|
||||||
|
|
||||||
throw _getRustException(rustError);
|
throw _getRustException(rustError);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,17 +20,17 @@ environment:
|
|||||||
flutter: '>=3.3.0'
|
flutter: '>=3.3.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
ffi: ^2.0.1
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
path_provider: ^2.1.4
|
path_provider: ^2.1.4
|
||||||
ffi: ^2.0.1
|
|
||||||
plugin_platform_interface: ^2.0.2
|
plugin_platform_interface: ^2.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
ffigen: ^19.1.0
|
ffigen: ^19.1.0
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^6.0.0
|
lint: ^2.8.0
|
||||||
|
|
||||||
ffigen:
|
ffigen:
|
||||||
output: 'lib/generated_bindings.dart'
|
output: 'lib/generated_bindings.dart'
|
||||||
|
|||||||
Reference in New Issue
Block a user