Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ git subtree pull --prefix cargokit https://github.com/irondash/cargokit.git main

## Development

To (re)generate Dart bindings run `just generate`
To (re)generate C bindings for Rust, `cargo build` the crate in `/rust`. For
Dart bindings, run `dart run ffigen --config ffigen.yaml`

## Example app

Expand Down
28 changes: 28 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class _MyAppState extends State<Home> {
// Flag to track if tor has started.
bool torStarted = false;

String? exitNodeAddress;

// Set the default text for the host input field.
final hostController = TextEditingController(text: 'https://icanhazip.com/');
// https://check.torproject.org is another good option.
Expand Down Expand Up @@ -83,6 +85,24 @@ class _MyAppState extends State<Home> {
});

print('Done awaiting; tor should be running');

// Fetch the exit node address.
try {
String? address = await Tor.instance.getExitNode();
// getExitNode above should return like: [1.2.3.4:5 ed25519:Q6+... $7...]
setState(() {
if (address != null && address!.contains(":")) {
// Strip just the IP out of the above.
address = address?.split(":")[0].substring(1);
}
exitNodeAddress = address;
});
} catch (e) {
print('Error getting exit node address: $e');
setState(() {
exitNodeAddress = 'Error retrieving exit node address';
});
}
}

@override
Expand Down Expand Up @@ -150,6 +170,14 @@ class _MyAppState extends State<Home> {
},
child: const Text("Stop"),
),
// Display the exit node address.
if (exitNodeAddress != null) ...[
spacerSmall,
Text(
'Exit Node: $exitNodeAddress',
style: const TextStyle(fontSize: 16),
),
],
],
),
Row(
Expand Down
22 changes: 11 additions & 11 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.18.0"
version: "1.19.0"
cupertino_icons:
dependency: "direct main"
description:
Expand Down Expand Up @@ -87,18 +87,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.7"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.8"
leak_tracker_testing:
dependency: transitive
description:
Expand Down Expand Up @@ -215,7 +215,7 @@ packages:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
version: "0.0.0"
socks5_proxy:
dependency: "direct main"
description:
Expand Down Expand Up @@ -252,10 +252,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.3.0"
term_glyph:
dependency: transitive
description:
Expand All @@ -268,10 +268,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.3"
tor:
dependency: "direct main"
description:
Expand Down
2 changes: 1 addition & 1 deletion ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: |
Bindings for `tor.h`.

Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
output: 'lib/tor_bindings_generated.dart'
output: 'lib/generated_bindings.dart'
headers:
entry-points:
- 'rust/target/tor.h'
Expand Down
179 changes: 41 additions & 138 deletions lib/generated_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@
//
// SPDX-License-Identifier: MIT

// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names

// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
import 'dart:ffi' as ffi;

/// Bindings for `tor.h`.
///
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
///
class NativeLibrary {
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
Expand Down Expand Up @@ -87,6 +95,39 @@ class NativeLibrary {
late final _tor_proxy_stop =
_tor_proxy_stopPtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();

/// Get the exit node's identity (e.g., nickname or ID) for the given client.
ffi.Pointer<ffi.Char> tor_get_exit_node(
ffi.Pointer<ffi.Void> client,
) {
return _tor_get_exit_node(
client,
);
}

late final _tor_get_exit_nodePtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<ffi.Char> Function(
ffi.Pointer<ffi.Void>)>>('tor_get_exit_node');
late final _tor_get_exit_node = _tor_get_exit_nodePtr
.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<ffi.Void>)>();

/// Free a C string allocated by this library.
///
/// Used to free memory allocated by functions like `tor_get_exit_node`.
void tor_free_string(
ffi.Pointer<ffi.Char> s,
) {
return _tor_free_string(
s,
);
}

late final _tor_free_stringPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
'tor_free_string');
late final _tor_free_string =
_tor_free_stringPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();

void tor_hello() {
return _tor_hello();
}
Expand Down Expand Up @@ -135,141 +176,3 @@ final class Tor extends ffi.Struct {

external ffi.Pointer<ffi.Void> proxy;
}

const int true1 = 1;

const int false1 = 0;

const int INT8_MIN = -128;

const int INT16_MIN = -32768;

const int INT32_MIN = -2147483648;

const int INT64_MIN = -9223372036854775808;

const int INT8_MAX = 127;

const int INT16_MAX = 32767;

const int INT32_MAX = 2147483647;

const int INT64_MAX = 9223372036854775807;

const int UINT8_MAX = 255;

const int UINT16_MAX = 65535;

const int UINT32_MAX = 4294967295;

const int UINT64_MAX = -1;

const int INT_LEAST8_MIN = -128;

const int INT_LEAST16_MIN = -32768;

const int INT_LEAST32_MIN = -2147483648;

const int INT_LEAST64_MIN = -9223372036854775808;

const int INT_LEAST8_MAX = 127;

const int INT_LEAST16_MAX = 32767;

const int INT_LEAST32_MAX = 2147483647;

const int INT_LEAST64_MAX = 9223372036854775807;

const int UINT_LEAST8_MAX = 255;

const int UINT_LEAST16_MAX = 65535;

const int UINT_LEAST32_MAX = 4294967295;

const int UINT_LEAST64_MAX = -1;

const int INT_FAST8_MIN = -128;

const int INT_FAST16_MIN = -9223372036854775808;

const int INT_FAST32_MIN = -9223372036854775808;

const int INT_FAST64_MIN = -9223372036854775808;

const int INT_FAST8_MAX = 127;

const int INT_FAST16_MAX = 9223372036854775807;

const int INT_FAST32_MAX = 9223372036854775807;

const int INT_FAST64_MAX = 9223372036854775807;

const int UINT_FAST8_MAX = 255;

const int UINT_FAST16_MAX = -1;

const int UINT_FAST32_MAX = -1;

const int UINT_FAST64_MAX = -1;

const int INTPTR_MIN = -9223372036854775808;

const int INTPTR_MAX = 9223372036854775807;

const int UINTPTR_MAX = -1;

const int INTMAX_MIN = -9223372036854775808;

const int INTMAX_MAX = 9223372036854775807;

const int UINTMAX_MAX = -1;

const int PTRDIFF_MIN = -9223372036854775808;

const int PTRDIFF_MAX = 9223372036854775807;

const int SIG_ATOMIC_MIN = -2147483648;

const int SIG_ATOMIC_MAX = 2147483647;

const int SIZE_MAX = -1;

const int WCHAR_MIN = -2147483648;

const int WCHAR_MAX = 2147483647;

const int WINT_MIN = 0;

const int WINT_MAX = 4294967295;

const int NULL = 0;

const int WNOHANG = 1;

const int WUNTRACED = 2;

const int WSTOPPED = 2;

const int WEXITED = 4;

const int WCONTINUED = 8;

const int WNOWAIT = 16777216;

const int RAND_MAX = 2147483647;

const int EXIT_FAILURE = 1;

const int EXIT_SUCCESS = 0;

const int LITTLE_ENDIAN = 1234;

const int BIG_ENDIAN = 4321;

const int PDP_ENDIAN = 3412;

const int BYTE_ORDER = 1234;

const int FD_SETSIZE = 1024;

const int NFDBITS = 64;
21 changes: 21 additions & 0 deletions lib/tor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,27 @@ class Tor {
}));
}

/// Gets the current exit node.
Future<String?> getExitNode() async {
if (_clientPtr == nullptr || !started || !bootstrapped) {
throw ClientNotActive();
}

final lib = rust.NativeLibrary(_lib);
Pointer<Char> addressPtr = lib.tor_get_exit_node(_clientPtr);

if (addressPtr == nullptr) {
String rustError =
lib.tor_last_error_message().cast<Utf8>().toDartString();
throw Exception("Failed to get exit node: $rustError");
}

String address = addressPtr.cast<Utf8>().toDartString();
lib.tor_free_string(addressPtr);

return address;
}

static throwRustException(rust.NativeLibrary lib) {
String rustError = lib.tor_last_error_message().cast<Utf8>().toDartString();

Expand Down
Loading