Controller

Struct Controller 

Source
pub struct Controller { /* private fields */ }
Expand description

A high-level interface for interacting with Tor’s control protocol.

The Controller provides the primary API for controlling a Tor process. It wraps a ControlSocket and provides typed methods for common operations like authentication, circuit management, and event subscription.

§Conceptual Role

The Controller is the main entry point for most stem-rs users. It handles:

  • Protocol message formatting and parsing
  • Response validation and error handling
  • Asynchronous event buffering
  • Connection lifecycle management

§What This Type Does NOT Do

§Invariants

  • The underlying socket connection is valid while the Controller exists
  • After successful authentication, the controller is ready for commands
  • Events received during command execution are buffered for later retrieval

§Thread Safety

Controller is Send but not Sync. 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

use stem_rs::controller::Controller;
use stem_rs::Signal;

// Connect and authenticate
let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(Some("my_password")).await?;

// Query information
let version = controller.get_version().await?;
let circuits = controller.get_circuits().await?;

// Send signal
controller.signal(Signal::Newnym).await?;

§Security

  • Passwords are not stored after authentication
  • Cookie files are read with minimal permissions
  • SAFECOOKIE uses secure random nonces

§See Also

Implementations§

Source§

impl Controller

Source

pub async fn from_port(addr: SocketAddr) -> Result<Self, Error>

Creates a new Controller connected to a TCP control port.

Establishes a TCP connection to Tor’s control port at the specified address. The connection is unauthenticated; call authenticate before issuing commands.

§Arguments
  • addr - The socket address of Tor’s control port (e.g., 127.0.0.1:9051)
§Errors

Returns Error::Socket if:

  • The connection is refused (Tor not running or port incorrect)
  • Network is unreachable
  • Connection times out
§Example
use stem_rs::controller::Controller;

// Connect to default control port
let controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;

// Connect to custom port
let controller = Controller::from_port("127.0.0.1:9151".parse()?).await?;
§See Also
Source

pub async fn from_socket_file(path: &Path) -> Result<Self, Error>

Creates a new Controller connected to a Unix domain socket.

Establishes a connection to Tor’s control socket at the specified file path. This is typically more secure than TCP as it doesn’t expose the control interface to the network.

§Arguments
  • path - Path to Tor’s control socket file (e.g., /var/run/tor/control)
§Errors

Returns Error::Socket if:

  • The socket file doesn’t exist
  • Permission denied accessing the socket
  • The socket is not a valid Unix domain socket
§Example
use std::path::Path;
use stem_rs::controller::Controller;

// Connect to Tor's Unix control socket
let controller = Controller::from_socket_file(
    Path::new("/var/run/tor/control")
).await?;
§Platform Support

Unix domain sockets are only available on Unix-like systems (Linux, macOS, BSD). On Windows, use from_port instead.

§See Also
Source

pub async fn authenticate( &mut self, password: Option<&str>, ) -> Result<(), Error>

Authenticates with the Tor control interface.

Attempts authentication using the best available method. If password is provided, PASSWORD authentication is attempted. Otherwise, the method is auto-detected from PROTOCOLINFO.

§Authentication Methods

Methods are tried in this order:

  1. NONE - If control port is open (no auth required)
  2. SAFECOOKIE - Preferred for local connections
  3. COOKIE - Fallback for older Tor versions
  4. PASSWORD - If password is provided
§Arguments
  • password - Optional password for PASSWORD authentication
§Preconditions
  • Socket must be connected (not closed)
  • No prior successful authentication on this connection
§Postconditions
  • On success: Controller is authenticated and ready for commands
  • On failure: Connection state is undefined; reconnect recommended
§Errors

Returns Error::Authentication with specific reason:

§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;

// Auto-detect authentication method
controller.authenticate(None).await?;

// Or use password authentication
controller.authenticate(Some("my_password")).await?;
§Security
  • Passwords are cleared from memory after use
  • Cookie comparison uses constant-time algorithm
  • SAFECOOKIE nonces are cryptographically random
§See Also
  • auth: Authentication implementation details
  • AuthError: Authentication error types
Source

pub async fn get_info(&mut self, key: &str) -> Result<String, Error>

Queries Tor for information using the GETINFO command.

GETINFO retrieves various pieces of information from Tor. The available keys depend on Tor’s version and configuration.

§Arguments
  • key - The information key to query (e.g., “version”, “circuit-status”)
§Common Keys
KeyDescription
versionTor version string
process/pidTor process ID
circuit-statusActive circuit information
stream-statusActive stream information
addressBest guess at external IP address
fingerprintRelay fingerprint (if running as relay)
config-filePath to torrc file
§Errors

Returns Error::OperationFailed if:

  • The key is unrecognized
  • The information is not available
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Query Tor version
let version = controller.get_info("version").await?;
println!("Tor version: {}", version);

// Query external IP address
let address = controller.get_info("address").await?;
println!("External IP: {}", address);
§See Also
Source

pub async fn get_version(&mut self) -> Result<Version, Error>

Retrieves the Tor version as a parsed Version object.

This is a convenience wrapper around get_info("version") that parses the version string into a structured Version type.

§Errors

Returns an error if:

  • The GETINFO command fails
  • The version string cannot be parsed
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let version = controller.get_version().await?;
println!("Tor version: {}", version);

// Version supports comparison
// if version >= Version::parse("0.4.0.0")? { ... }
§See Also
  • Version: Version type with comparison support
Source

pub async fn get_pid(&mut self) -> Result<u32, Error>

Retrieves the process ID of the Tor process.

This is a convenience wrapper around get_info("process/pid") that parses the PID into a u32.

§Errors

Returns an error if:

  • The GETINFO command fails
  • The PID string cannot be parsed as a number
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let pid = controller.get_pid().await?;
println!("Tor PID: {}", pid);
Source

pub async fn get_conf(&mut self, key: &str) -> Result<Vec<String>, Error>

Retrieves the value(s) of a Tor configuration option.

Uses the GETCONF command to query Tor’s current configuration. Some options can have multiple values, so this returns a Vec<String>.

§Arguments
  • key - The configuration option name (e.g., “SocksPort”, “ExitPolicy”)
§Errors

Returns Error::OperationFailed if:

  • The configuration option is unrecognized
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Get SOCKS port configuration
let socks_ports = controller.get_conf("SocksPort").await?;
for port in socks_ports {
    println!("SOCKS port: {}", port);
}
§See Also
Source

pub async fn set_conf(&mut self, key: &str, value: &str) -> Result<(), Error>

Sets a Tor configuration option.

Uses the SETCONF command to change Tor’s configuration at runtime. The change takes effect immediately but is not persisted to the torrc file unless you call save_conf.

§Arguments
  • key - The configuration option name
  • value - The new value for the option
§Value Escaping

Values containing spaces or quotes are automatically escaped. You don’t need to handle quoting yourself.

§Errors

Returns Error::OperationFailed if:

  • The configuration option is unrecognized
  • The value is invalid for this option
  • The option cannot be changed at runtime
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Change bandwidth rate
controller.set_conf("BandwidthRate", "1 MB").await?;

// Enable a feature
controller.set_conf("SafeLogging", "1").await?;
§See Also
Source

pub async fn reset_conf(&mut self, key: &str) -> Result<(), Error>

Resets a Tor configuration option to its default value.

Uses the RESETCONF command to restore a configuration option to its default value as if it were not set in the torrc file.

§Arguments
  • key - The configuration option name to reset
§Errors

Returns Error::OperationFailed if:

  • The configuration option is unrecognized
  • The option cannot be reset at runtime
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Reset bandwidth rate to default
controller.reset_conf("BandwidthRate").await?;
§See Also
Source

pub async fn save_conf(&mut self, force: bool) -> Result<(), Error>

Saves the current configuration to the torrc file.

This persists any configuration changes made via set_conf to Tor’s configuration file, so they survive restarts.

§Arguments
  • force - If true, overwrite the configuration even if it includes a %include clause. This is ignored if Tor doesn’t support it.
§Errors

Returns Error::OperationFailed if:

  • Tor is unable to save the configuration file (e.g., permission denied)
  • The configuration file contains %include and force is false
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Change a configuration option
controller.set_conf("BandwidthRate", "1 MB").await?;

// Save to torrc
controller.save_conf(false).await?;

// Force save even with %include
controller.save_conf(true).await?;
§See Also
Source

pub async fn signal(&mut self, signal: Signal) -> Result<(), Error>

Sends a signal to the Tor process.

Signals control various aspects of Tor’s behavior, from requesting new circuits to initiating shutdown.

§Arguments
  • signal - The signal to send (see Signal)
§Available Signals
SignalDescription
ReloadReload configuration (SIGHUP)
ShutdownControlled shutdown
DumpWrite statistics to disk
DebugSwitch to debug logging
HaltImmediate shutdown (SIGTERM)
NewnymRequest new circuits
ClearDnsCacheClear DNS cache
HeartbeatTrigger heartbeat log
ActiveWake from dormant mode
DormantEnter dormant mode
§Errors

Returns Error::OperationFailed if:

  • The signal is not recognized
  • The signal cannot be sent (e.g., rate-limited NEWNYM)
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;
use stem_rs::Signal;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Request new identity (new circuits)
controller.signal(Signal::Newnym).await?;

// Reload configuration
controller.signal(Signal::Reload).await?;

// Clear DNS cache
controller.signal(Signal::ClearDnsCache).await?;
§Rate Limiting

The Newnym signal is rate-limited by Tor to prevent abuse. If called too frequently, Tor may delay the signal or return an error.

§See Also
Source

pub async fn get_circuits(&mut self) -> Result<Vec<Circuit>, Error>

Retrieves information about all active circuits.

Returns a list of all circuits currently known to Tor, including their status and path information.

§Errors

Returns an error if:

  • The GETINFO command fails
  • The circuit status cannot be parsed
§Example
use stem_rs::controller::Controller;
use stem_rs::CircStatus;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let circuits = controller.get_circuits().await?;
for circuit in circuits {
    if circuit.status == CircStatus::Built {
        println!("Circuit {} is ready with {} hops",
            circuit.id, circuit.path.len());
    }
}
§See Also
Source

pub async fn new_circuit( &mut self, path: Option<&[&str]>, ) -> Result<CircuitId, Error>

Creates a new circuit, optionally with a specified path.

If no path is specified, Tor will select relays automatically based on its path selection algorithm. If a path is provided, Tor will attempt to build a circuit through those specific relays.

§Arguments
  • path - Optional list of relay fingerprints or nicknames for the circuit path
§Path Specification

Relays can be specified by:

  • Fingerprint: $9695DFC35FFEB861329B9F1AB04C46397020CE31
  • Nickname: MyRelay
  • Fingerprint with nickname: $9695DFC35FFEB861329B9F1AB04C46397020CE31~MyRelay
§Errors

Returns Error::OperationFailed if:

  • A specified relay is unknown or unavailable
  • The path is invalid (e.g., too short)
  • Circuit creation fails
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Create circuit with automatic path selection
let circuit_id = controller.new_circuit(None).await?;
println!("Created circuit: {}", circuit_id);

// Create circuit with specific path
let path = &["$AAAA...", "$BBBB...", "$CCCC..."];
let circuit_id = controller.new_circuit(Some(path)).await?;
§See Also
Source

pub async fn extend_circuit( &mut self, id: &CircuitId, path: &[&str], ) -> Result<(), Error>

Extends an existing circuit by adding additional hops.

Adds one or more relays to an existing circuit. The circuit must be in a state that allows extension (typically BUILT or EXTENDED).

§Arguments
  • id - The circuit ID to extend
  • path - List of relay fingerprints or nicknames to add
§Errors

Returns Error::InvalidArguments if:

  • The path is empty

Returns Error::CircuitExtensionFailed if:

  • The circuit doesn’t exist
  • The circuit is in a state that doesn’t allow extension
  • A specified relay is unknown or unavailable
  • The extension fails for any other reason
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Create a circuit and extend it
let circuit_id = controller.new_circuit(None).await?;
controller.extend_circuit(&circuit_id, &["$DDDD..."]).await?;
§See Also
Source

pub async fn close_circuit(&mut self, id: &CircuitId) -> Result<(), Error>

Closes an existing circuit.

Tears down the specified circuit, closing all streams attached to it.

§Arguments
  • id - The circuit ID to close
§Errors

Returns Error::OperationFailed if:

  • The circuit doesn’t exist
  • The circuit is already closed
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Create and then close a circuit
let circuit_id = controller.new_circuit(None).await?;
controller.close_circuit(&circuit_id).await?;
§See Also
Source

pub async fn get_streams(&mut self) -> Result<Vec<Stream>, Error>

Retrieves information about all active streams.

Returns a list of all streams currently known to Tor, including their status, target, and circuit attachment.

§Errors

Returns an error if:

  • The GETINFO command fails
  • The stream status cannot be parsed
§Example
use stem_rs::controller::Controller;
use stem_rs::StreamStatus;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let streams = controller.get_streams().await?;
for stream in streams {
    println!("Stream {} -> {}:{} ({:?})",
        stream.id, stream.target_host, stream.target_port, stream.status);
}
§See Also
Source

pub async fn attach_stream( &mut self, stream_id: &StreamId, circuit_id: &CircuitId, ) -> Result<(), Error>

Attaches a stream to a specific circuit.

Manually attaches a stream to a circuit. This is typically used when you want to control which circuit a stream uses, rather than letting Tor choose automatically.

§Arguments
  • stream_id - The stream to attach
  • circuit_id - The circuit to attach the stream to
§Preconditions
  • The stream must be in a state that allows attachment (typically NEW)
  • The circuit must be BUILT
  • The circuit’s exit policy must allow the stream’s target
§Errors

Returns Error::OperationFailed if:

  • The stream doesn’t exist
  • The circuit doesn’t exist
  • The stream is not in an attachable state
  • The circuit cannot handle the stream’s target
§Example
use stem_rs::controller::{Controller, CircuitId, StreamId};

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Attach stream 1 to circuit 5
let stream_id = StreamId::new("1");
let circuit_id = CircuitId::new("5");
controller.attach_stream(&stream_id, &circuit_id).await?;
§See Also
Source

pub async fn close_stream( &mut self, id: &StreamId, reason: Option<u8>, ) -> Result<(), Error>

Closes an existing stream.

Terminates the specified stream with an optional reason code.

§Arguments
  • id - The stream ID to close
  • reason - Optional reason code (defaults to 1 = MISC if not specified)
§Reason Codes

Common reason codes include:

  • 1: MISC (miscellaneous)
  • 2: RESOLVEFAILED (DNS resolution failed)
  • 3: CONNECTREFUSED (connection refused)
  • 4: EXITPOLICY (exit policy violation)
  • 5: DESTROY (circuit destroyed)
  • 6: DONE (stream finished normally)
  • 7: TIMEOUT (connection timeout)
§Errors

Returns Error::OperationFailed if:

  • The stream doesn’t exist
  • The stream is already closed
  • Tor returns an error response
§Example
use stem_rs::controller::{Controller, StreamId};

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Close stream with default reason
let stream_id = StreamId::new("1");
controller.close_stream(&stream_id, None).await?;

// Close stream with specific reason (DONE)
controller.close_stream(&stream_id, Some(6)).await?;
§See Also
Source

pub async fn map_address( &mut self, from: &str, to: &str, ) -> Result<HashMap<String, String>, Error>

Maps one address to another for Tor connections.

Creates an address mapping so that connections to the from address are redirected to the to address. This is useful for creating virtual addresses or redirecting traffic.

§Arguments
  • from - The source address to map from
  • to - The destination address to map to
§Returns

Returns a HashMap containing the established mappings. The keys are the source addresses and values are the destination addresses.

§Errors

Returns Error::OperationFailed if:

  • The address format is invalid
  • The mapping cannot be created
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Map a hostname to a .onion address
let mappings = controller.map_address(
    "www.example.com",
    "exampleonion.onion"
).await?;

for (from, to) in mappings {
    println!("{} -> {}", from, to);
}
Source

pub async fn set_events(&mut self, events: &[EventType]) -> Result<(), Error>

Subscribes to asynchronous events from Tor.

Configures which event types Tor should send to this controller. Events are received via recv_event.

§Arguments
  • events - List of event types to subscribe to
§Event Types

Common event types include:

§Errors

Returns Error::OperationFailed if:

  • An event type is not recognized
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;
use stem_rs::EventType;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Subscribe to circuit and bandwidth events
controller.set_events(&[EventType::Circ, EventType::Bw]).await?;

// Receive events
loop {
    let event = controller.recv_event().await?;
    println!("Received event: {:?}", event);
}
§Clearing Subscriptions

To stop receiving events, call with an empty slice:

controller.set_events(&[]).await?; // Clear all subscriptions
§See Also
Source

pub async fn recv_event(&mut self) -> Result<ParsedEvent, Error>

Receives the next asynchronous event from Tor.

Blocks until an event is available. Events must first be subscribed to using set_events.

§Event Buffering

Events that arrive while waiting for command responses are automatically buffered and returned by subsequent calls to this method.

§Errors

Returns Error::Protocol if:

  • The received message is not an event (status code != 650)

Returns Error::Socket if:

  • The connection is closed
  • A network error occurs
§Example
use stem_rs::controller::Controller;
use stem_rs::EventType;
use stem_rs::events::ParsedEvent;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Subscribe to bandwidth events
controller.set_events(&[EventType::Bw]).await?;

// Receive and process events
loop {
    match controller.recv_event().await? {
        ParsedEvent::Bandwidth(bw) => {
            println!("Bandwidth: {} read, {} written", bw.read, bw.written);
        }
        other => println!("Other event: {:?}", other),
    }
}
§See Also
Source

pub async fn msg(&mut self, command: &str) -> Result<String, Error>

Sends a raw command to Tor and returns the response.

This is a low-level method for sending arbitrary control protocol commands. For most use cases, prefer the typed methods like get_info, signal, etc.

§Arguments
  • command - The raw command string to send
§Errors

Returns Error::OperationFailed if:

  • Tor returns an error response

Returns Error::Socket if:

  • The connection is closed
  • A network error occurs
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Send a raw GETINFO command
let response = controller.msg("GETINFO version").await?;
println!("Raw response: {}", response);
§See Also
Source

pub async fn create_ephemeral_hidden_service( &mut self, ports: &[(u16, &str)], key_type: &str, key_content: &str, flags: &[&str], ) -> Result<AddOnionResponse, Error>

Creates an ephemeral hidden service.

Unlike file-based hidden services, ephemeral services don’t touch disk and are the recommended way to create hidden services programmatically.

§Arguments
  • ports - Mapping of virtual ports to local targets (e.g., [(80, "127.0.0.1:8080")])
  • key_type - Type of key: "NEW" to generate, "RSA1024", or "ED25519-V3"
  • key_content - Key content or type to generate ("BEST", "RSA1024", "ED25519-V3")
  • flags - Optional flags like "Detach", "DiscardPK", "BasicAuth", "MaxStreamsCloseCircuit"
§Returns

Returns an AddOnionResponse containing:

  • service_id: The onion address (without .onion suffix)
  • private_key: The private key (unless DiscardPK flag was set)
  • private_key_type: The key type (e.g., "ED25519-V3")
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Create a v3 hidden service mapping port 80 to local port 8080
let response = controller.create_ephemeral_hidden_service(
    &[(80, "127.0.0.1:8080")],
    "NEW",
    "ED25519-V3",
    &[],
).await?;

println!("Hidden service: {}.onion", response.service_id);
§See Also
Source

pub async fn remove_ephemeral_hidden_service( &mut self, service_id: &str, ) -> Result<bool, Error>

Removes an ephemeral hidden service.

Discontinues a hidden service that was created with create_ephemeral_hidden_service.

§Arguments
  • service_id - The onion address without the .onion suffix
§Returns

Returns true if the service was removed, false if it wasn’t running.

§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Create and then remove a hidden service
let response = controller.create_ephemeral_hidden_service(
    &[(80, "127.0.0.1:8080")],
    "NEW",
    "BEST",
    &[],
).await?;

controller.remove_ephemeral_hidden_service(&response.service_id).await?;
Source

pub async fn load_conf(&mut self, config_text: &str) -> Result<(), Error>

Loads configuration text as if it were read from the torrc.

This allows dynamically configuring Tor without modifying the torrc file. The configuration text is processed as if it were part of the torrc.

§Arguments
  • config_text - The configuration text to load
§Errors

Returns Error::InvalidRequest if:

  • The configuration text contains invalid options
  • The configuration text has syntax errors

Returns Error::InvalidArguments if:

  • An unknown configuration option is specified
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Load configuration
controller.load_conf("MaxCircuitDirtiness 600").await?;
§See Also
  • set_conf: Set individual configuration options
  • save_conf: Save configuration to torrc
Source

pub async fn drop_guards(&mut self, reset_timeouts: bool) -> Result<(), Error>

Drops guard nodes and optionally resets circuit timeouts.

This forces Tor to drop its current guard nodes and select new ones. Optionally, circuit build timeout counters can also be reset.

§Arguments
  • reset_timeouts - If true, also reset circuit build timeout counters
§Errors

Returns Error::OperationFailed if:

  • Tor returns an error response
  • reset_timeouts is true but Tor version doesn’t support DROPTIMEOUTS
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

// Drop guards only
controller.drop_guards(false).await?;

// Drop guards and reset timeouts
controller.drop_guards(true).await?;
Source

pub async fn repurpose_circuit( &mut self, circuit_id: &CircuitId, purpose: CircuitPurpose, ) -> Result<(), Error>

Changes a circuit’s purpose.

Currently, two purposes are recognized: “general” and “controller”.

§Arguments
  • circuit_id - The ID of the circuit to repurpose
  • purpose - The new purpose for the circuit
§Errors

Returns Error::InvalidRequest if:

  • The circuit doesn’t exist
  • The purpose is invalid
§Example
use stem_rs::controller::{Controller, CircuitId, CircuitPurpose};

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let circuit_id = CircuitId::new("5");
controller.repurpose_circuit(&circuit_id, CircuitPurpose::Controller).await?;
Source

pub async fn enable_feature(&mut self, features: &[&str]) -> Result<(), Error>

Enables controller features that are disabled by default.

Once enabled, a feature cannot be disabled and a new control connection must be opened to get a connection with the feature disabled.

§Arguments
  • features - List of feature names to enable
§Errors

Returns Error::InvalidArguments if:

  • An unrecognized feature is specified
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

controller.enable_feature(&["VERBOSE_NAMES"]).await?;
Source

pub async fn get_listeners( &mut self, listener_type: ListenerType, ) -> Result<Vec<(String, u16)>, Error>

Gets the addresses and ports where Tor is listening for connections.

Returns a list of (address, port) tuples for the specified listener type.

§Arguments
  • listener_type - The type of listener to query
§Errors

Returns Error::OperationFailed if:

  • The GETINFO command fails

Returns Error::Protocol if:

  • The response format is unexpected
§Example
use stem_rs::controller::{Controller, ListenerType};

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let listeners = controller.get_listeners(ListenerType::Socks).await?;
for (addr, port) in listeners {
    println!("SOCKS listener: {}:{}", addr, port);
}
§See Also
Source

pub async fn get_ports( &mut self, listener_type: ListenerType, ) -> Result<HashSet<u16>, Error>

Gets just the port numbers where Tor is listening for connections.

Returns a set of unique port numbers for the specified listener type. This is a convenience method that extracts just the ports from get_listeners.

§Arguments
  • listener_type - The type of listener to query
§Example
use stem_rs::controller::{Controller, ListenerType};

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let ports = controller.get_ports(ListenerType::Socks).await?;
for port in ports {
    println!("SOCKS port: {}", port);
}
§See Also
Source

pub async fn get_user(&mut self) -> Result<String, Error>

Gets the user Tor is running as.

§Errors

Returns Error::OperationFailed if:

  • The information is not available
  • Tor returns an error response
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let user = controller.get_user().await?;
println!("Tor is running as: {}", user);
Source

pub async fn get_start_time(&mut self) -> Result<f64, Error>

Gets the Unix timestamp when Tor started.

Calculates the start time by subtracting the uptime from the current time.

§Errors

Returns an error if:

  • The uptime cannot be determined
  • The uptime value is invalid
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let start_time = controller.get_start_time().await?;
println!("Tor started at: {}", start_time);
§See Also
Source

pub async fn get_uptime(&mut self) -> Result<f64, Error>

Gets how long Tor has been running in seconds.

§Errors

Returns an error if:

  • The GETINFO command fails
  • The uptime value cannot be parsed
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let uptime = controller.get_uptime().await?;
println!("Tor has been running for {} seconds", uptime);
§See Also
Source

pub async fn get_protocolinfo(&mut self) -> Result<ProtocolInfo, Error>

Gets protocol information including authentication methods.

Returns information about the Tor control protocol version, the Tor version, and available authentication methods.

§Errors

Returns Error::Parse if:

  • The PROTOCOLINFO response cannot be parsed
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;

let info = controller.get_protocolinfo().await?;
println!("Protocol version: {}", info.protocol_version);
println!("Tor version: {}", info.tor_version);
println!("Auth methods: {:?}", info.auth_methods);
Source

pub async fn get_accounting_stats(&mut self) -> Result<AccountingStats, Error>

Gets accounting statistics for bandwidth limiting.

Returns statistics about Tor’s accounting status when AccountingMax is set in the torrc.

§Errors

Returns Error::OperationFailed if:

  • Accounting is not enabled
  • The GETINFO commands fail
§Example
use stem_rs::controller::Controller;

let mut controller = Controller::from_port("127.0.0.1:9051".parse()?).await?;
controller.authenticate(None).await?;

let stats = controller.get_accounting_stats().await?;
println!("Status: {}", stats.status);
println!("Read: {} bytes", stats.read_bytes);
println!("Written: {} bytes", stats.written_bytes);

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.