using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using Tor.Helpers; using System.ComponentModel; namespace Tor.Controller { /// /// A class containing the command to retrieve router status information. /// internal sealed class GetRouterStatusCommand : Command { private string identity; /// /// Initializes a new instance of the class. /// public GetRouterStatusCommand() : this(null) { } /// /// Initializes a new instance of the class. /// /// The router identity to retrieve status information for. public GetRouterStatusCommand(string identity) { this.identity = identity; } #region Properties /// /// Gets or sets the identity of the router. /// public string Identity { get { return identity; } } #endregion #region Tor.Controller.Command<> /// /// Dispatches the command to the client control port and produces a response result. /// /// /// /// A object instance containing the response data. /// 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(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 } /// /// A class containing the response information from a getinfo ns/id/? command. /// internal sealed class GetRouterStatusResponse : Response { private readonly Router router; /// /// Initializes a new instance of the class. /// /// A value indicating whether the command was received and processed successfully. /// The router information retrieved from the command. public GetRouterStatusResponse(bool success, Router router) : base(success) { this.router = router; } #region Properties /// /// Gets the router information retrieved from the control connection. /// public Router Router { get { return router; } } #endregion } }