use anyhow::Result; use arti_client::{TorClient, TorClientConfig}; use tokio_crate as tokio; use futures::io::{AsyncReadExt, AsyncWriteExt}; #[tokio::main] async fn main() -> Result<()> { // Arti uses the `tracing` crate for logging. Install a handler for this, to print Arti's logs. tracing_subscriber::fmt::init(); // The client config includes things like where to store persistent Tor network state. // The "sane defaults" provided are the same as the Arti standalone application, and save data // to a conventional place depending on operating system (for example, ~/.local/share/arti // on Linux platforms) let config = TorClientConfig::sane_defaults()?; // Arti needs an async runtime handle to spawn async tasks. let rt = tor_rtcompat::tokio::current_runtime()?; eprintln!("connecting to Tor..."); // We now let the Arti client start and bootstrap a connection to the network. // (This takes a while to gather the necessary consensus state, etc.) let tor_client = TorClient::bootstrap(rt, config).await?; eprintln!("connecting to example.com..."); let mut stream = tor_client.connect(("example.com", 80), None).await?; eprintln!("sending request..."); stream .write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n") .await?; stream.flush().await?; eprintln!("reading response..."); let mut buf = Vec::new(); stream.read_to_end(&mut buf).await?; println!("{}", String::from_utf8_lossy(&buf)); Ok(()) }