Expand description
High-level controller API for Tor control protocol interaction.
This module provides the primary interface for interacting with Tor’s control
protocol. The Controller type wraps a ControlSocket
and provides high-level methods for common operations like authentication,
circuit management, stream handling, and event subscription.
§Overview
The Controller is the main entry point for most stem-rs users. It handles:
- Connection Management: Connect via TCP port or Unix domain socket
- Authentication: Automatic method detection and credential handling
- Information Queries: GETINFO commands for version, PID, circuit status, etc.
- Configuration: GETCONF/SETCONF/RESETCONF for Tor configuration
- Circuit Control: Create, extend, and close circuits
- Stream Control: Attach and close streams
- Event Handling: Subscribe to and receive asynchronous events
- Hidden Services: Create and manage ephemeral hidden services
- Address Mapping: Map addresses for custom routing
§Conceptual Role
The Controller sits between your application and Tor’s control socket:
┌─────────────┐ ┌────────────┐ ┌─────────────┐
│ Application │ ──▶│ Controller │ ──▶│ Tor Process │
└─────────────┘ └────────────┘ └─────────────┘
│
Handles:
• Protocol formatting
• Response parsing
• Event buffering
• Error handling§What This Module Does NOT Do
- Direct relay communication: Use
client::Relayfor ORPort connections - Descriptor parsing: Use the
descriptormodule - Exit policy evaluation: Use
ExitPolicy
§Thread Safety
Controller is Send but not Sync. The controller maintains internal
state (socket, event buffer) that requires exclusive access. For concurrent
access from multiple tasks, wrap in Arc<Mutex<Controller>>:
use std::sync::Arc;
use tokio::sync::Mutex;
use stem_rs::controller::Controller;
let controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
let shared = Arc::new(Mutex::new(controller));
// Clone Arc for each task
let c1 = shared.clone();
tokio::spawn(async move {
let mut ctrl = c1.lock().await;
// Use controller...
});§Example
Basic usage pattern:
use stem_rs::controller::Controller;
use stem_rs::Signal;
// Connect to Tor's control port
let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
// Authenticate (auto-detects method)
controller.authenticate(None).await?;
// Query information
let version = controller.get_version().await?;
println!("Connected to Tor {}", version);
// Get active circuits
let circuits = controller.get_circuits().await?;
for circuit in circuits {
println!("Circuit {}: {:?}", circuit.id, circuit.status);
}
// Request new identity
controller.signal(Signal::Newnym).await?;§Security Considerations
- Passwords are not stored after authentication
- Cookie files are read with minimal permissions
- SAFECOOKIE authentication uses secure random nonces
- Input is validated to prevent protocol injection attacks
§See Also
Structs§
- AddOnion
Response - Response from ADD_ONION command.
- Circuit
- Information about an active Tor circuit.
- Circuit
Id - A unique identifier for a Tor circuit.
- Controller
- A high-level interface for interacting with Tor’s control protocol.
- Relay
Info - Information about a relay in a circuit path.
- Stream
- Information about an active Tor stream.
- Stream
Id - A unique identifier for a Tor stream.