Init
This commit is contained in:
81
TorWebClient/TorClient/Events/Enumerators/Event.cs
Normal file
81
TorWebClient/TorClient/Events/Enumerators/Event.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Tor.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// An enumerator containing the list of events which can be monitored in the tor service.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum Event : int
|
||||
{
|
||||
/// <summary>
|
||||
/// The event was unrecognised.
|
||||
/// </summary>
|
||||
[Description(null)]
|
||||
Unknown = 0x000,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when the circuit status is changed.
|
||||
/// </summary>
|
||||
[Description("CIRC")]
|
||||
Circuits = 0x001,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when a stream status is changed.
|
||||
/// </summary>
|
||||
[Description("STREAM")]
|
||||
Streams = 0x002,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when an OR connection status is changed.
|
||||
/// </summary>
|
||||
[Description("ORCONN")]
|
||||
ORConnections = 0x004,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when the bandwidth used within the last second has changed.
|
||||
/// </summary>
|
||||
[Description("BW")]
|
||||
Bandwidth = 0x008,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when the value of a configuration has changed.
|
||||
/// </summary>
|
||||
[Description("CONF_CHANGED")]
|
||||
ConfigChanged = 0x010,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when a debug message is produced.
|
||||
/// </summary>
|
||||
[Description("DEBUG")]
|
||||
LogDebug = 0x020,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when an information message is produced.
|
||||
/// </summary>
|
||||
[Description("INFO")]
|
||||
LogInfo = 0x040,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when a notice message is produced.
|
||||
/// </summary>
|
||||
[Description("NOTICE")]
|
||||
LogNotice = 0x080,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when a warning message is produced.
|
||||
/// </summary>
|
||||
[Description("WARN")]
|
||||
LogWarn = 0x100,
|
||||
|
||||
/// <summary>
|
||||
/// An event raised when an error message is produced.
|
||||
/// </summary>
|
||||
[Description("ERR")]
|
||||
LogError = 0x200,
|
||||
}
|
||||
}
|
||||
240
TorWebClient/TorClient/Events/Enumerators/Events.cs
Normal file
240
TorWebClient/TorClient/Events/Enumerators/Events.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using Tor.Helpers;
|
||||
|
||||
namespace Tor.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// A class which provides monitoring for events occuring within the tor service.
|
||||
/// </summary>
|
||||
public sealed class Events : IDisposable
|
||||
{
|
||||
private readonly static string EOL = "\r\n";
|
||||
|
||||
private readonly Client client;
|
||||
private readonly List<Event> events;
|
||||
private readonly object synchronize;
|
||||
|
||||
private StringBuilder backlog;
|
||||
private byte[] buffer;
|
||||
private volatile bool disposed;
|
||||
private volatile bool enabled;
|
||||
private Socket socket;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Events"/> class.
|
||||
/// </summary>
|
||||
/// <param name="client">The client for which this object instance belongs.</param>
|
||||
internal Events(Client client)
|
||||
{
|
||||
this.backlog = new StringBuilder();
|
||||
this.buffer = new byte[256];
|
||||
this.client = client;
|
||||
this.disposed = false;
|
||||
this.enabled = false;
|
||||
this.events = new List<Event>();
|
||||
this.socket = null;
|
||||
this.synchronize = new object();
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the client should monitor for interested events within the tor service.
|
||||
/// </summary>
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region System.IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region System.Net.Sockets.Socket
|
||||
|
||||
/// <summary>
|
||||
/// Called when the socket connects to the control port.
|
||||
/// </summary>
|
||||
/// <param name="ar">The asynchronous result object for the asynchronous method.</param>
|
||||
private void OnSocketConnect(IAsyncResult ar)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.EndConnect(ar);
|
||||
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, OnSocketReceive, null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the socket receives data from the control port.
|
||||
/// </summary>
|
||||
/// <param name="ar">The asynchronous result object for the asynchronous method.</param>
|
||||
private void OnSocketReceive(IAsyncResult ar)
|
||||
{
|
||||
try
|
||||
{
|
||||
int received = socket.EndReceive(ar);
|
||||
|
||||
if (received <= 0)
|
||||
return;
|
||||
|
||||
SetEventResponse(Encoding.ASCII.GetString(buffer, 0, received));
|
||||
|
||||
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, OnSocketReceive, null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the socket completes sending a list of interested events.
|
||||
/// </summary>
|
||||
/// <param name="ar">The asynchronous result object for the asynchronous method.</param>
|
||||
private void OnSocketSendEvents(IAsyncResult ar)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.EndSend(ar);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Signals to the control connection to begin monitoring for interested events.
|
||||
/// </summary>
|
||||
private void SetEvents()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException("this");
|
||||
|
||||
lock (synchronize)
|
||||
{
|
||||
if (socket == null || !enabled)
|
||||
return;
|
||||
|
||||
StringBuilder builder = new StringBuilder("SETEVENTS");
|
||||
|
||||
foreach (Event interested in events)
|
||||
{
|
||||
string name = ReflectionHelper.GetDescription<Event>(interested);
|
||||
|
||||
builder.Append(' ');
|
||||
builder.Append(name);
|
||||
}
|
||||
|
||||
string command = builder.Append("\r\n").ToString();
|
||||
byte[] buffer = Encoding.ASCII.GetBytes(command);
|
||||
|
||||
socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnSocketSendEvents, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current response data received from the control port, which is event information.
|
||||
/// </summary>
|
||||
/// <param name="response">The response received from the control port.</param>
|
||||
private void SetEventResponse(string response)
|
||||
{
|
||||
if (response == null)
|
||||
throw new ArgumentNullException("response");
|
||||
if (response.Length == 0)
|
||||
return;
|
||||
|
||||
if (backlog.Length > 0)
|
||||
response = new StringBuilder(backlog.Length + response.Length).Append(backlog).Append(response).ToString();
|
||||
|
||||
int index = 0;
|
||||
int length = response.Length;
|
||||
|
||||
if (response.Contains(EOL))
|
||||
{
|
||||
for (int next = response.IndexOf(EOL); 0 <= next; next = response.IndexOf(EOL, next))
|
||||
{
|
||||
if (next + EOL.Length == length)
|
||||
{
|
||||
index = length;
|
||||
break;
|
||||
}
|
||||
|
||||
string line = response.Substring(index, next);
|
||||
|
||||
index = next + EOL.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (backlog.Length > 0 && index == length)
|
||||
backlog = new StringBuilder();
|
||||
|
||||
if (index < length)
|
||||
backlog = new StringBuilder(response.Substring(index));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the process of monitoring for events by launching a control connection.
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException("this");
|
||||
|
||||
lock (synchronize)
|
||||
{
|
||||
if (socket != null || !enabled)
|
||||
return;
|
||||
|
||||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
|
||||
socket.BeginConnect("127.0.0.1", client.Configuration.ControlPort, OnSocketConnect, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down the listener socket and releases all resources associated with it.
|
||||
/// </summary>
|
||||
private void Shutdown()
|
||||
{
|
||||
lock (synchronize)
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
}
|
||||
catch { }
|
||||
|
||||
socket.Dispose();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user