Hey Guys,
Rust noob trying to learn by building my first project: Tor on mobile.
I'm trying to create a mobile library for developers to easily integrate Tor into their projects.
I'm standing on the shoulder of giants by combining to great crates:
Libtor: Tor Daemon
https://crates.io/crates/libtor
Torut: Control the Tor Daemon
https://crates.io/crates/torut
What i'm trying to do is use libtor to spawn the Tor Daemon and then use Torut to control and shut it down when an app goes in the background and then spin it back up when foregrounded via a C and JNI FFI.
I've manged to get my POC to compile on iOS/Android etc, but now I'm trying to make it into a Pacakge, I'm trying to do the following:
pub struct TorService {
socks_port: u16,
control_port: String,
_handle: Option<JoinHandle<Result<u8, libtor::Error>>>, // Stores the thread handle returned by libtor for the daemon thread
_ctl: RefCell<Option<G>>, // Stores the authenticated daemon control connection returned by Torut
}
I setup G to have the following type:
type G = AuthenticatedConn<
TcpStream,
Fn(AsyncEvent<'static>) -> Future<Output = Result<(), ConnError>>,
>;
based on Torut's authenticated connection's definition, which also requires an Async callback to be injected :
Github link:
teawithsand/torut/blob/master/src/control/conn/authenticated_conn.rs#L54-L61
(sorry for partial url, only allowed 2 links per post as a noob)
impl<S, H, F> AuthenticatedConn<S, H>
where
S: AsyncRead + Unpin,
// there fns make use of event handler so it's needed
H: Fn(AsyncEvent<'static>) -> F,
F: Future<Output=Result<(), ConnError>>,
{
I define my Async handler as
fn handler(
event: AsyncEvent<'static>,
) -> Pin<Box<dyn Future<Output = Result<(), ConnError>> + '_>> {
Box::pin(async move { Ok(()) })
}
My issues all lie in trying to store the AuthenticatedConn
in TorService._handle
:
let mut ac = self.get_control_auth_conn(Some(Box::new(handler))).await;
*self._ctl.borrow_mut() = Some(ac);
no matter what typing I try, the compiler just hates me, things i've tried so far:
type G = AuthenticatedConn<
TcpStream,
fn(AsyncEvent<'static>) -> Pin<Box<dyn Future<Output = Result<(), ConnError>> + '_>>>,
>;
i get
error[E0308]: mismatched types
--> tor/src/lib.rs:123:44
|
123 | *self._ctl.borrow_mut() = Some(ac);
| ^^ expected fn pointer, found fn item
|
= note: expected struct `torut::control::AuthenticatedConn<_, fn(torut::control::AsyncEvent<'_>) -> std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>>>>>`
found struct `torut::control::AuthenticatedConn<_, fn(torut::control::AsyncEvent<'static>) -> std::pin::Pin<std::boxed::Box<(dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>> + 'static)>> {handler}>`
If i try:
type G = AuthenticatedConn<
TcpStream,
Box<dyn Fn(AsyncEvent<'static>) -> Pin<Box<dyn Future<Output = Result<(), ConnError>> + '_>>>,
>;
i get
error[E0308]: mismatched types
--> tor/src/lib.rs:124:44
|
124 | *self._ctl.borrow_mut() = Some(ac);
| ^^ expected trait object `dyn std::ops::Fn`, found fn item
|
= note: expected struct `torut::control::AuthenticatedConn<_, std::boxed::Box<dyn std::ops::Fn(torut::control::AsyncEvent<'static>) -> std::pin::Pin<std::boxed::Box<(dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>> + 'static)>>>>`
found struct `torut::control::AuthenticatedConn<_, std::boxed::Box<fn(torut::control::AsyncEvent<'static>) -> std::pin::Pin<std::boxed::Box<(dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>> + 'static)>> {handler}>>`
finally if i try:
type G = AuthenticatedConn<
TcpStream,
Fn(AsyncEvent<'static>) -> Future<Output = Result<(), ConnError>>,
>;
i get
error[E0277]: the size for values of type `(dyn std::ops::Fn(torut::control::AsyncEvent<'static>) -> (dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>> + 'static) + 'static)` cannot be known at compilation time
--> tor/src/lib.rs:41:11
|
41 | _ctl: RefCell<Option<G>>,
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
::: <snip>/.cargo/registry/src/github.com-1ecc6299db9ec823/torut-0.1.6/src/control/conn/authenticated_conn.rs:33:33
|
33 | pub struct AuthenticatedConn<S, H> {
| - required by this bound in `torut::control::AuthenticatedConn`
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn(torut::control::AsyncEvent<'static>) -> (dyn futures::Future<Output = std::result::Result<(), torut::control::ConnError>> + 'static) + 'static)`
I've been at this for 5 days now and i Just can't seem to get it working.
The reason i'm trying to store the control connection in the TorService is to be able to stop/start the Daemon on App foregrounding/back-grounding while keeping the FFI very basic.
I would really appreciate any guidance on what i'm doing wrong, or what i'm doing right but Rust thinks is wrong or maybe i'm just doing it all wrong. At this point i'm just looking to get an understanding on how one would approach/fix this issue in rust!
Apologies for the long post and if i have missed any important information, kindly do let me know, thank you so much for reading so far!