### Rust Basic TLS Connection Setup Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-rtcompat/src/lib Illustrates the setup for a TLS connection. This example includes loading a self-signed certificate and its associated password, intended for use in a TLS server context. It uses a PFX file and specifies a password for decryption. ```rust fn simple_tls(runtime: &R) -> IoResult<()> { static PFX_ID: &[u8] = include_bytes!("test.pfx"); static PFX_PASSWORD: &str = "abc"; // ... implementation details for TLS connection ... Ok(()) } ``` -------------------------------- ### Example TOML Connection Point Configurations (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-rpc-connect/src/load Defines several string constants representing example TOML configurations for connection points. These are used in tests to verify parsing and loading logic for different valid connection point setups. ```rust const EXAMPLE_1: &str = r#" [connect] socket = "inet:[::1]:9191" socket_canonical = "inet:[::1]:2020" auth = { cookie = { path = "/home/user/.arti_rpc/cookie" } } "#; const EXAMPLE_2: &str = r#" [connect] socket = "inet:[::1]:9000" socket_canonical = "inet:[::1]:2000" auth = { cookie = { path = "/home/user/.arti_rpc/cookie" } } "#; const EXAMPLE_3: &str = r#" [connect] socket = "inet:[::1]:413" socket_canonical = "inet:[::1]:612" auth = { cookie = { path = "/home/user/.arti_rpc/cookie" } } "#; ``` -------------------------------- ### Launch RPC Manager and Listeners Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/arti/src/rpc Initializes the RPC manager, binds to network endpoints, and starts a listener task to accept incoming RPC connections. It handles configuration and client setup, returning RPC proxy support details upon successful launch. ```rust pub(crate) async fn launch_rpc_mgr( runtime: &R, cfg: &RpcConfig, resolver: &CfgPathResolver, mistrust: &Mistrust, client: TorClient, ) -> Result> { if !cfg.enable { return Ok(None); } let (rpc_state, rpc_state_sender) = RpcVisibleArtiState::new(); let rpc_mgr = RpcMgr::new(move |auth| ArtiRpcSession::new(auth, &client, &rpc_state))?; // Register methods. Needed since TorClient is generic. // // TODO: If we accumulate a large number of generics like this, we should do this elsewhere. rpc_mgr.register_rpc_methods(TorClient::::rpc_methods()); rpc_mgr.register_rpc_methods(arti_rpcserver::rpc_methods::()); let rt_clone = runtime.clone(); let rpc_mgr_clone = rpc_mgr.clone(); let (incoming, guards) = launch_all_listeners(runtime, cfg, resolver, mistrust).await?; // TODO: Using spawn in this way makes it hard to report whether we // succeeded or not. This is something we should fix when we refactor // our service-launching code. runtime.spawn(async move { let result = run_rpc_listener(rt_clone, incoming, rpc_mgr_clone).await; if let Err(e) = result { tracing::warn!("RPC manager quit with an error: {}", e); } drop(guards); })?; Ok(Some(RpcProxySupport { rpc_mgr, rpc_state_sender, })) } ``` -------------------------------- ### Basic TLS Listener Setup in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-rtmock/src/net Illustrates setting up a TLS-enabled listener using client_pair and a predefined certificate. It demonstrates how to start a secure listener and retrieve its local address. This snippet is a foundational step for secure communication testing. ```rust let (client1, client2) = client_pair(); let cert = b"I am certified for something I assure you."; test_with_all_runtimes!(|_rt| async { let lis = client2 .listen_tls(&"0.0.0.0:0".parse().unwrap(), cert[..].into()) .unwrap(); let address = lis.local_addr().unwrap(); // ... further operations with lis and address ... IoResult::Ok(()) }); ``` -------------------------------- ### Rust: Construct ExampleSectionLines from Markers Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti/src/cfg Implements a generic constructor for `ExampleSectionLines` that accepts start and end string references. It parses `ARTI_EXAMPLE_CONFIG`, extracting lines that start with the `start` marker up to, but not including, the `end` marker. It also handles identifying a section header if the `start` marker is enclosed in brackets. ```rust /// Construct a new `ExampleSectionLines` from `ARTI_EXAMPLE_CONFIG`, /// containing everything that starts with `start`, up to but not /// including the next line that begins with `end`. /// /// If `start` is a configuration section header it will be put in the /// `section` field of the returned `ExampleSectionLines`, otherwise /// at the beginning of the `lines` field. /// /// `start` will be perceived as a configuration section header if it /// starts with `[` and ends with `]`. fn from_markers(start: S, end: E) -> Self where S: AsRef, E: AsRef, { let (start, end) = (start.as_ref(), end.as_ref()); let mut lines = ARTI_EXAMPLE_CONFIG .lines() .skip_while(|line| !line.starts_with(start)) .peekable(); let section = lines .next_if(|l0| l0.starts_with('[')) .map(|section| section.to_owned()) .unwrap_or_default(); let lines = lines .take_while(|line| !line.starts_with(end)) .map(|l| l.to_owned()) .collect_vec(); Self { section, lines } } ``` -------------------------------- ### Construct ExampleSectionLines from Markers in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/arti/src/cfg Implements a generic constructor `from_markers` for `ExampleSectionLines`. It extracts lines from `ARTI_EXAMPLE_CONFIG` starting from a `start` marker up to an `end` marker. It handles whether the start marker is a section header. ```rust impl ExampleSectionLines { /// Construct a new `ExampleSectionLines` from `ARTI_EXAMPLE_CONFIG`, /// containing everything that starts with `start`, up to but not /// including the next line that begins with `end`. /// /// If `start` is a configuration section header it will be put in the /// `section` field of the returned `ExampleSectionLines`, otherwise /// at the beginning of the `lines` field. /// /// `start` will be perceived as a configuration section header if it /// starts with `[` and ends with `]`. fn from_markers(start: S, end: E) -> Self where S: AsRef, E: AsRef, { let (start, end) = (start.as_ref(), end.as_ref()); let mut lines = ARTI_EXAMPLE_CONFIG .lines() .skip_while(|line| !line.starts_with(start)) .peekable(); let section = lines .next_if(|l0| l0.starts_with('[')) .map(|section| section.to_owned()) .unwrap_or_default(); let lines = lines .take_while(|line| !line.starts_with(end)) .map(|l| l.to_owned()) .collect_vec(); Self { section, lines } } } ``` -------------------------------- ### Initialize IPT Parameters and Establisher Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_mgr This section sets up the necessary parameters for an Introduction Point establisher and then creates a new establisher instance. It includes details like replay log, network directory provider, and introduction point configuration. ```rust let replay_log = IptReplayLog::new_logged(&imm.replay_log_dir, &lid)?; let params = IptParameters { replay_log, config_rx: new_configs.clone(), netdir_provider: imm.dirprovider.clone(), introduce_tx: imm.output_rend_reqs.clone(), lid, target: relay.clone(), k_sid: k_sid.clone(), k_ntor: Arc::clone(&k_hss_ntor), accepting_requests: ipt_establish::RequestDisposition::NotAdvertised, }; let (establisher, mut watch_rx) = mockable.make_new_ipt(imm, params)?; ``` -------------------------------- ### Initialize and Launch Introduction Point Establisher (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_establish Initializes and launches an introduction point establisher. This function sets up the necessary state, context, and communication channels for managing an introduction point. It requires a runtime, parameters including configuration and keying material, and a connection pool. It returns the establisher and a status receiver, or a fatal error if initialization fails. ```rust pub(crate) fn launch( runtime: &R, params: IptParameters, pool: Arc>, keymgr: &Arc, ) -> Result<(Self, postage::watch::Receiver), FatalError> { let IptParameters { config_rx, netdir_provider, introduce_tx, lid, target, k_sid, k_ntor, accepting_requests, replay_log, } = params; let config = Arc::clone(&config_rx.borrow()); let nickname = config.nickname().clone(); if matches!(accepting_requests, RequestDisposition::Shutdown) { return Err( bad_api_usage!("Tried to create a IptEstablisher that that was already shutting down?") .into() ); } let state = Arc::new(Mutex::new(EstablisherState { accepting_requests })); let request_context = Arc::new(RendRequestContext { nickname: nickname.clone(), keymgr: Arc::clone(keymgr), kp_hss_ntor: Arc::clone(&k_ntor), kp_hs_ipt_sid: k_sid.as_ref().as_ref().verifying_key().into(), filter: config.filter_settings(), netdir_provider: netdir_provider.clone(), circ_pool: pool.clone(), }); let reactor = Reactor { runtime: runtime.clone(), nickname, pool, netdir_provider, lid, target, k_sid, introduce_tx, extensions: EstIntroExtensionSet { dos_params: config.dos_extension()?, }, state: state.clone(), request_context, replay_log: Arc::new(replay_log.into()), }; let (status_tx, status_rx) = postage::watch::channel_with(IptStatus::new()); let (terminate_tx, mut terminate_rx) = oneshot::channel::(); let status_tx = DropNotifyWatchSender::new(status_tx); runtime .spawn(async move { futures::select_biased!( terminated = terminate_rx => { let oneshot::Canceled = terminated.void_unwrap_err(); } outcome = reactor.keep_intro_established(status_tx).fuse() => { warn_report!(outcome.void_unwrap_err(), "Error from intro-point establisher task"); } ); }) .map_err(|e| FatalError::Spawn { spawning: "introduction point establisher", cause: Arc::new(e), })?; let establisher = IptEstablisher { _terminate_tx: terminate_tx, state, }; Ok((establisher, status_rx)) } ``` -------------------------------- ### Uncomment Example Settings in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti/src/cfg This Rust function takes a string representing a configuration template and uses a regular expression to uncomment lines that start with a '#' followed by a non-whitespace character. It's used to prepare example configuration files for testing. ```rust fn uncomment_example_settings(template: &str) -> String { let re = Regex::new(r#"(?m)^#([^ \n])"#).unwrap(); re.replace_all(template, |cap: ®ex::Captures<'_>| -> _ { cap.get(1).unwrap().as_str().to_string() }) .into() } ``` -------------------------------- ### Start Accepting Introduction Requests (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_establish Enables an introduction point to start accepting incoming introduction requests. This method modifies the internal state to transition from an initial state to an 'Advertised' state, indicating readiness to process requests. Failure to call this method before sending requests will result in errors and connection closures. ```rust /// Begin accepting requests from this introduction point. /// /// If any introduction requests are sent before we have called this method, /// they are treated as an error and our connection to this introduction /// point is closed. pub(crate) fn start_accepting(&self) { self.state.lock().expect("poisoned lock").accepting_requests = RequestDisposition::Advertised; } ``` -------------------------------- ### Rust: Calculate example wallclock time Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-dirmgr/src/bridgedesc/bdtest This Rust function `example_wallclock` calculates an example wallclock time by taking the start of the validity period from `example_validity` and adding a 10-second duration. This is useful for setting up test scenarios that require specific time points. ```rust fn example_wallclock() -> SystemTime { example_validity().0 + Duration::from_secs(10) } ``` -------------------------------- ### Launch Introduction Point Establisher in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hsservice/src/ipt_establish Initializes and launches a new Introduction Point (IP) establisher. This function sets up the necessary state, context, and a background task to maintain the IP's connection. It takes runtime, parameters, circuit pool, and key manager as input, returning the establisher instance and a status receiver. Errors can occur during initialization or task spawning. ```rust pub(crate) fn launch( runtime: &R, params: IptParameters, pool: Arc>, keymgr: &Arc, ) -> Result<(Self, postage::watch::Receiver), FatalError> { let IptParameters { config_rx, netdir_provider, introduce_tx, lid, target, k_sid, k_ntor, accepting_requests, replay_log, } = params; let config = Arc::clone(&config_rx.borrow()); let nickname = config.nickname().clone(); if matches!(accepting_requests, RequestDisposition::Shutdown) { return Err(bad_api_usage!("Tried to create a IptEstablisher that that was already shutting down?" ).into()); } let state = Arc::new(Mutex::new(EstablisherState { accepting_requests })); let request_context = Arc::new(RendRequestContext { nickname: nickname.clone(), keymgr: Arc::clone(keymgr), kp_hss_ntor: Arc::clone(&k_ntor), kp_hs_ipt_sid: k_sid.as_ref().as_ref().verifying_key().into(), filter: config.filter_settings(), netdir_provider: netdir_provider.clone(), circ_pool: pool.clone(), }); let reactor = Reactor { runtime: runtime.clone(), nickname, pool, netdir_provider, lid, target, k_sid, introduce_tx, extensions: EstIntroExtensionSet { dos_params: config.dos_extension()?, }, state: state.clone(), request_context, replay_log: Arc::new(replay_log.into()), }; let (status_tx, status_rx) = postage::watch::channel_with(IptStatus::new()); let (terminate_tx, mut terminate_rx) = oneshot::channel::(); let status_tx = DropNotifyWatchSender::new(status_tx); runtime .spawn(async move { futures::select_biased!( terminated = terminate_rx => { let oneshot::Canceled = terminated.void_unwrap_err(); } outcome = reactor.keep_intro_established(status_tx).fuse() => { warn_report!(outcome.void_unwrap_err(), "Error from intro-point establisher task"); } ); }) .map_err(|e| FatalError::Spawn { spawning: "introduction point establisher", cause: Arc::new(e), })?; let establisher = IptEstablisher { _terminate_tx: terminate_tx, state, }; Ok((establisher, status_rx)) } ``` -------------------------------- ### Implement IptEstablisher::new for Onion Service Introduction Points Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hsservice/src/ipt_establish The `IptEstablisher::new` function initializes a new introduction point establisher. It takes `IptParameters` which bundles configuration and state, and an `accepting_requests` flag to determine initial request handling. This method sets up the necessary tasks to maintain the introduction point, and returns a stream of `IptStatus` events. Dropping the returned `IptEstablisher` cancels all associated tasks and closes circuits. ```rust impl IptEstablisher { /// Try to set up, and maintain, an IPT at `target`. /// /// Rendezvous requests will be rejected or accepted /// depending on the value of `accepting_requests` /// (which must be `Advertised` or `NotAdvertised`). /// /// Also returns a stream of events that is produced whenever we have a /// change in the IptStatus for this intro point. Note that this stream is /// potentially lossy. /// /// The returned `watch::Receiver` will yield `Faulty` if the IPT /// establisher is shut down (or crashes). /// /// When the resulting `IptEstablisher` is dropped, it will cancel all tasks /// and close all circuits used to establish this introduction point. pub(crate) fn new( params: IptParameters, accepting_requests: RequestDisposition, ) -> (Self, watch::Receiver) { // ... implementation details ... } } ``` -------------------------------- ### Example: Building a List of Structs with Builders Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-config/src/list_builder This example demonstrates how to use `define_list_builder_helper` and `define_list_builder_accessors` to manage a list of `Thing` structs within an `Outer` struct. It shows the setup of the structs, the usage of the macros, and the instantiation and modification of the builder. Dependencies include `derive_builder`, `serde`, and `tor_config`. ```rust use derive_builder::Builder; use serde::{Deserialize, Serialize}; use tor_config::{define_list_builder_helper, define_list_builder_accessors, ConfigBuildError}; #[derive(Builder, Debug, Eq, PartialEq)] #[builder(build_fn(error = "ConfigBuildError"))] #[builder(derive(Debug, Serialize, Deserialize))] pub struct Thing { value: i32 } #[derive(Builder, Debug, Eq, PartialEq)] #[builder(build_fn(error = "ConfigBuildError"))] #[builder(derive(Debug, Serialize, Deserialize))] pub struct Outer { /// List of things, being built as part of the configuration #[builder(sub_builder, setter(custom))] things: ThingList, } define_list_builder_accessors! { struct OuterBuilder { pub things: [ThingBuilder], } } /// Type alias for use by list builder macrology type ThingList = Vec; define_list_builder_helper! { pub(crate) struct ThingListBuilder { pub(crate) things: [ThingBuilder], } built: ThingList = things; default = vec![]; } let mut builder = OuterBuilder::default(); builder.things().push(ThingBuilder::default().value(42).clone()); ``` -------------------------------- ### MockExecutor Creation with Default Parameters Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-rtmock/src/task Creates a new MockExecutor instance with default configuration. This is the simplest way to get started with MockExecutor for testing purposes. ```rust impl MockExecutor { /// Make a `MockExecutor` with default parameters pub fn new() -> Self { Self::default() } } ``` -------------------------------- ### Rust: Construct ExampleSectionLines from Section Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti/src/cfg Implements a constructor for `ExampleSectionLines` that takes a section name and creates an instance by parsing the `ARTI_EXAMPLE_CONFIG`. It extracts lines starting with the section header up to the next section. ```rust impl ExampleSectionLines { /// Construct a new `ExampleSectionLines` from `ARTI_EXAMPLE_CONFIG`, containing /// everything that starts with `[section]`, up to but not including the /// next line that begins with a `[`. fn from_section(section: &str) -> Self { Self::from_markers(format!("[{{section}}]"), "[") } ``` -------------------------------- ### Memory Quota Tracker Setup and Usage Example (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-memquota/src/mtracker This example demonstrates how to initialize and use the MemoryQuotaTracker. It shows setting up a runtime, configuring the tracker with a specific memory limit, and creating new accounts. It also illustrates registering a custom `TrackingQueue` as a participant to monitor memory usage. ```rust #![cfg_attr(feature = "memquota", doc = "let trk = MemoryQuotaTracker::new(&runtime, config).unwrap();")] #![cfg_attr(not(feature = "memquota"), doc = "let trk = MemoryQuotaTracker::new_noop();")] let runtime = PreferredRuntime::create().unwrap(); let config = tor_memquota::Config::builder().max(1024*1024*1024).build().unwrap(); let account = trk.new_account(None).unwrap(); let queue: Arc = account.register_participant_with( runtime.now_coarse(), |partn| { Ok::<_, Void>((Arc::new(TrackingQueue(Mutex::new(Ok(Inner { partn, data: VecDeque::new(), })))), ())) // Note: the second () is from the original code, possibly a typo or placeholder. }, ).unwrap().void_unwrap().0; queue.push(runtime.now_coarse(), Box::new([0; 24])).unwrap(); ``` -------------------------------- ### Start Accepting Introduction Requests in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hsservice/src/ipt_establish Changes the state of an Introduction Point (IP) establisher to begin accepting introduction requests. This method should be called before any introduction requests are sent to the IP. Failure to do so will result in requests being treated as errors and the connection being closed. ```rust pub(crate) fn start_accepting(&self) { self.state.lock().expect("poisoned lock").accepting_requests = RequestDisposition::Advertised; } ``` -------------------------------- ### Initialize Tor Client Configuration Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/arti/src/subcommands/proxy Demonstrates the initialization of a TorClient with a given runtime and configuration. It also sets the bootstrap behavior to OnDemand, indicating that connections will be established as needed. ```rust let fs_mistrust = client_config.fs_mistrust().clone(); let path_resolver: CfgPathResolver = AsRef::::as_ref(&client_config).clone(); let client_builder = TorClient::with_runtime(runtime.clone()) .config(client_config) .bootstrap_behavior(OnDemand); let client = client_builder.create_unbootstrapped_async().await?; ``` -------------------------------- ### Checking Development Environment Setup Source: https://tpo.pages.torproject.net/core/arti/contributing Execute this script to verify if all necessary dependencies for running maintenance scripts, such as coverage reports, are installed on your system. It will report any missing dependencies. ```bash ./maint/check_env ``` -------------------------------- ### Rust: Helper Struct for Configuration Parsing Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/arti/src/cfg The `ExampleSectionLines` struct is a testing utility designed to parse and manipulate sections of configuration files. It allows for ad-hoc regexp matching, uncommenting lines, and resolving parsed results, facilitating complex configuration tests. ```rust /// Helper for fishing out parts of the config file and uncommenting them. /// /// It represents a part of a configuration file. /// /// This can be used to find part of the config file by ad-hoc regexp matching, /// uncomment it, and parse it. This is useful as part of a test to check /// that we can parse more complex config. #[derive(Debug, Clone)] struct ExampleSectionLines { /// The header for the section that we are parsing. It is /// prepended to the lines before parsing them. section: String, /// The lines in the section. lines: Vec, } ``` -------------------------------- ### Default Agent Creation Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/arti-ureq/src/lib Creates a default `ureq::Agent` instance using the default `Connector`. This is the recommended way to get started with making requests through Tor. ```APIDOC ## POST /api/users ### Description Creates a default `ureq::Agent` instance using the default `Connector`. This is the recommended way to get started with making requests through Tor. ### Method GET ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```json { "example": "No request body for this operation." } ``` ### Response #### Success Response (200) - **agent** (ureq::Agent) - The created ureq::Agent instance. #### Response Example ```json { "example": "ureq::Agent instance" } ``` ``` -------------------------------- ### Create Arti ureq Connector with Default TorClient Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti-ureq/src/lib Instantiates a Connector using a default TorClient. This is the simplest way to get started. It handles the creation of the underlying Tor client and its runtime. ```rust let connector = arti_ureq::Connector::new().expect("Failed to create Connector."); ``` -------------------------------- ### Establish Introduction Point Logic in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hsservice/src/ipt_establish This Rust code snippet demonstrates the core logic for establishing an introduction point. It handles successful connections, cases where the intro point is not listed in the network directory, and general error handling with retry mechanisms. It uses the `debug!` macro for logging and `IptEstablisherError` for error management. ```Rust debug!( "{}: Successfully established introduction point with {}", &self.nickname, self.target.display_relay_ids().redacted() ); // Now that we've succeeded, we can stop backing off for our // next attempt. retry_delay.reset(); // Wait for the session to be closed. session.wait_for_close().await; } Err(e @ IptEstablisherError::Ipt(IptError::IntroPointNotListed)) => { // The network directory didn't include this relay. Wait // until it does. // // Note that this `note_error` will necessarily mark the // ipt as Faulty. That's important, since we may be about to // wait indefinitely when we call wait_for_netdir_to_list. status_tx.borrow_mut().note_error(&e, self.runtime.now()); self.netdir_provider .wait_for_netdir_to_list(&self.target, Timeliness::Timely) .await?; } Err(e) => { status_tx.borrow_mut().note_error(&e, self.runtime.now()); debug_report!( e, "{}: Problem establishing introduction point with {}", &self.nickname, self.target.display_relay_ids().redacted() ); let retry_after = retry_delay.next_delay(&mut rand::rng()); self.runtime.sleep(retry_after).await; } } } } ``` -------------------------------- ### Start IPT Establisher Function - Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_mgr Initiates the establishment of a new Introduction Point (IPT). This function handles key management, configuration loading, and returns an `Ipt` object or a `CreateIptError`. It supports options for key existence checks and configuration. ```rust /// Token, representing promise by caller of `start_establisher` ``` 365 ``` /// ``` 366 ``` /// Caller who makes one of these structs promises that it is OK for `start_establisher` ``` 367 ``` /// to set `last_descriptor_expiry_including_slop` to `None`. ``` 368 ``` struct PromiseLastDescriptorExpiryNoneIsGood {} ``` 369 ``` 370 ``` /// Token telling [`Ipt::start_establisher`] to expect existing keys in the keystore ``` 371 ``` #[derive(Debug, Clone, Copy)] ``` 372 ``` struct IptExpectExistingKeys; ``` 373 ``` 374 ``` impl Ipt { ``` 375 ``` /// Start a new IPT establisher, and create and return an `Ipt` ``` 376 ``` #[allow(clippy::too_many_arguments)] // There's only two call sites ``` 377 40 ``` fn start_establisher>( ``` 378 40 ``` imm: &Immutable, ``` 379 40 ``` new_configs: &watch::Receiver>, ``` 380 40 ``` mockable: &mut M, ``` 381 40 ``` relay: &RelayIds, ``` 382 40 ``` lid: IptLocalId, ``` 383 40 ``` is_current: Option, ``` 384 40 ``` expect_existing_keys: Option, ``` 385 40 ``` _: PromiseLastDescriptorExpiryNoneIsGood, ``` 386 40 ``` ) -> Result { ``` 387 40 ``` let mut rng = tor_llcrypto::rng::CautiousRng; ``` 388 ``` 389 ``` /// Load (from disk) or generate an IPT key with role IptKeyRole::$role ``` 390 ``` /// ``` 391 ``` /// Ideally this would be a closure, but it has to be generic over the ``` 392 ``` /// returned key type. So it's a macro. (A proper function would have ``` 393 ``` /// many type parameters and arguments and be quite annoying.) ``` 394 80 ``` macro_rules! get_or_gen_key { { $Keypair:ty, $role:ident } => { (||{ ``` 395 80 ``` let spec = IptKeySpecifier { ``` 396 80 ``` nick: imm.nick.clone(), ``` 397 80 ``` role: IptKeyRole::$role, ``` 398 80 ``` lid, ``` 399 80 ``` }; ``` 400 ``` // Our desired behaviour: ``` 401 ``` // expect_existing_keys == None ``` 402 ``` // The keys shouldn't exist. Generate and insert. ``` 403 ``` // If they do exist then things are badly messed up ``` 404 ``` // (we're creating a new IPT with a fres lid). ``` 405 ``` // So, then, crash. ``` 406 ``` // expect_existing_keys == Some(IptExpectExistingKeys) ``` 407 ``` // The key is supposed to exist. Load them. ``` 408 ``` // We ought to have stored them before storing in our on-disk records that ``` 409 ``` // this IPT exists. But this could happen due to file deletion or something. ``` 410 ``` // And we could recover by creating fresh keys, although maybe some clients ``` 411 ``` // would find the previous keys in old descriptors. ``` 412 ``` // So if the keys are missing, make and store new ones, logging an error msg. ``` 413 80 ``` let k: Option<$Keypair> = imm.keymgr.get(&spec)?; ``` 414 80 ``` let arti_path = || { ``` 415 ``` spec ``` 416 ``` .arti_path() ``` 417 ``` .map_err(|e| { ``` 418 ``` CreateIptError::Fatal( ``` 419 ``` ``` -------------------------------- ### Default Agent Usage Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti-ureq/src/lib This section describes how to obtain a default ureq agent that is configured to use the Tor network via Arti. It provides an example of making a simple GET request. ```APIDOC ## GET /api/ip (Example with Default Agent) ### Description This example demonstrates making a GET request to an external service using a default ureq agent configured with Arti for Tor network access. ### Method GET ### Endpoint http://check.torproject.org/api/ip ### Parameters None ### Request Example ```rust use arti_ureq::default_agent; let agent = default_agent().expect("Failed to create default agent."); agent.get("http://check.torproject.org/api/ip").call().expect("Failed to make request."); ``` ### Response #### Success Response (200) - **body** (string) - The response body from the requested URL, typically in JSON format. #### Response Example ```json { "origin": "1.2.3.4", "url": "http://check.torproject.org/api/ip" } ``` ### Notes - The `default_agent()` function creates a TorClient internally, and it's recommended to create only one `TorClient` instance per application. ``` -------------------------------- ### Get and Validate Current Directory (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/fs-mistrust/src/walk Retrieves the current working directory and ensures it is an absolute path. If the directory is not absolute, it returns an error. This is crucial for establishing a reliable starting point for path resolution. ```rust let cwd = std::env::current_dir().map_err(|e| Error::CurrentDirectory(Arc::new(e)))?; if !cwd.is_absolute() { // This should be impossible, but let's make sure. let ioe = io::Error::other(format!("Current directory {:?} was not absolute.", cwd)); return Err(Error::CurrentDirectory(Arc::new(ioe))); } push_prefix(&mut resolve.stack, cwd.as_ref()); ``` -------------------------------- ### Initialize and Setup Core Components Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-memquota/src/mq_queue Initializes the tracker, creates a new account, and sets up an ItemTracker. These are fundamental components for managing items and tracking their state within the Arti system. Dependencies include `mk_tracker` and `new_account` from the runtime and tracker modules. ```Rust let trk = mk_tracker(rt); let acct = trk.new_account(None).unwrap(); let itrk = ItemTracker::new_tracker(); Setup { dtp, trk, acct, itrk, } ``` -------------------------------- ### Rust: Implement Introduction Point Status Methods Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_establish Implements methods for the `IptStatus` struct to manage the state of an introduction point. Functions include `note_open` for successful connections, `note_attempt` for recording connection attempts, `note_error` for recording errors and determining faultiness, `new` for creating a new uninitialized status, and `new_terminated` for creating a status representing a shut down point. Dependencies include `IptStatusStatus`, `GoodIptDetails`, `IptEstablisherError`, `IptError`, `Instant`, and `FAULY_IPT_THRESHOLD`. ```rust impl IptStatus { /// Record that we have successfully connected to an introduction point. fn note_open(&mut self, ipt_details: GoodIptDetails) { self.status = IptStatusStatus::Good(ipt_details); self.failing_since = None; } /// Record that we are trying to connect to an introduction point. fn note_attempt(&mut self) { use IptStatusStatus::*; self.status = match &self.status { Establishing | Good(..) => Establishing, Faulty(e) => Faulty(e.clone()), // We don't change status if we think we're broken. } } /// Record that an error has occurred. fn note_error(&mut self, err: &IptEstablisherError, now: Instant) { use IptStatusStatus::*; let failing_since = *self.failing_since.get_or_insert(now); #[allow(clippy::if_same_then_else)] if let Some(ipt_err) = err.ipt_failure() { // This error always indicates a faulty introduction point. self.status = Faulty(Some(ipt_err.clone())); } else if now.saturating_duration_since(failing_since) >= FAULTY_IPT_THRESHOLD { // This introduction point has gone too long without a success. self.status = Faulty(Some(IptError::Timeout)); } } /// Return an `IptStatus` representing an establisher that has not yet taken /// any action. fn new() -> Self { Self { status: IptStatusStatus::Establishing, wants_to_retire: Ok(()), failing_since: None, } } /// Produce an `IptStatus` representing a shut down or crashed establisher fn new_terminated() -> Self { IptStatus { status: IptStatusStatus::Faulty(None), // If we're broken, we simply tell the manager that that is the case. // It will decide for itself whether it wants to replace us. wants_to_retire: Ok(()), failing_since: None, } } } ``` -------------------------------- ### Configure Tor bridge with redundant transport configuration Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/arti-client/src/config This configuration demonstrates a Tor bridge setup where a non-pluggable transport bridge is defined, but a redundant transports section is also present. The bridges are disabled in this example. ```toml # One non-PT bridge with a redundant transports section [bridges] enabled = false bridges = [ ``` -------------------------------- ### Test Get or Generate Key in Key Manager Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-keymgr/src/mgr Initializes a Key Manager with multiple keystores and prepares for testing the get_or_generate functionality. This setup involves defining primary and secondary keystores for subsequent operations. ```rust #[test] fn get_or_generate() { let mut rng = FakeEntropicRng(testing_rng()); let mut builder = KeyMgrBuilder::default().primary_store(Box::::default()); builder .secondary_stores() .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]); ``` -------------------------------- ### Get TimePeriod Epoch Offset in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hscrypto/src/time Retrieves the offset of the time period from the epoch in seconds. This value is a `u32` and represents a specific point in time relative to a defined epoch, distinct from the start of the time period itself. ```Rust /// Return our offset from the epoch, in seconds. /// /// Note that this is *not* the start of the TP. /// See `TimePeriod::from_parts`. pub fn epoch_offset_in_sec(&self) -> u32 { self.epoch_offset_in_sec } ``` -------------------------------- ### Setup Pending Channel Entry in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-chanmgr/src/mgr/state The `setup_launch` function is a helper that initializes the necessary components for a pending channel. It creates a oneshot channel for communication, a shared receiver for the pending state, a unique identifier, and packages them into a `PendingEntry`. ```rust fn setup_launch(ids: RelayIds) -> (PendingEntry, Sending, UniqPendingChanId) { let (snd, rcv) = oneshot::channel(); let pending = rcv.shared(); let unique_id = UniqPendingChanId::new(); let entry = PendingEntry { ids, pending, unique_id, }; (entry, snd, unique_id) } ``` -------------------------------- ### Rust TimerangeBound: Get Bounds Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-checkable/src/timed The `bounds` method returns the start and end time bounds of the TimerangeBound as an `Option` tuple. This allows external code to inspect the time range associated with the object without consuming the TimerangeBound. ```rust pub fn bounds(&self) -> (Option, Option) { (self.start, self.end) } ``` -------------------------------- ### Implement Launchable for ForLaunch Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-hsservice/src/lib Implements the `Launchable` trait for the `ForLaunch` struct. This method orchestrates the launch of the introduction point manager, the publisher, and the proof-of-work manager, ensuring all necessary background tasks and services are started correctly. ```rust impl Launchable for ForLaunch { fn launch(self: Box) -> Result<(), StartupError> { self.ipt_mgr.launch_background_tasks(self.ipt_mgr_view)?; self.publisher.launch()?; self.pow_manager.launch()?; Ok(()) } } ``` -------------------------------- ### Parse Server Transport Failed Messages in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-ptmgr/src/ipc Illustrates parsing `PtMessage::ServerTransportFailed` in Rust, which signifies an error during server-side transport setup. This example shows a specific failure message related to transport availability. ```rust assert_eq!( "SMETHOD-ERROR trebuchet no cows available".parse(), Ok(PtMessage::ServerTransportFailed { transport: "trebuchet".parse().unwrap(), message: "no cows available".to_string() }) ); ``` -------------------------------- ### Prepare IPT for Publishing (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-hsservice/src/ipt_mgr Constructs the necessary information for publishing an Introduction Point (IPT). This function takes 'GoodIptDetails' and returns an 'Ipt' structure suitable for network documentation, mapping potential errors to an internal 'Bug' type. ```rust /// Construct the information needed by the publisher for this intro point fn for_publish(&self, details: &ipt_establish::GoodIptDetails) -> Result { let k_sid: &ed25519::Keypair = (*self.k_sid).as_ref(); tor_netdoc::doc::hsdesc::IntroPointDesc::builder() .link_specifiers(details.link_specifiers.clone()) .ipt_kp_ntor(details.ipt_kp_ntor) .kp_hs_ipt_sid(k_sid.verifying_key().into()) .kp_hss_ntor(self.k_hss_ntor.public().clone()) .build() .map_err(into_internal!("failed to construct IntroPointDesc")) } ``` -------------------------------- ### Get Item Offset in a String in Rust Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-netdoc/src/parse/tokenize Calculates the starting byte offset of an Item's keyword within a given string `s`. Returns `None` if the item's keyword is not found within `s`. ```rust pub(crate) fn offset_in(&self, s: &str) -> Option { crate::util::str::str_offset(s, self.kwd_str) } ``` -------------------------------- ### Rate Limiter Test Setup Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-proto/src/util/token_bucket/writer This Rust code sets up a test environment for the rate limiter using `tor_rtmock::MockRuntime`. It initializes a mock runtime and starts an asynchronous test function, including setting an initial time reference. ```rust #[test] fn writer() { tor_rtmock::MockRuntime::test_with_various(|rt| async move { let start = rt.now(); // increases 10 tokens/second (one every 100 ms) let config = TokenBucketConfig { rate: 10, ``` -------------------------------- ### Configure and Launch Channel Builder (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-proto/src/channel Demonstrates the usage of `ChannelBuilder` to configure and launch a client channel. It sets the declared network method to direct connection and initializes the builder with a TLS message buffer and a runtime. The `launch_client` method is called to initiate the channel setup. ```Rust #[test] fn chanbuilder() { let rt = PreferredRuntime::create().unwrap(); let mut builder = ChannelBuilder::default(); builder.set_declared_method(tor_linkspec::ChannelMethod::Direct(vec![ "127.0.0.1:9001".parse().unwrap(), ])); let tls = MsgBuf::new(&b""[..]); let _outbound = builder.launch_client(tls, rt, fake_mq()); } ``` -------------------------------- ### Initialize and Get Keys from Key Store (Rust) Source: https://tpo.pages.torproject.net/core/arti/coverage/all/crates/tor-keymgr/src/keystore/arti Demonstrates the initialization of a key store and the retrieval of keys using the `assert_found!` macro. It tests scenarios for both empty and pre-populated key stores, verifying that keys are correctly found or not found as expected. It also checks the state of the key store list after operations. ```Rust #[test] fn get() { // Initialize an empty key store let (key_store, _keystore_dir) = init_keystore(false); let mut expected_arti_paths = Vec::new(); // Not found assert_found!( key_store, &TestSpecifier::default(), &KeyType::Ed25519Keypair, false ); assert!(key_store.list().unwrap().is_empty()); // Initialize a key store with some test keys let (key_store, _keystore_dir) = init_keystore(true); expected_arti_paths.push(TestSpecifier::default().arti_path().unwrap()); // Found! assert_found!( key_store, &TestSpecifier::default(), &KeyType::Ed25519Keypair, true ); assert_contains_arti_paths!(expected_arti_paths, key_store.list().unwrap()); } ``` -------------------------------- ### Get Item Offset within a String Source: https://tpo.pages.torproject.net/core/arti/coverage/unit/crates/tor-netdoc/src/parse/tokenize Calculates the starting byte offset of an Item within a given string `s`. It uses a utility function `str_offset` for this calculation. Returns `None` if the item's keyword string is not found within `s`. ```Rust pub(crate) fn offset_in(&self, s: &str) -> Option { crate::util::str::str_offset(s, self.kwd_str) } ```