<!--
{
  "availability" : [

  ],
  "documentType" : "symbol",
  "framework" : "Tor",
  "identifier" : "/documentation/Tor/TorSession",
  "metadataVersion" : "0.1.0",
  "role" : "Protocol",
  "symbol" : {
    "kind" : "Protocol",
    "modules" : [
      "Tor"
    ],
    "preciseIdentifier" : "s:3Tor0A7SessionP"
  },
  "title" : "TorSession"
}
-->

# TorSession

Minimal lifecycle interface for driving (or mocking) an embedded Tor
instance.

```
protocol TorSession : Sendable
```

## Overview

`TorSession` is the seam between swift-tor’s concrete [`TorClient`](/documentation/Tor/TorClient) actor
and downstream code that wants to exercise Tor’s lifecycle without
paying the real-world cost of it. A production conformer launches
`tor_run_main()` on a dedicated thread, negotiates with the Tor network
(guard selection, consensus download, circuit build — typically
30–60 s), and exposes the SOCKS endpoint when complete. A test
conformer returns a fabricated endpoint immediately, pushes synthetic
[`TorEvent`](/documentation/Tor/TorEvent) values through its [`events`](/documentation/Tor/TorSession/events) stream, and never touches
the network.

The surface is deliberately narrow: one method each for start/stop/wait,
one async-get property for the SOCKS endpoint, and one stream property
for lifecycle events. Anything richer (`GETINFO`, `addOnion`, URLSession
proxy helpers) lives on [`TorClient`](/documentation/Tor/TorClient) directly and is out of scope for
mocking through this protocol.

> Note: Conformance is `Sendable` — all methods are `async` (or `async throws`) and all properties are `async` getters, so implementations
> are free to use actor isolation, `Mutex`, or any other serialisation
> strategy for internal state.

> Important: Mock conformers should preserve causal ordering: a call to
> ``doc://Tor/documentation/Tor/TorSession/waitUntilBootstrapped(timeout:)`` must observe at least
> one ``doc://Tor/documentation/Tor/TorSession/start()`` before returning successfully, otherwise downstream
> state machines that assume “bootstrapped implies started” will drift.

## Topics

### Lifecycle

[`start()`](/documentation/Tor/TorSession/start())

Start the underlying Tor instance.

[`stop()`](/documentation/Tor/TorSession/stop())

Stop the Tor instance and release any resources.

[`waitUntilBootstrapped(timeout:)`](/documentation/Tor/TorSession/waitUntilBootstrapped(timeout:))

Block until Tor reports 100% bootstrap progress, or fail after
`timeout`.

[`waitUntilBootstrapped()`](/documentation/Tor/TorSession/waitUntilBootstrapped())

Wait up to the default 120-second bootstrap window.

### Observing state

[`socksEndpoint`](/documentation/Tor/TorSession/socksEndpoint)

Tor’s local SOCKS5 proxy endpoint, `nil` until the port is known.

[`events`](/documentation/Tor/TorSession/events)

Back-pressure-aware async stream of [`TorEvent`](/documentation/Tor/TorEvent) values for this
session.

