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)
{
}
}
}