summaryrefslogtreecommitdiff
path: root/crates/tor-hsclient/src/connect.rs
blob: 9df26c8cbc67cb97bec13a91b3725b8a590737b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Main implementation of the connection functionality

//use std::time::SystemTime;

use std::sync::Arc;

use async_trait::async_trait;

use tor_hscrypto::pk::HsId;
use tor_netdir::NetDir;
use tor_proto::circuit::ClientCirc;
use tor_rtcompat::Runtime;

use crate::state::MockableConnectorData;
use crate::{ConnError, HsClientConnector, HsClientSecretKeys};

/// Information about a hidden service, including our connection history
#[allow(dead_code, unused_variables)] // TODO hs remove.
#[derive(Default, Debug)]
// This type is actually crate-private, since it isn't re-exported, but it must
// be `pub` because it appears as a default for a type parameter in HsClientConnector.
pub struct Data {
    //    /// A time when we should check whether this descriptor is still the latest.
    //    desc_fresh_until: SystemTime,
    //    /// A time when we should expire this entry completely.
    //    expires: SystemTime,
    /// The latest known onion service descriptor for this service.
    desc: (), // TODO hs: use actual onion service descriptor type.
    /// Information about the latest status of trying to connect to this service
    /// through each of its introduction points.
    ///
    ipts: (), // TODO hs: make this type real, use `RetryDelay`, etc.
}

/// Actually make a HS connection, updating our recorded state as necessary
///
/// `connector` is provided only for obtaining the runtime and netdir (and `mock_for_state`).
/// Obviously, `connect` is not supposed to go looking in `services`.
///
/// This function handles all necessary retrying of fallible operations,
/// (and, therefore, must also limit the total work done for a particular call).
#[allow(dead_code, unused_variables)] // TODO hs remove.
pub(crate) async fn connect(
    connector: &HsClientConnector<impl Runtime>,
    netdir: Arc<NetDir>,
    hsid: HsId,
    data: &mut Data,
    secret_keys: HsClientSecretKeys,
) -> Result<ClientCirc, ConnError> {
    // This function must do the following, retrying as appropriate.
    //  - Look up the onion descriptor in the state.
    //  - Download the onion descriptor if one isn't there.
    //  - In parallel:
    //    - Pick a rendezvous point from the netdirprovider and launch a
    //      rendezvous circuit to it. Then send ESTABLISH_INTRO.
    //    - Pick a number of introduction points (1 or more) and try to
    //      launch circuits to them.
    //  - On a circuit to an introduction point, send an INTRODUCE1 cell.
    //  - Wait for a RENDEZVOUS2 cell on the rendezvous circuit
    //  - Add a virtual hop to the rendezvous circuit.
    //  - Return the rendezvous circuit.
    todo!()
}

#[async_trait]
impl MockableConnectorData for Data {
    type ClientCirc = ClientCirc;
    type MockGlobalState = ();

    async fn connect<R: Runtime>(
        connector: &HsClientConnector<R>,
        netdir: Arc<NetDir>,
        hsid: HsId,
        data: &mut Self,
        secret_keys: HsClientSecretKeys,
    ) -> Result<Self::ClientCirc, ConnError> {
        connect(connector, netdir, hsid, data, secret_keys).await
    }

    fn circuit_is_ok(circuit: &Self::ClientCirc) -> bool {
        !circuit.is_closing()
    }
}