cake_wallet/lib/utils/proxy_wrapper.dart

221 lines
5.5 KiB
Dart
Raw Normal View History

2023-12-07 16:44:07 +00:00
import 'dart:io';
2024-01-08 17:33:04 +00:00
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/view_model/settings/tor_connection.dart';
2024-01-30 01:34:48 +00:00
import 'package:cake_wallet/view_model/settings/tor_view_model.dart';
2023-12-07 16:44:07 +00:00
import 'package:socks5_proxy/socks.dart';
import 'package:tor/tor.dart';
2024-01-12 19:53:19 +00:00
// this is the only way to ensure we're making a non-tor connection:
class NullOverrides extends HttpOverrides {
NullOverrides();
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context);
}
}
2023-12-07 16:44:07 +00:00
class ProxyWrapper {
2024-01-08 23:18:13 +00:00
ProxyWrapper({
2024-01-18 17:16:54 +00:00
this.settingsStore,
2024-01-30 01:34:48 +00:00
this.torViewModel,
2024-01-08 23:18:13 +00:00
});
2024-01-18 17:16:54 +00:00
SettingsStore? settingsStore;
2024-01-30 01:34:48 +00:00
TorViewModel? torViewModel;
2023-12-07 16:44:07 +00:00
2024-01-08 17:33:04 +00:00
HttpClient? _torClient;
2023-12-07 16:44:07 +00:00
2024-01-27 02:02:10 +00:00
int getPort() {
TorConnectionMode mode = settingsStore?.torConnectionMode ?? TorConnectionMode.disabled;
if (mode == TorConnectionMode.disabled) {
return -1;
}
2024-01-30 01:34:48 +00:00
return torViewModel?.torInstance.port ?? -1;
2024-01-27 02:02:10 +00:00
}
2024-01-08 17:33:04 +00:00
bool started = false;
2023-12-12 20:29:06 +00:00
Future<HttpClient> getProxyHttpClient({int? portOverride}) async {
2024-01-30 01:34:48 +00:00
if (portOverride == -1 || portOverride == null) {
portOverride = torViewModel?.torInstance.port ?? -1;
}
2024-01-18 17:16:54 +00:00
2023-12-07 16:44:07 +00:00
if (!started) {
started = true;
2024-01-08 17:33:04 +00:00
_torClient = HttpClient();
2023-12-07 16:44:07 +00:00
// Assign connection factory.
2024-01-08 17:33:04 +00:00
SocksTCPClient.assignToHttpClient(_torClient!, [
2023-12-07 16:44:07 +00:00
ProxySettings(
InternetAddress.loopbackIPv4,
2024-01-18 17:16:54 +00:00
portOverride,
2023-12-07 16:44:07 +00:00
password: null,
),
]);
}
2024-01-08 17:33:04 +00:00
return _torClient!;
}
2024-01-12 19:53:19 +00:00
Future<HttpClientResponse> makeGet({
required HttpClient client,
required Uri uri,
required Map<String, String>? headers,
}) async {
final request = await client.getUrl(uri);
if (headers != null) {
headers.forEach((key, value) {
request.headers.add(key, value);
});
}
return await request.close();
}
Future<HttpClientResponse> makePost({
required HttpClient client,
required Uri uri,
required Map<String, String>? headers,
}) async {
final request = await client.postUrl(uri);
if (headers != null) {
headers.forEach((key, value) {
request.headers.add(key, value);
});
}
return await request.close();
}
Future<HttpClientResponse> get({
Map<String, String>? headers,
int? portOverride,
2024-01-18 17:16:54 +00:00
TorConnectionMode? torConnectionMode,
Uri? clearnetUri,
2024-01-12 19:53:19 +00:00
Uri? onionUri,
}) async {
2024-01-12 19:53:19 +00:00
HttpClient? torClient;
late bool torEnabled;
2024-01-18 17:16:54 +00:00
torConnectionMode ??= settingsStore?.torConnectionMode ?? TorConnectionMode.disabled;
2024-01-23 18:36:46 +00:00
if (torConnectionMode == TorConnectionMode.torOnly ||
2024-01-18 17:16:54 +00:00
torConnectionMode == TorConnectionMode.enabled) {
torEnabled = true;
2024-01-08 17:33:04 +00:00
} else {
torEnabled = false;
2024-01-08 17:33:04 +00:00
}
2024-01-12 19:53:19 +00:00
// if tor is enabled, try to connect to the onion url first:
if (torEnabled) {
2024-01-18 17:16:54 +00:00
try {
torClient = await getProxyHttpClient(portOverride: portOverride);
} catch (_) {}
2024-01-12 19:53:19 +00:00
if (onionUri != null) {
try {
return await makeGet(
2024-01-12 19:53:19 +00:00
client: torClient!,
uri: onionUri,
headers: headers,
);
} catch (_) {}
}
2024-01-08 17:33:04 +00:00
2024-01-23 18:36:46 +00:00
if (clearnetUri != null) {
2024-01-12 19:53:19 +00:00
try {
return await makeGet(
2024-01-12 19:53:19 +00:00
client: torClient!,
uri: clearnetUri,
headers: headers,
);
} catch (_) {}
2024-01-08 17:33:04 +00:00
}
2024-01-12 19:53:19 +00:00
}
2024-01-23 18:36:46 +00:00
if (clearnetUri != null && torConnectionMode != TorConnectionMode.torOnly) {
2024-01-12 19:53:19 +00:00
try {
return HttpOverrides.runZoned(
() async {
return await makeGet(
2024-01-12 19:53:19 +00:00
client: HttpClient(),
uri: clearnetUri,
headers: headers,
);
},
createHttpClient: NullOverrides().createHttpClient,
);
} catch (_) {
// we weren't able to get a response:
rethrow;
2024-01-08 17:33:04 +00:00
}
}
2024-01-12 19:53:19 +00:00
throw Exception("Unable to connect to server");
2024-01-08 17:33:04 +00:00
}
2024-01-12 19:53:19 +00:00
Future<HttpClientResponse> post({
Map<String, String>? headers,
int? portOverride,
2024-01-18 17:16:54 +00:00
TorConnectionMode? torConnectionMode,
Uri? clearnetUri,
2024-01-12 19:53:19 +00:00
Uri? onionUri,
}) async {
2024-01-12 19:53:19 +00:00
HttpClient? torClient;
late bool torEnabled;
2024-01-18 17:16:54 +00:00
torConnectionMode ??= settingsStore?.torConnectionMode ?? TorConnectionMode.disabled;
2024-01-23 18:36:46 +00:00
if (torConnectionMode == TorConnectionMode.torOnly ||
2024-01-18 17:16:54 +00:00
torConnectionMode == TorConnectionMode.enabled) {
torEnabled = true;
2024-01-08 17:33:04 +00:00
} else {
torEnabled = false;
2024-01-08 17:33:04 +00:00
}
2024-01-12 19:53:19 +00:00
// if tor is enabled, try to connect to the onion url first:
if (torEnabled) {
2024-01-18 17:16:54 +00:00
try {
torClient = await getProxyHttpClient(portOverride: portOverride);
} catch (_) {}
2024-01-12 19:53:19 +00:00
if (onionUri != null) {
try {
return await makePost(
2024-01-12 19:53:19 +00:00
client: torClient!,
uri: onionUri,
headers: headers,
);
} catch (_) {}
}
2024-01-08 17:33:04 +00:00
2024-01-23 18:36:46 +00:00
if (clearnetUri != null) {
2024-01-12 19:53:19 +00:00
try {
return await makePost(
2024-01-12 19:53:19 +00:00
client: torClient!,
uri: clearnetUri,
headers: headers,
);
} catch (_) {}
2024-01-08 17:33:04 +00:00
}
2024-01-12 19:53:19 +00:00
}
2024-01-23 18:36:46 +00:00
if (clearnetUri != null && torConnectionMode != TorConnectionMode.torOnly) {
2024-01-12 19:53:19 +00:00
try {
return HttpOverrides.runZoned(
() async {
return await makePost(
2024-01-12 19:53:19 +00:00
client: HttpClient(),
uri: clearnetUri,
headers: headers,
);
},
createHttpClient: NullOverrides().createHttpClient,
);
} catch (_) {
// we weren't able to get a response:
rethrow;
2024-01-08 17:33:04 +00:00
}
}
2024-01-12 19:53:19 +00:00
throw Exception("Unable to connect to server");
2023-12-07 16:44:07 +00:00
}
}