This commit is contained in:
2024-02-23 06:57:07 -05:00
commit 8fb7082f56
104 changed files with 284139 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to close an existing circuit.
/// </summary>
internal sealed class CloseCircuitCommand : Command<Response>
{
private readonly Circuit circuit;
/// <summary>
/// Initializes a new instance of the <see cref="CloseCircuitCommand"/> class.
/// </summary>
/// <param name="circuit">The circuit which should be closed.</param>
public CloseCircuitCommand(Circuit circuit)
{
this.circuit = circuit;
}
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (circuit == null || circuit.Status == CircuitStatus.Closed)
return new Response(false);
if (connection.Write("closecircuit {0}", circuit.ID))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tor.Helpers;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to close an existing stream.
/// </summary>
internal sealed class CloseStreamCommand : Command<Response>
{
private readonly StreamReason reason;
private readonly Stream stream;
/// <summary>
/// Initializes a new instance of the <see cref="CloseStreamCommand"/> class.
/// </summary>
/// <param name="stream">The stream which should be closed.</param>
/// <param name="reason">The reason for the stream being closed.</param>
public CloseStreamCommand(Stream stream, StreamReason reason)
{
this.reason = reason;
this.stream = stream;
}
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (stream == null || stream.ID <= 0)
return new Response(false);
if (stream.Status == StreamStatus.Failed || stream.Status == StreamStatus.Closed)
return new Response(false);
if (reason == StreamReason.None || reason == StreamReason.PrivateAddr || reason == StreamReason.End)
return new Response(false);
if (connection.Write("closestream {0} {1}", stream.ID, (int)reason))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tor.Helpers;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to create a new circuit.
/// </summary>
internal sealed class CreateCircuitCommand : Command<CreateCircuitResponse>
{
private readonly List<string> routers;
/// <summary>
/// Initializes a new instance of the <see cref="CreateCircuitCommand"/> class.
/// </summary>
public CreateCircuitCommand()
{
this.routers = new List<string>();
}
/// <summary>
/// Initializes a new instance of the <see cref="CreateCircuitCommand"/> class.
/// </summary>
/// <param name="routers">The collection of routers which should be part of this circuit.</param>
public CreateCircuitCommand(IEnumerable<string> routers)
{
this.routers = new List<string>(routers);
}
#region Properties
/// <summary>
/// Gets a collection containing the list of routers which should be comprise this circuit.
/// </summary>
public List<string> Routers
{
get { return routers; }
}
#endregion
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override CreateCircuitResponse Dispatch(Connection connection)
{
StringBuilder builder = new StringBuilder("extendcircuit 0");
foreach (string router in routers)
{
builder.Append(' ');
builder.Append(router);
}
if (connection.Write(builder.ToString()))
{
ConnectionResponse response = connection.Read();
if (!response.Success)
return new CreateCircuitResponse(false, -1);
string[] parts = StringHelper.GetAll(response.Responses[0], ' ');
if (parts.Length < 2 || !"extended".Equals(parts[0], StringComparison.CurrentCultureIgnoreCase))
return new CreateCircuitResponse(false, -1);
int circuitID;
if (!int.TryParse(parts[1], out circuitID))
return new CreateCircuitResponse(false, -1);
return new CreateCircuitResponse(true, circuitID);
}
return new CreateCircuitResponse(false, -1);
}
#endregion
}
/// <summary>
/// A class containing the response information from a <c>extendcircuit 0</c> command.
/// </summary>
internal sealed class CreateCircuitResponse : Response
{
private readonly int circuitID;
/// <summary>
/// Initializes a new instance of the <see cref="CreateCircuitResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
/// <param name="circuitID">The unique circuit identifier within the tor service.</param>
public CreateCircuitResponse(bool success, int circuitID) : base(success)
{
this.circuitID = circuitID;
}
#region Properties
/// <summary>
/// Gets the unique circuit identifier.
/// </summary>
public int CircuitID
{
get { return circuitID; }
}
#endregion
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command responsible for extending a circuit.
/// </summary>
internal class ExtendCircuitCommand : Command<Response>
{
private readonly Circuit circuit;
private readonly List<string> routers;
/// <summary>
/// Initializes a new instance of the <see cref="ExtendCircuitCommand"/> class.
/// </summary>
/// <param name="circuit">The circuit which should be the target of extension. A <c>null</c> value indicates a new circuit.</param>
public ExtendCircuitCommand(Circuit circuit)
{
this.circuit = circuit;
this.routers = new List<string>();
}
#region Properties
/// <summary>
/// Gets a collection containing the list of routers which should be extended onto this circuit.
/// </summary>
public List<string> Routers
{
get { return routers; }
}
#endregion
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (routers.Count == 0)
return new Response(false);
int circuitID = 0;
if (circuit != null)
circuitID = circuit.ID;
StringBuilder builder = new StringBuilder("extendcircuit");
builder.AppendFormat(" {0}", circuitID);
foreach (string router in routers)
builder.AppendFormat(" {0}", router);
if (connection.Write(builder.ToString()))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Tor.Helpers;
using System.ComponentModel;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to retrieve all relevant router statuses.
/// </summary>
internal sealed class GetAllRouterStatusCommand : Command<GetAllRouterStatusResponse>
{
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override GetAllRouterStatusResponse Dispatch(Connection connection)
{
if (connection.Write("getinfo ns/all"))
{
ConnectionResponse response = connection.Read();
if (!response.Success || !response.Responses[0].StartsWith("ns/all", StringComparison.CurrentCultureIgnoreCase))
return new GetAllRouterStatusResponse(false);
List<Router> routers = new List<Router>();
Router router = null;
for (int i = 1, count = response.Responses.Count; i < count; i++)
{
string line = response.Responses[i].Trim();
if (string.IsNullOrWhiteSpace(line) || ".".Equals(line))
continue;
if (line.StartsWith("r"))
{
if (router != null)
{
routers.Add(router);
router = null;
}
string[] values = line.Split(' ');
if (values.Length < 9)
continue;
DateTime publication = DateTime.MinValue;
if (!DateTime.TryParse(string.Format("{0} {1}", values[4], values[5]), out publication))
publication = DateTime.MinValue;
int orPort = 0;
if (!int.TryParse(values[7], out orPort))
orPort = 0;
int dirPort = 0;
if (!int.TryParse(values[8], out dirPort))
dirPort = 0;
IPAddress ipAddress = null;
if (!IPAddress.TryParse(values[6], out ipAddress))
ipAddress = null;
router = new Router();
router.Digest = values[3];
router.DIRPort = dirPort;
router.Identity = values[2];
router.IPAddress = ipAddress;
router.Nickname = values[1];
router.ORPort = orPort;
router.Publication = publication;
continue;
}
if (line.StartsWith("s") && router != null)
{
string[] values = line.Split(' ');
for (int j = 1, length = values.Length; j < length; j++)
{
RouterFlags flag = ReflectionHelper.GetEnumerator<RouterFlags, DescriptionAttribute>(attr => values[j].Equals(attr.Description, StringComparison.CurrentCultureIgnoreCase));
if (flag != RouterFlags.None)
router.Flags |= flag;
}
continue;
}
if (line.StartsWith("w") && router != null)
{
string[] values = line.Split(' ');
if (values.Length < 2 || !values[1].StartsWith("bandwidth=", StringComparison.CurrentCultureIgnoreCase))
continue;
string[] value = values[1].Split(new[] { '=' }, 2);
if (value.Length < 2)
continue;
int bandwidth;
if (int.TryParse(value[1].Trim(), out bandwidth))
router.Bandwidth = new Bytes((double)bandwidth, Bits.KB).Normalize();
}
}
if (router != null)
{
routers.Add(router);
router = null;
}
return new GetAllRouterStatusResponse(true, routers);
}
return new GetAllRouterStatusResponse(false);
}
#endregion
}
/// <summary>
/// A class containing the response information from a <c>getinfo ns/all</c> command.
/// </summary>
internal sealed class GetAllRouterStatusResponse : Response
{
private readonly RouterCollection routers;
/// <summary>
/// Initializes a new instance of the <see cref="GetAllRouterStatusResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
public GetAllRouterStatusResponse(bool success) : base(success)
{
this.routers = null;
}
/// <summary>
/// Initializes a new instance of the <see cref="GetAllRouterStatusResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
/// <param name="routers">The collection of routers.</param>
public GetAllRouterStatusResponse(bool success, IList<Router> routers) : base(success)
{
this.routers = new RouterCollection(routers);
}
#region Properties
/// <summary>
/// Gets a read-only collection containing the router status information.
/// </summary>
public RouterCollection Routers
{
get { return routers; }
}
#endregion
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to retrieve configuration values from a client.
/// </summary>
internal sealed class GetConfCommand : Command<GetConfResponse>
{
private readonly ReadOnlyCollection<string> configurations;
/// <summary>
/// Initializes a new instance of the <see cref="GetConfCommand"/> class.
/// </summary>
/// <param name="configurations">The configurations which should be retrieved from the tor application.</param>
public GetConfCommand(List<string> configurations)
{
this.configurations = configurations.AsReadOnly();
}
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override GetConfResponse Dispatch(Connection connection)
{
StringBuilder builder = new StringBuilder("getconf");
foreach (string name in configurations)
{
builder.Append(' ');
builder.Append(name);
}
if (connection.Write(builder.ToString()))
{
ConnectionResponse response = connection.Read();
if (!response.Success)
return new GetConfResponse(false, null);
ResponsePairs values = new ResponsePairs(response.Responses.Count);
foreach (string value in response.Responses)
{
string[] parts = value.Split(new[] { '=' }, 2);
string name = parts[0].Trim();
if (parts.Length != 2)
values[name] = null;
else
values[name] = parts[1].Trim();
}
return new GetConfResponse(true, values);
}
return new GetConfResponse(false, null);
}
#endregion
}
/// <summary>
/// A class containing a collection of configuration value responses.
/// </summary>
internal sealed class GetConfResponse : Response
{
private readonly ResponsePairs values;
/// <summary>
/// Initializes a new instance of the <see cref="GetConfResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
/// <param name="values">The values received from the tor control connection.</param>
public GetConfResponse(bool success, ResponsePairs values) : base(success)
{
this.values = values;
}
#region Properties
/// <summary>
/// Gets the values received from the control connection.
/// </summary>
public ResponsePairs Values
{
get { return values; }
}
#endregion
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to get network information from the tor service.
/// </summary>
internal sealed class GetInfoCommand : Command<GetInfoResponse>
{
private string request;
/// <summary>
/// Initializes a new instance of the <see cref="GetInfoCommand"/> class.
/// </summary>
public GetInfoCommand()
{
this.request = null;
}
/// <summary>
/// Initializes a new instance of the <see cref="GetInfoCommand"/> class.
/// </summary>
/// <param name="request">The request to send with the <c>getinfo</c> command.</param>
public GetInfoCommand(string request)
{
this.request = request;
}
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override GetInfoResponse Dispatch(Connection connection)
{
if (request == null)
return new GetInfoResponse(false);
if (connection.Write("getinfo {0}", request))
{
ConnectionResponse response = connection.Read();
if (!response.Success || !response.Responses[0].StartsWith(request, StringComparison.CurrentCultureIgnoreCase))
return new GetInfoResponse(false);
List<string> values = new List<string>(response.Responses.Count);
if (response.Responses.Count == 1)
{
string[] parts = response.Responses[0].Split(new[] { '=' }, 2);
values.Add(parts.Length == 1 ? null : parts[1]);
}
else
{
for (int i = 1; i < response.Responses.Count; i++)
{
if (".".Equals(response.Responses[i]))
break;
values.Add(response.Responses[i]);
}
}
return new GetInfoResponse(true, values.AsReadOnly());
}
return new GetInfoResponse(false);
}
#endregion
}
/// <summary>
/// A class containing the response values for a <c>getinfo</c> command.
/// </summary>
internal sealed class GetInfoResponse : Response
{
private readonly ReadOnlyCollection<string> values;
/// <summary>
/// Initializes a new instance of the <see cref="GetInfoResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
public GetInfoResponse(bool success) : base(success)
{
this.values = new List<string>().AsReadOnly();
}
/// <summary>
/// Initializes a new instance of the <see cref="GetInfoResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
/// <param name="values">The values returned from the control connection.</param>
public GetInfoResponse(bool success, ReadOnlyCollection<string> values) : base(success)
{
this.values = values;
}
#region Properties
/// <summary>
/// Gets a read-only collection of the values returned from the control connection.
/// </summary>
public ReadOnlyCollection<string> Values
{
get { return values; }
}
#endregion
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Tor.Helpers;
using System.ComponentModel;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to retrieve router status information.
/// </summary>
internal sealed class GetRouterStatusCommand : Command<GetRouterStatusResponse>
{
private string identity;
/// <summary>
/// Initializes a new instance of the <see cref="GetRouterStatusCommand"/> class.
/// </summary>
public GetRouterStatusCommand() : this(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GetRouterStatusCommand"/> class.
/// </summary>
/// <param name="identity">The router identity to retrieve status information for.</param>
public GetRouterStatusCommand(string identity)
{
this.identity = identity;
}
#region Properties
/// <summary>
/// Gets or sets the identity of the router.
/// </summary>
public string Identity
{
get { return identity; }
}
#endregion
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection"></param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override GetRouterStatusResponse Dispatch(Connection connection)
{
if (identity == null)
return new GetRouterStatusResponse(false, null);
string request = string.Format("ns/id/{0}", identity);
if (connection.Write("getinfo {0}", request))
{
ConnectionResponse response = connection.Read();
if (!response.Success || !response.Responses[0].StartsWith(request, StringComparison.CurrentCultureIgnoreCase))
return new GetRouterStatusResponse(false, null);
Router router = null;
foreach (string line in response.Responses)
{
string stripped = line.Trim();
if (string.IsNullOrWhiteSpace(stripped))
continue;
if (stripped.StartsWith("r"))
{
string[] values = stripped.Split(' ');
if (values.Length < 9)
continue;
DateTime publication = DateTime.MinValue;
if (!DateTime.TryParse(string.Format("{0} {1}", values[4], values[5]), out publication))
publication = DateTime.MinValue;
int orPort = 0;
if (!int.TryParse(values[7], out orPort))
orPort = 0;
int dirPort = 0;
if (!int.TryParse(values[8], out dirPort))
dirPort = 0;
IPAddress ipAddress = null;
if (!IPAddress.TryParse(values[6], out ipAddress))
ipAddress = null;
router = new Router();
router.Digest = values[3];
router.DIRPort = dirPort;
router.Identity = values[2];
router.IPAddress = ipAddress;
router.Nickname = values[1];
router.ORPort = orPort;
router.Publication = publication;
continue;
}
if (stripped.StartsWith("s") && router != null)
{
string[] values = stripped.Split(' ');
for (int i = 1, length = values.Length; i < length; i++)
{
RouterFlags flag = ReflectionHelper.GetEnumerator<RouterFlags, DescriptionAttribute>(attr => values[i].Equals(attr.Description, StringComparison.CurrentCultureIgnoreCase));
if (flag != RouterFlags.None)
router.Flags |= flag;
}
continue;
}
if (stripped.StartsWith("w") && router != null)
{
string[] values = stripped.Split(' ');
if (values.Length < 2 || !values[1].StartsWith("bandwidth=", StringComparison.CurrentCultureIgnoreCase))
continue;
string[] value = values[1].Split(new[] { '=' }, 2);
if (value.Length < 2)
continue;
int bandwidth;
if (int.TryParse(value[1].Trim(), out bandwidth))
router.Bandwidth = new Bytes((double)bandwidth, Bits.KB).Normalize();
}
}
return new GetRouterStatusResponse(true, router);
}
return new GetRouterStatusResponse(false, null);
}
#endregion
}
/// <summary>
/// A class containing the response information from a <c>getinfo ns/id/?</c> command.
/// </summary>
internal sealed class GetRouterStatusResponse : Response
{
private readonly Router router;
/// <summary>
/// Initializes a new instance of the <see cref="GetRouterStatusResponse"/> class.
/// </summary>
/// <param name="success">A value indicating whether the command was received and processed successfully.</param>
/// <param name="router">The router information retrieved from the command.</param>
public GetRouterStatusResponse(bool success, Router router) : base(success)
{
this.router = router;
}
#region Properties
/// <summary>
/// Gets the router information retrieved from the control connection.
/// </summary>
public Router Router
{
get { return router; }
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to save the configuration values in memory, to the <c>torrc</c> document.
/// </summary>
internal sealed class SaveConfCommand : Command<Response>
{
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (connection.Write("saveconf"))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command used to set the value of a configuration.
/// </summary>
internal sealed class SetConfCommand : Command<Response>
{
private readonly string name;
private readonly string value;
/// <summary>
/// Initializes a new instance of the <see cref="SetConfCommand"/> class.
/// </summary>
/// <param name="name">The name of the configuration to set.</param>
/// <param name="value">The value of the configuration.</param>
public SetConfCommand(string name, string value)
{
this.name = name;
this.value = value;
}
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (name == null || value == null)
return new Response(false);
if (connection.Write("setconf {0}={1}", name, value.Contains(" ") ? string.Format("\"{0}\"", value) : value))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to clear client-side cached IP addresses for hostnames.
/// </summary>
internal sealed class SignalClearDNSCacheCommand : Command<Response>
{
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (connection.Write("signal cleardnscache"))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to signal an immediate halt in the tor process.
/// </summary>
internal sealed class SignalHaltCommand : Command<Response>
{
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (connection.Write("signal halt"))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tor.Controller
{
/// <summary>
/// A class containing the command to generate a new circuit.
/// </summary>
internal sealed class SignalNewCircuitCommand : Command<Response>
{
#region Tor.Controller.Command<>
/// <summary>
/// Dispatches the command to the client control port and produces a <typeparamref name="T" /> response result.
/// </summary>
/// <param name="connection">The control connection where the command should be dispatched.</param>
/// <returns>
/// A <typeparamref name="T" /> object instance containing the response data.
/// </returns>
protected override Response Dispatch(Connection connection)
{
if (connection.Write("signal newnym"))
{
ConnectionResponse response = connection.Read();
return new Response(response.Success);
}
return new Response(false);
}
#endregion
}
}