using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; using Tor.Controller; using System.Net; using Tor.Helpers; using System.ComponentModel; namespace Tor { /// /// A class containing information regarding a circuit within the tor service. /// public sealed class Circuit : MarshalByRefObject { private readonly Client client; private readonly int id; private readonly object synchronize; private CircuitBuildFlags buildFlags; private CircuitHSState hsState; private List paths; private CircuitPurpose purpose; private CircuitReason reason; private RouterCollection routers; private CircuitStatus status; private DateTime timeCreated; /// /// Initializes a new instance of the class. /// /// The client for which the circuit belongs. /// The unique identifier of the circuit within the tor session. internal Circuit(Client client, int id) { this.buildFlags = CircuitBuildFlags.None; this.client = client; this.hsState = CircuitHSState.None; this.id = id; this.paths = new List(); this.purpose = CircuitPurpose.None; this.reason = CircuitReason.None; this.synchronize = new object(); this.timeCreated = DateTime.MinValue; } #region Properties /// /// Gets the build flags associated with the circuit. /// public CircuitBuildFlags BuildFlags { get { return buildFlags; } internal set { buildFlags = value; } } /// /// Gets the hidden-service state of the circuit. /// public CircuitHSState HSState { get { return hsState; } internal set { hsState = value; } } /// /// Gets the unique identifier of the circuit in the tor session. /// public int ID { get { return id; } } /// /// Gets the purpose of the circuit. /// public CircuitPurpose Purpose { get { return purpose; } internal set { purpose = value; } } /// /// Gets the reason associated with the circuit, usually assigned upon closed or failed events. /// public CircuitReason Reason { get { return reason; } internal set { reason = value; } } /// /// Gets the routers associated with the circuit. /// public RouterCollection Routers { get { return routers; } } /// /// Gets the status of the circuit. /// public CircuitStatus Status { get { return status; } internal set { status = value; } } /// /// Gets the date and time the circuit was created. /// public DateTime TimeCreated { get { return timeCreated; } internal set { timeCreated = value; } } /// /// Gets or sets the collection containing the paths associated with the circuit. /// internal List Paths { get { lock (synchronize) return paths; } set { lock (synchronize) paths = value; } } #endregion /// /// Sends a request to the associated tor client to close the circuit. /// /// true if the circuit is closed successfully; otherwise, false. public bool Close() { return client.Controller.CloseCircuit(this); } /// /// Sends a request to the associated tor client to extend the circuit. /// /// The list of identities or nicknames to extend onto this circuit. /// true if the circuit is extended successfully; otherwise, false. public bool Extend(params string[] routers) { return client.Controller.ExtendCircuit(this, routers); } /// /// Sends a request to the associated tor client to extend the circuit. /// /// The list of routers to extend onto this circuit. /// true if the circuit is extended successfully; otherwise, false. public bool Extend(params Router[] routers) { string[] nicknames = new string[routers.Length]; for (int i = 0, length = routers.Length; i < length; i++) nicknames[i] = routers[i].Nickname; return client.Controller.ExtendCircuit(this, nicknames); } /// /// Gets the routers associated with the circuit. /// /// A object instance. internal RouterCollection GetRouters() { lock (synchronize) { List routers = new List(); if (paths == null || paths.Count == 0) { this.routers = new RouterCollection(routers); return this.routers; } foreach (string path in paths) { string trimmed = path; if (trimmed == null) continue; if (trimmed.StartsWith("$")) trimmed = trimmed.Substring(1); if (trimmed.Contains("~")) trimmed = trimmed.Substring(0, trimmed.IndexOf("~")); if (string.IsNullOrWhiteSpace(trimmed)) continue; GetRouterStatusCommand command = new GetRouterStatusCommand(trimmed); GetRouterStatusResponse response = command.Dispatch(client); if (response.Success && response.Router != null) routers.Add(response.Router); } this.routers = new RouterCollection(routers); return this.routers; } } } /// /// A class containing a read-only collection of objects. /// public sealed class CircuitCollection : ReadOnlyCollection { /// /// Initializes a new instance of the class. /// /// The list of circuits. internal CircuitCollection(IList list) : base(list) { } } }