#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
use anyhow::Result;
use arti_client::{TorClient, TorClientConfig};
use tokio_crate as tokio;
use futures::io::{AsyncReadExt, AsyncWriteExt};
use once_cell::sync::OnceCell;
use tor_rtcompat::PreferredRuntime;
static TOR_CLIENT: OnceCell<TorClient<PreferredRuntime>> = OnceCell::new();
pub fn get_tor_client() -> Result<TorClient<PreferredRuntime>> {
let client = TOR_CLIENT.get_or_try_init(|| -> Result<TorClient<_>> {
let config = TorClientConfig::default();
eprintln!("creating unbootstrapped Tor client");
Ok(TorClient::builder()
.config(config)
.create_unbootstrapped()?)
})?;
Ok(client.clone())
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
eprintln!("getting shared Tor client...");
let tor_client = get_tor_client()?;
eprintln!("connecting to example.com...");
let mut stream = tor_client.connect(("example.com", 80)).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(())
}