Skip to content

Commit

Permalink
bind tor_get_exit_node to Dart and add example
Browse files Browse the repository at this point in the history
update ffigen.yaml to use correct filepath (correct as in matching the code instead of changing the code to match the yaml)
dart run ffigen --config ffigen.yaml
  • Loading branch information
sneurlax committed Oct 4, 2024
1 parent aedc52d commit eb784d5
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 145 deletions.
39 changes: 34 additions & 5 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
//
// SPDX-License-Identifier: MIT

// Example app deps, not necessarily needed for tor usage.
// Flutter dependencies not necessarily needed for tor usage:
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
// Imports needed for tor usage:
import 'package:socks5_proxy/socks_client.dart'; // Just for example; can use any socks5 proxy package, pick your favorite.
import 'package:tor/tor.dart';
import 'package:tor/socks_socket.dart'; // For socket connections
// Example application dependencies you can replace with any that works for you:
import 'package:socks5_proxy/socks_client.dart';
import 'package:tor/socks_socket.dart';
// The only real import needed for basic usage:
import 'package:tor/tor.dart'; // This would go at the top, but dart autoformatter doesn't like it there.

void main() {
runApp(const MyApp());
Expand Down Expand Up @@ -44,6 +45,8 @@ class _MyAppState extends State<Home> {
final hostController = TextEditingController(text: 'https://icanhazip.com/');
// https://check.torproject.org is another good option.

String? exitNodeAddress;

Future<void> startTor() async {
await Tor.init();

Expand All @@ -56,6 +59,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 @@ -123,6 +144,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
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.7"
version: "0.0.8"
vector_math:
dependency: transitive
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

0 comments on commit eb784d5

Please sign in to comment.