use hypertor::{Result, TorClient};
use std::time::{Duration, Instant};
async fn demonstrate_polling(client: &TorClient) -> Result<()> {
println!("🧅 Real-time Updates via Long Polling");
println!("--------------------------------------");
println!();
println!("Long polling pattern over Tor:");
println!();
println!(" 1. Client sends request to server");
println!(" 2. Server holds connection until data is available (or timeout)");
println!(" 3. Server responds with new data");
println!(" 4. Client immediately sends new request");
println!();
println!("📡 Demonstrating polling with httpbin.org via Tor...");
println!();
for i in 1..=3 {
let start = Instant::now();
let response = client
.get("https://httpbin.org/delay/1")? .send()
.await?;
let elapsed = start.elapsed();
if response.status().is_success() {
println!(
" 📥 Poll {}: Got response after {:.1}s",
i,
elapsed.as_secs_f64()
);
} else {
println!(" ⚠️ Poll {}: Status {}", i, response.status());
}
if i < 3 {
tokio::time::sleep(Duration::from_millis(500)).await;
}
}
println!();
println!(" ✅ Polling demonstration complete");
Ok(())
}
fn show_sse_pattern() {
println!();
println!("🧅 Server-Sent Events (SSE) Pattern");
println!("------------------------------------");
println!();
println!("SSE is ideal for server→client streaming over Tor:");
println!();
println!(
r#"
Example SSE Server (using OnionApp):
use hypertor::{{OnionApp, get, ServeRequest}};
use hypertor::streaming::StreamingResponseBuilder;
let app = OnionApp::builder()
.route("/events", get(|_req: ServeRequest| async {{
StreamingResponseBuilder::new()
.content_type("text/event-stream")
.streaming(async_stream::stream! {{
loop {{
let data = get_next_event().await;
yield format!("data: {{}}\n\n", data);
}}
}})
.build()
}}))
.build();
Example SSE Client:
let response = client.get("http://xxx.onion/events")?.send().await?;
// Process events as they arrive
for line in response.text()?.lines() {{
if line.starts_with("data: ") {{
let event = &line[6..];
process_event(event);
}}
}}
"#
);
}
fn show_bidirectional_pattern() {
println!();
println!("🧅 Bidirectional Communication Pattern");
println!("--------------------------------------");
println!();
println!("Achieve WebSocket-like bidirectional communication:");
println!();
println!(
r#"
Pattern: Separate send/receive channels
async fn chat_client(client: &TorClient, onion: &str) -> Result<()> {{
// Spawn receiver task (long polling)
let receiver = tokio::spawn(async move {{
let mut last_id = 0;
loop {{
let resp = client
.get(&format!("http://{{}}/poll?after={{}}", onion, last_id))?
.send()
.await?;
let messages: Vec<Message> = resp.json()?;
for msg in messages {{
println!("Received: {{}}", msg.text);
last_id = last_id.max(msg.id);
}}
}}
}});
// Sender loop
loop {{
let message = get_user_input().await;
client
.post(&format!("http://{{}}/send", onion))?
.json(&message)
.send()
.await?;
}}
}}
"#
);
}
async fn demonstrate_websocket(client: &TorClient) -> Result<()> {
println!();
println!("🧅 True WebSocket over Tor");
println!("--------------------------");
println!();
println!("hypertor supports real WebSocket connections through Tor!");
println!();
println!("WebSocket connection pattern:");
println!();
println!(
r#"
use hypertor::{{TorClient, TorWebSocket, TorWebSocketBuilder}};
let client = TorClient::new().await?;
// Connect to a WebSocket server through Tor
let ws = TorWebSocketBuilder::new(&client)
.connect("wss://echo.websocket.events/")
.await?;
// Send a message
ws.send_text("Hello from Tor!").await?;
// Receive response
let response = ws.recv().await?;
println!("Received: {{}}", response);
// Close gracefully
ws.close().await?;
"#
);
println!();
println!("📡 Making HTTP request that would upgrade to WebSocket:");
let start = Instant::now();
let response = client.get("https://httpbin.org/get")?.send().await?;
println!(" Status: {}", response.status());
println!(" Latency: {:.1}s", start.elapsed().as_secs_f64());
println!();
println!(" ✅ Connection through Tor successful");
println!(" 💡 For real WebSocket, use TorWebSocketBuilder::connect()");
Ok(())
}
async fn demonstrate_http_chat(client: &TorClient) -> Result<()> {
println!();
println!("🧅 Live Demo: HTTP Request/Response over Tor");
println!("---------------------------------------------");
println!();
println!("📡 Sending message to httpbin.org via Tor...");
let message = serde_json::json!({
"user": "anonymous",
"text": "Hello from Tor!",
"timestamp": std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0)
});
let start = Instant::now();
let response = client
.post("https://httpbin.org/post")?
.json(&message)
.send()
.await?;
let latency = start.elapsed();
if response.status().is_success() {
let text = response.text()?;
let data: serde_json::Value = serde_json::from_str(&text).unwrap_or_default();
println!(" ✅ Message sent successfully");
if let Some(origin) = data.get("origin").and_then(|v| v.as_str()) {
println!(" 📍 Via Tor exit: {}", origin);
}
if let Some(json) = data.get("json") {
println!(" 📦 Server received: {}", json);
}
println!(" ⏱️ Latency: {:.1}s", latency.as_secs_f64());
} else {
println!(" ❌ Error: {}", response.status());
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
println!("🧅 hypertor - Real-time Communication Patterns");
println!("===============================================");
println!();
println!("This example shows how to achieve real-time communication over Tor.");
println!();
println!("Creating Tor client...");
let client = TorClient::new().await?;
println!("✅ Connected to Tor network");
println!();
match demonstrate_polling(&client).await {
Ok(_) => {}
Err(e) => println!(" ⚠️ Polling demo error: {}", e),
}
show_sse_pattern();
show_bidirectional_pattern();
match demonstrate_websocket(&client).await {
Ok(_) => {}
Err(e) => println!(" ⚠️ WebSocket demo error: {}", e),
}
match demonstrate_http_chat(&client).await {
Ok(_) => {}
Err(e) => println!(" ⚠️ HTTP chat demo error: {}", e),
}
println!();
println!("================================================");
println!("✅ Real-time patterns demonstration completed!");
println!();
println!("Key takeaways:");
println!(" • Long polling works well for real-time over Tor");
println!(" • SSE provides server→client streaming");
println!(" • Bidirectional achieved with send/receive channels");
println!(" • TorWebSocket provides true WebSocket support");
Ok(())
}