pub struct RelayCircuit {
pub id: u32,
/* private fields */
}Expand description
A circuit established through a Tor relay.
RelayCircuit represents an established circuit through a Relay and
provides methods for sending and receiving encrypted data. Circuits are
the fundamental unit of communication in the Tor network.
§Conceptual Role
A circuit is a path through one or more Tor relays. This implementation supports single-hop circuits created with CREATE_FAST. Each circuit has:
- A unique circuit ID within the relay connection
- Forward and backward encryption keys
- Forward and backward digests for integrity checking
§Encryption Semantics
Data sent through the circuit is encrypted using AES-CTR mode:
- Forward direction: Client → Relay (uses
forward_key) - Backward direction: Relay → Client (uses
backward_key)
Each direction also maintains a running SHA-1 digest for integrity verification of relay cells.
§Invariants
- Circuit ID is unique within the parent relay connection
- Encryption keys are derived from the CREATE_FAST handshake
- The circuit remains valid until explicitly closed
§Thread Safety
RelayCircuit is Clone and Send. Multiple clones share the same
underlying relay connection through Arc<Mutex<_>>. Operations are
serialized through the mutex.
§Example
use stem_rs::client::{Relay, DEFAULT_LINK_PROTOCOLS};
let mut relay = Relay::connect("127.0.0.1", 9001, DEFAULT_LINK_PROTOCOLS).await?;
let mut circuit = relay.create_circuit().await?;
// Make a directory request
let request = "GET /tor/server/authority HTTP/1.0\r\n\r\n";
let response = circuit.directory(request, 1).await?;
println!("Received {} bytes", response.len());
circuit.close().await?;§Security
- Keys are stored in memory for the circuit’s lifetime
- Encryption is not yet fully implemented (placeholder)
- Single-hop circuits don’t provide anonymity
Fields§
§id: u32The unique identifier for this circuit within the relay connection.
Circuit IDs are assigned sequentially starting from the link protocol’s
first_circ_id value. The ID is used in all cells sent on this circuit.
Implementations§
Source§impl RelayCircuit
impl RelayCircuit
Sourcepub async fn directory(
&mut self,
request: &str,
stream_id: u16,
) -> Result<Vec<u8>, Error>
pub async fn directory( &mut self, request: &str, stream_id: u16, ) -> Result<Vec<u8>, Error>
Sends a directory request through this circuit and returns the response.
This method establishes a directory stream and sends an HTTP request to fetch descriptor data from the relay. The relay must support the DirPort functionality for this to work.
§Protocol
- Send RELAY_BEGIN_DIR cell to open a directory stream
- Send RELAY_DATA cell with the HTTP request
- Receive RELAY_DATA cells with the response
- Stream ends when RELAY_END cell is received
§Arguments
request- HTTP request string (e.g.,"GET /tor/server/authority HTTP/1.0\r\n\r\n")stream_id- Stream identifier for this request (must be non-zero)
§Returns
The raw HTTP response bytes, including headers and body.
§Errors
Returns Error::Protocol if:
- Response is for a different circuit ID
- Unexpected cell type is received
- I/O errors occur during communication
§Example
use stem_rs::client::{Relay, DEFAULT_LINK_PROTOCOLS};
let mut relay = Relay::connect("127.0.0.1", 9001, DEFAULT_LINK_PROTOCOLS).await?;
let mut circuit = relay.create_circuit().await?;
// Fetch the relay's server descriptor
let request = "GET /tor/server/authority HTTP/1.0\r\n\r\n";
let response = circuit.directory(request, 1).await?;
// Parse the HTTP response
let response_str = String::from_utf8_lossy(&response);
println!("{}", response_str);§Common Requests
/tor/server/authority- Relay’s own server descriptor/tor/server/fp/<fingerprint>- Server descriptor by fingerprint/tor/status-vote/current/consensus- Current consensus document
Sourcepub async fn close(&mut self) -> Result<(), Error>
pub async fn close(&mut self) -> Result<(), Error>
Closes this circuit.
Sends a DESTROY cell to the relay to tear down the circuit. After calling this method, the circuit can no longer be used for communication.
§Errors
Returns an error if the DESTROY cell cannot be sent.
§Example
use stem_rs::client::{Relay, DEFAULT_LINK_PROTOCOLS};
let mut relay = Relay::connect("127.0.0.1", 9001, DEFAULT_LINK_PROTOCOLS).await?;
let mut circuit = relay.create_circuit().await?;
// Use the circuit...
// Close when done
circuit.close().await?;Trait Implementations§
Source§impl Clone for RelayCircuit
impl Clone for RelayCircuit
Source§fn clone(&self) -> RelayCircuit
fn clone(&self) -> RelayCircuit
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more