diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 6641d0cf..1d99f102 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -36,6 +36,7 @@ + diff --git a/MinecraftClient/Proxy/Handlers/EventArgs/CreateConnectionAsyncCompletedEventArgs.cs b/MinecraftClient/Proxy/Handlers/EventArgs/CreateConnectionAsyncCompletedEventArgs.cs deleted file mode 100644 index e26c3568..00000000 --- a/MinecraftClient/Proxy/Handlers/EventArgs/CreateConnectionAsyncCompletedEventArgs.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Net.Sockets; -using System.ComponentModel; - -namespace Starksoft.Net.Proxy -{ - /// - /// Event arguments class for the EncryptAsyncCompleted event. - /// - public class CreateConnectionAsyncCompletedEventArgs : AsyncCompletedEventArgs - { - private TcpClient _proxyConnection; - - /// - /// Constructor. - /// - /// Exception information generated by the event. - /// Cancelled event flag. This flag is set to true if the event was cancelled. - /// Proxy Connection. The initialized and open TcpClient proxy connection. - public CreateConnectionAsyncCompletedEventArgs(Exception error, bool cancelled, TcpClient proxyConnection) - : base(error, cancelled, null) - { - _proxyConnection = proxyConnection; - } - - /// - /// The proxy connection. - /// - public TcpClient ProxyConnection - { - get { return _proxyConnection; } - } - } - -} diff --git a/MinecraftClient/Proxy/Handlers/Exceptions/ProxyException.cs b/MinecraftClient/Proxy/Handlers/Exceptions/ProxyException.cs deleted file mode 100644 index 1d966db6..00000000 --- a/MinecraftClient/Proxy/Handlers/Exceptions/ProxyException.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Runtime.Serialization; - -namespace Starksoft.Net.Proxy -{ - - /// - /// This exception is thrown when a general, unexpected proxy error. - /// - [Serializable()] - public class ProxyException : Exception - { - /// - /// Constructor. - /// - public ProxyException() - { - } - - /// - /// Constructor. - /// - /// Exception message text. - public ProxyException(string message) - : base(message) - { - } - - /// - /// Constructor. - /// - /// Exception message text. - /// The inner exception object. - public ProxyException(string message, Exception innerException) - : - base(message, innerException) - { - } - - /// - /// Constructor. - /// - /// Serialization information. - /// Stream context information. - protected ProxyException(SerializationInfo info, - StreamingContext context) - : base(info, context) - { - } - } - -} \ No newline at end of file diff --git a/MinecraftClient/Proxy/Handlers/HttpProxyClient.cs b/MinecraftClient/Proxy/Handlers/HttpProxyClient.cs deleted file mode 100644 index bef356e5..00000000 --- a/MinecraftClient/Proxy/Handlers/HttpProxyClient.cs +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Text; -using System.Net.Sockets; -using System.Threading; -using System.Globalization; -using System.ComponentModel; - -namespace Starksoft.Net.Proxy -{ - /// - /// HTTP connection proxy class. This class implements the HTTP standard proxy protocol. - /// - /// You can use this class to set up a connection to an HTTP proxy server. Calling the - /// CreateConnection() method initiates the proxy connection and returns a standard - /// System.Net.Socks.TcpClient object that can be used as normal. The proxy plumbing - /// is all handled for you. - /// - /// - /// - /// - /// - public class HttpProxyClient : IProxyClient - { - private string _proxyHost; - private int _proxyPort; - private string _proxyUsername; - private string _proxyPassword; - private HttpResponseCodes _respCode; - private string _respText; - private TcpClient _tcpClient; - private TcpClient _tcpClientCached; - - private const int HTTP_PROXY_DEFAULT_PORT = 8080; - private const string HTTP_PROXY_CONNECT_CMD = "CONNECT {0}:{1} HTTP/1.0\r\nHOST {0}:{1}\r\n\r\n"; - private const string HTTP_PROXY_AUTHENTICATE_CMD = "CONNECT {0}:{1} HTTP/1.0\r\nHOST {0}:{1}\r\nProxy-Authorization: Basic {2}\r\n\r\n"; - - private const int WAIT_FOR_DATA_INTERVAL = 50; // 50 ms - private const int WAIT_FOR_DATA_TIMEOUT = 15000; // 15 seconds - private const string PROXY_NAME = "HTTP"; - - private enum HttpResponseCodes - { - None = 0, - Continue = 100, - SwitchingProtocols = 101, - OK = 200, - Created = 201, - Accepted = 202, - NonAuthoritiveInformation = 203, - NoContent = 204, - ResetContent = 205, - PartialContent = 206, - MultipleChoices = 300, - MovedPermanetly = 301, - Found = 302, - SeeOther = 303, - NotModified = 304, - UserProxy = 305, - TemporaryRedirect = 307, - BadRequest = 400, - Unauthorized = 401, - PaymentRequired = 402, - Forbidden = 403, - NotFound = 404, - MethodNotAllowed = 405, - NotAcceptable = 406, - ProxyAuthenticantionRequired = 407, - RequestTimeout = 408, - Conflict = 409, - Gone = 410, - PreconditionFailed = 411, - RequestEntityTooLarge = 413, - RequestURITooLong = 414, - UnsupportedMediaType = 415, - RequestedRangeNotSatisfied = 416, - ExpectationFailed = 417, - InternalServerError = 500, - NotImplemented = 501, - BadGateway = 502, - ServiceUnavailable = 503, - GatewayTimeout = 504, - HTTPVersionNotSupported = 505 - } - - /// - /// Constructor. - /// - public HttpProxyClient() { } - - /// - /// Creates a HTTP proxy client object using the supplied TcpClient object connection. - /// - /// A TcpClient connection object. - public HttpProxyClient(TcpClient tcpClient) - { - if (tcpClient == null) - throw new ArgumentNullException("tcpClient"); - - _tcpClientCached = tcpClient; - } - - - /// - /// Constructor. The default HTTP proxy port 8080 is used. - /// - /// Host name or IP address of the proxy. - public HttpProxyClient(string proxyHost) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - _proxyHost = proxyHost; - _proxyPort = HTTP_PROXY_DEFAULT_PORT; - } - - /// - /// Constructor. - /// - /// Host name or IP address of the proxy server. - /// Port number to connect to the proxy server. - /// Username for the proxy server. - /// Password for the proxy server. - public HttpProxyClient(string proxyHost, int proxyPort, string proxyUsername, string proxyPassword) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (String.IsNullOrEmpty(proxyUsername)) - throw new ArgumentNullException("proxyUsername"); - - if (proxyPassword == null) - throw new ArgumentNullException("proxyPassword"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - _proxyUsername = proxyUsername; - _proxyPassword = proxyPassword; - } - - - /// - /// Constructor. - /// - /// Host name or IP address of the proxy server. - /// Port number for the proxy server. - public HttpProxyClient(string proxyHost, int proxyPort) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - } - - /// - /// Gets or sets host name or IP address of the proxy server. - /// - public string ProxyHost - { - get { return _proxyHost; } - set { _proxyHost = value; } - } - - /// - /// Gets or sets port number for the proxy server. - /// - public int ProxyPort - { - get { return _proxyPort; } - set { _proxyPort = value; } - } - - /// - /// Gets String representing the name of the proxy. - /// - /// This property will always return the value 'HTTP' - public string ProxyName - { - get { return PROXY_NAME; } - } - - /// - /// Gets or sets the TcpClient object. - /// This property can be set prior to executing CreateConnection to use an existing TcpClient connection. - /// - public TcpClient TcpClient - { - get { return _tcpClientCached; } - set { _tcpClientCached = value; } - } - - - /// - /// Creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - public TcpClient CreateConnection(string destinationHost, int destinationPort) - { - try - { - // if we have no cached tcpip connection then create one - if (_tcpClientCached == null) - { - if (String.IsNullOrEmpty(_proxyHost)) - throw new ProxyException("ProxyHost property must contain a value."); - - if (_proxyPort <= 0 || _proxyPort > 65535) - throw new ProxyException("ProxyPort value must be greater than zero and less than 65535"); - - // create new tcp client object to the proxy server - _tcpClient = new TcpClient(); - - // attempt to open the connection - _tcpClient.Connect(_proxyHost, _proxyPort); - } - else - { - _tcpClient = _tcpClientCached; - } - - // send connection command to proxy host for the specified destination host and port - SendConnectionCommand(destinationHost, destinationPort); - - // remove the private reference to the tcp client so the proxy object does not keep it - // return the open proxied tcp client object to the caller for normal use - TcpClient rtn = _tcpClient; - _tcpClient = null; - return rtn; - } - catch (SocketException ex) - { - throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "Connection to proxy host {0} on port {1} failed.", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient)), ex); - } - } - - - private void SendConnectionCommand(string host, int port) - { - NetworkStream stream = _tcpClient.GetStream(); - - string connectCmd = CreateCommandString(host, port); - - byte[] request = ASCIIEncoding.ASCII.GetBytes(connectCmd); - - // send the connect request - stream.Write(request, 0, request.Length); - - // wait for the proxy server to respond - WaitForData(stream); - - // PROXY SERVER RESPONSE - // ======================================================================= - //HTTP/1.0 200 Connection Established - //[.... other HTTP header lines ending with .. - //ignore all of them] - // // Last Empty Line - - // create an byte response array - byte[] response = new byte[_tcpClient.ReceiveBufferSize]; - StringBuilder sbuilder = new StringBuilder(); - int bytes = 0; - long total = 0; - - do - { - bytes = stream.Read(response, 0, _tcpClient.ReceiveBufferSize); - total += bytes; - sbuilder.Append(System.Text.ASCIIEncoding.UTF8.GetString(response, 0, bytes)); - } while (stream.DataAvailable); - - ParseResponse(sbuilder.ToString()); - - // evaluate the reply code for an error condition - if (_respCode != HttpResponseCodes.OK) - HandleProxyCommandError(host, port); - } - - private string CreateCommandString(string host, int port) - { - string connectCmd; - if (!string.IsNullOrEmpty(_proxyUsername)) - { - // gets the user/pass into base64 encoded string in the form of [username]:[password] - string auth = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", _proxyUsername, _proxyPassword))); - - // PROXY SERVER REQUEST - // ======================================================================= - //CONNECT starksoft.com:443 HTTP/1.0 - //HOST starksoft.com:443 - //Proxy-Authorization: username:password - // NOTE: username:password string will be base64 encoded as one - // concatenated string - //[... other HTTP header lines ending with if required]> - // // Last Empty Line - connectCmd = String.Format(CultureInfo.InvariantCulture, HTTP_PROXY_AUTHENTICATE_CMD, host, port.ToString(CultureInfo.InvariantCulture), auth); - } - else - { - // PROXY SERVER REQUEST - // ======================================================================= - //CONNECT starksoft.com:443 HTTP/1.0 - //HOST starksoft.com:443 - //[... other HTTP header lines ending with if required]> - // // Last Empty Line - connectCmd = String.Format(CultureInfo.InvariantCulture, HTTP_PROXY_CONNECT_CMD + "\r\n", host, port.ToString(CultureInfo.InvariantCulture)); - } - return connectCmd; - } - - private void HandleProxyCommandError(string host, int port) - { - string msg; - - switch (_respCode) - { - case HttpResponseCodes.None: - msg = String.Format(CultureInfo.InvariantCulture, "Proxy destination {0} on port {1} failed to return a recognized HTTP response code. Server response: {2}", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient), _respText); - break; - - case HttpResponseCodes.BadGateway: - //HTTP/1.1 502 Proxy Error (The specified Secure Sockets Layer (SSL) port is not allowed. ISA Server is not configured to allow SSL requests from this port. Most Web browsers use port 443 for SSL requests.) - msg = String.Format(CultureInfo.InvariantCulture, "Proxy destination {0} on port {1} responded with a 502 code - Bad Gateway. If you are connecting to a Microsoft ISA destination please refer to knowledge based article Q283284 for more information. Server response: {2}", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient), _respText); - break; - - default: - msg = String.Format(CultureInfo.InvariantCulture, "Proxy destination {0} on port {1} responded with a {2} code - {3}", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient), ((int)_respCode).ToString(CultureInfo.InvariantCulture), _respText); - break; - } - - // throw a new application exception - throw new ProxyException(msg); - } - - private void WaitForData(NetworkStream stream) - { - int sleepTime = 0; - while (!stream.DataAvailable) - { - Thread.Sleep(WAIT_FOR_DATA_INTERVAL); - sleepTime += WAIT_FOR_DATA_INTERVAL; - if (sleepTime > WAIT_FOR_DATA_TIMEOUT) - throw new ProxyException(String.Format("A timeout while waiting for the proxy server at {0} on port {1} to respond.", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient) )); - } - } - - private void ParseResponse(string response) - { - string[] data = null; - - // get rid of the LF character if it exists and then split the string on all CR - data = response.Replace('\n', ' ').Split('\r'); - - ParseCodeAndText(data[0]); - } - - private void ParseCodeAndText(string line) - { - int begin = 0; - int end = 0; - string val = null; - - if (line.IndexOf("HTTP") == -1) - throw new ProxyException(String.Format("No HTTP response received from proxy destination. Server response: {0}.", line)); - - begin = line.IndexOf(" ") + 1; - end = line.IndexOf(" ", begin); - - val = line.Substring(begin, end - begin); - Int32 code = 0; - - if (!Int32.TryParse(val, out code)) - throw new ProxyException(String.Format("An invalid response code was received from proxy destination. Server response: {0}.", line)); - - _respCode = (HttpResponseCodes)code; - _respText = line.Substring(end + 1).Trim(); - } - - - -#region "Async Methods" - - private BackgroundWorker _asyncWorker; - private Exception _asyncException; - bool _asyncCancelled; - - /// - /// Gets a value indicating whether an asynchronous operation is running. - /// - /// Returns true if an asynchronous operation is running; otherwise, false. - /// - public bool IsBusy - { - get { return _asyncWorker == null ? false : _asyncWorker.IsBusy; } - } - - /// - /// Gets a value indicating whether an asynchronous operation is cancelled. - /// - /// Returns true if an asynchronous operation is cancelled; otherwise, false. - /// - public bool IsAsyncCancelled - { - get { return _asyncCancelled; } - } - - /// - /// Cancels any asychronous operation that is currently active. - /// - public void CancelAsync() - { - if (_asyncWorker != null && !_asyncWorker.CancellationPending && _asyncWorker.IsBusy) - { - _asyncCancelled = true; - _asyncWorker.CancelAsync(); - } - } - - private void CreateAsyncWorker() - { - if (_asyncWorker != null) - _asyncWorker.Dispose(); - _asyncException = null; - _asyncWorker = null; - _asyncCancelled = false; - _asyncWorker = new BackgroundWorker(); - } - - /// - /// Event handler for CreateConnectionAsync method completed. - /// - public event EventHandler CreateConnectionAsyncCompleted; - - /// - /// Asynchronously creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - public void CreateConnectionAsync(string destinationHost, int destinationPort) - { - if (_asyncWorker != null && _asyncWorker.IsBusy) - throw new InvalidOperationException("The HttpProxy object is already busy executing another asynchronous operation. You can only execute one asychronous method at a time."); - - CreateAsyncWorker(); - _asyncWorker.WorkerSupportsCancellation = true; - _asyncWorker.DoWork += new DoWorkEventHandler(CreateConnectionAsync_DoWork); - _asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateConnectionAsync_RunWorkerCompleted); - Object[] args = new Object[2]; - args[0] = destinationHost; - args[1] = destinationPort; - _asyncWorker.RunWorkerAsync(args); - } - - private void CreateConnectionAsync_DoWork(object sender, DoWorkEventArgs e) - { - try - { - Object[] args = (Object[])e.Argument; - e.Result = CreateConnection((string)args[0], (int)args[1]); - } - catch (Exception ex) - { - _asyncException = ex; - } - } - - private void CreateConnectionAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - if (CreateConnectionAsyncCompleted != null) - CreateConnectionAsyncCompleted(this, new CreateConnectionAsyncCompletedEventArgs(_asyncException, _asyncCancelled, (TcpClient)e.Result)); - } - - - -#endregion - - } -} diff --git a/MinecraftClient/Proxy/Handlers/IProxyClient.cs b/MinecraftClient/Proxy/Handlers/IProxyClient.cs deleted file mode 100644 index e83ad43d..00000000 --- a/MinecraftClient/Proxy/Handlers/IProxyClient.cs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net.Sockets; - -namespace Starksoft.Net.Proxy -{ - /// - /// Proxy client interface. This is the interface that all proxy clients must implement. - /// - public interface IProxyClient - { - - /// - /// Event handler for CreateConnectionAsync method completed. - /// - event EventHandler CreateConnectionAsyncCompleted; - - /// - /// Gets or sets proxy host name or IP address. - /// - string ProxyHost { get; set; } - - /// - /// Gets or sets proxy port number. - /// - int ProxyPort { get; set; } - - /// - /// Gets String representing the name of the proxy. - /// - string ProxyName { get; } - - /// - /// Gets or set the TcpClient object if one was specified in the constructor. - /// - TcpClient TcpClient { get; set; } - - /// - /// Creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - TcpClient CreateConnection(string destinationHost, int destinationPort); - - /// - /// Asynchronously creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - void CreateConnectionAsync(string destinationHost, int destinationPort); - - } -} diff --git a/MinecraftClient/Proxy/Handlers/ProxyClientFactory.cs b/MinecraftClient/Proxy/Handlers/ProxyClientFactory.cs deleted file mode 100644 index b7b9edbf..00000000 --- a/MinecraftClient/Proxy/Handlers/ProxyClientFactory.cs +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Net.Sockets; - -namespace Starksoft.Net.Proxy -{ - /// - /// The type of proxy. - /// - public enum ProxyType - { - /// - /// No Proxy specified. Note this option will cause an exception to be thrown if used to create a proxy object by the factory. - /// - None, - /// - /// HTTP Proxy - /// - Http, - /// - /// SOCKS v4 Proxy - /// - Socks4, - /// - /// SOCKS v4a Proxy - /// - Socks4a, - /// - /// SOCKS v5 Proxy - /// - Socks5 - } - - /// - /// Factory class for creating new proxy client objects. - /// - /// - /// - /// // create an instance of the client proxy factory - /// ProxyClientFactory factory = new ProxyClientFactory(); - /// - /// // use the proxy client factory to generically specify the type of proxy to create - /// // the proxy factory method CreateProxyClient returns an IProxyClient object - /// IProxyClient proxy = factory.CreateProxyClient(ProxyType.Http, "localhost", 6588); - /// - /// // create a connection through the proxy to www.starksoft.com over port 80 - /// System.Net.Sockets.TcpClient tcpClient = proxy.CreateConnection("www.starksoft.com", 80); - /// - /// - public class ProxyClientFactory - { - - /// - /// Factory method for creating new proxy client objects. - /// - /// The type of proxy client to create. - /// Proxy client object. - public IProxyClient CreateProxyClient(ProxyType type) - { - if (type == ProxyType.None) - throw new ArgumentOutOfRangeException("type"); - - switch (type) - { - case ProxyType.Http: - return new HttpProxyClient(); - case ProxyType.Socks4: - return new Socks4ProxyClient(); - case ProxyType.Socks4a: - return new Socks4aProxyClient(); - case ProxyType.Socks5: - return new Socks5ProxyClient(); - default: - throw new ProxyException(String.Format("Unknown proxy type {0}.", type.ToString())); - } - } - - /// - /// Factory method for creating new proxy client objects using an existing TcpClient connection object. - /// - /// The type of proxy client to create. - /// Open TcpClient object. - /// Proxy client object. - public IProxyClient CreateProxyClient(ProxyType type, TcpClient tcpClient) - { - if (type == ProxyType.None) - throw new ArgumentOutOfRangeException("type"); - - switch (type) - { - case ProxyType.Http: - return new HttpProxyClient(tcpClient); - case ProxyType.Socks4: - return new Socks4ProxyClient(tcpClient); - case ProxyType.Socks4a: - return new Socks4aProxyClient(tcpClient); - case ProxyType.Socks5: - return new Socks5ProxyClient(tcpClient); - default: - throw new ProxyException(String.Format("Unknown proxy type {0}.", type.ToString())); - } - } - - /// - /// Factory method for creating new proxy client objects. - /// - /// The type of proxy client to create. - /// The proxy host or IP address. - /// The proxy port number. - /// Proxy client object. - public IProxyClient CreateProxyClient(ProxyType type, string proxyHost, int proxyPort) - { - if (type == ProxyType.None) - throw new ArgumentOutOfRangeException("type"); - - switch (type) - { - case ProxyType.Http: - return new HttpProxyClient(proxyHost, proxyPort); - case ProxyType.Socks4: - return new Socks4ProxyClient(proxyHost, proxyPort); - case ProxyType.Socks4a: - return new Socks4aProxyClient(proxyHost, proxyPort); - case ProxyType.Socks5: - return new Socks5ProxyClient(proxyHost, proxyPort); - default: - throw new ProxyException(String.Format("Unknown proxy type {0}.", type.ToString())); - } - } - - /// - /// Factory method for creating new proxy client objects. - /// - /// The type of proxy client to create. - /// The proxy host or IP address. - /// The proxy port number. - /// The proxy username. This parameter is only used by Http, Socks4 and Socks5 proxy objects. - /// The proxy user password. This parameter is only used Http, Socks5 proxy objects. - /// Proxy client object. - public IProxyClient CreateProxyClient(ProxyType type, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword) - { - if (type == ProxyType.None) - throw new ArgumentOutOfRangeException("type"); - - switch (type) - { - case ProxyType.Http: - return new HttpProxyClient(proxyHost, proxyPort, proxyUsername, proxyPassword); - case ProxyType.Socks4: - return new Socks4ProxyClient(proxyHost, proxyPort, proxyUsername); - case ProxyType.Socks4a: - return new Socks4aProxyClient(proxyHost, proxyPort, proxyUsername); - case ProxyType.Socks5: - return new Socks5ProxyClient(proxyHost, proxyPort, proxyUsername, proxyPassword); - default: - throw new ProxyException(String.Format("Unknown proxy type {0}.", type.ToString())); - } - } - - /// - /// Factory method for creating new proxy client objects. - /// - /// The type of proxy client to create. - /// Open TcpClient object. - /// The proxy host or IP address. - /// The proxy port number. - /// The proxy username. This parameter is only used by Http, Socks4 and Socks5 proxy objects. - /// The proxy user password. This parameter is only used Http, Socks5 proxy objects. - /// Proxy client object. - public IProxyClient CreateProxyClient(ProxyType type, TcpClient tcpClient, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword) - { - IProxyClient c = CreateProxyClient(type, proxyHost, proxyPort, proxyUsername, proxyPassword); - c.TcpClient = tcpClient; - return c; - } - - - } - - - -} diff --git a/MinecraftClient/Proxy/Handlers/Socks4ProxyClient.cs b/MinecraftClient/Proxy/Handlers/Socks4ProxyClient.cs deleted file mode 100644 index fc72c001..00000000 --- a/MinecraftClient/Proxy/Handlers/Socks4ProxyClient.cs +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Text; -using System.Net; -using System.Net.Sockets; -using System.Globalization; -using System.IO; -using System.Threading; -using System.ComponentModel; - -namespace Starksoft.Net.Proxy -{ - /// - /// Socks4 connection proxy class. This class implements the Socks4 standard proxy protocol. - /// - /// - /// This class implements the Socks4 proxy protocol standard for TCP communciations. - /// - public class Socks4ProxyClient : IProxyClient - { - private const int WAIT_FOR_DATA_INTERVAL = 50; // 50 ms - private const int WAIT_FOR_DATA_TIMEOUT = 15000; // 15 seconds - private const string PROXY_NAME = "SOCKS4"; - private TcpClient _tcpClient; - private TcpClient _tcpClientCached; - - private string _proxyHost; - private int _proxyPort; - private string _proxyUserId; - - /// - /// Default Socks4 proxy port. - /// - internal const int SOCKS_PROXY_DEFAULT_PORT = 1080; - /// - /// Socks4 version number. - /// - internal const byte SOCKS4_VERSION_NUMBER = 4; - /// - /// Socks4 connection command value. - /// - internal const byte SOCKS4_CMD_CONNECT = 0x01; - /// - /// Socks4 bind command value. - /// - internal const byte SOCKS4_CMD_BIND = 0x02; - /// - /// Socks4 reply request grant response value. - /// - internal const byte SOCKS4_CMD_REPLY_REQUEST_GRANTED = 90; - /// - /// Socks4 reply request rejected or failed response value. - /// - internal const byte SOCKS4_CMD_REPLY_REQUEST_REJECTED_OR_FAILED = 91; - /// - /// Socks4 reply request rejected becauase the proxy server can not connect to the IDENTD server value. - /// - internal const byte SOCKS4_CMD_REPLY_REQUEST_REJECTED_CANNOT_CONNECT_TO_IDENTD = 92; - /// - /// Socks4 reply request rejected because of a different IDENTD server. - /// - internal const byte SOCKS4_CMD_REPLY_REQUEST_REJECTED_DIFFERENT_IDENTD = 93; - - /// - /// Create a Socks4 proxy client object. The default proxy port 1080 is used. - /// - public Socks4ProxyClient() { } - - /// - /// Creates a Socks4 proxy client object using the supplied TcpClient object connection. - /// - /// A TcpClient connection object. - public Socks4ProxyClient(TcpClient tcpClient) - { - if (tcpClient == null) - throw new ArgumentNullException("tcpClient"); - - _tcpClientCached = tcpClient; - } - - /// - /// Create a Socks4 proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - /// Proxy user identification information. - public Socks4ProxyClient(string proxyHost, string proxyUserId) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyUserId == null) - throw new ArgumentNullException("proxyUserId"); - - _proxyHost = proxyHost; - _proxyPort = SOCKS_PROXY_DEFAULT_PORT; - _proxyUserId = proxyUserId; - } - - /// - /// Create a Socks4 proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - /// Proxy user identification information. - public Socks4ProxyClient(string proxyHost, int proxyPort, string proxyUserId) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - if (proxyUserId == null) - throw new ArgumentNullException("proxyUserId"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - _proxyUserId = proxyUserId; - } - - /// - /// Create a Socks4 proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - public Socks4ProxyClient(string proxyHost) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - _proxyHost = proxyHost; - _proxyPort = SOCKS_PROXY_DEFAULT_PORT; - } - - /// - /// Create a Socks4 proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - public Socks4ProxyClient(string proxyHost, int proxyPort) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - } - - /// - /// Gets or sets host name or IP address of the proxy server. - /// - public string ProxyHost - { - get { return _proxyHost; } - set { _proxyHost = value; } - } - - /// - /// Gets or sets port used to connect to proxy server. - /// - public int ProxyPort - { - get { return _proxyPort; } - set { _proxyPort = value; } - } - - /// - /// Gets String representing the name of the proxy. - /// - /// This property will always return the value 'SOCKS4' - virtual public string ProxyName - { - get { return PROXY_NAME; } - } - - /// - /// Gets or sets proxy user identification information. - /// - public string ProxyUserId - { - get { return _proxyUserId; } - set { _proxyUserId = value; } - } - - /// - /// Gets or sets the TcpClient object. - /// This property can be set prior to executing CreateConnection to use an existing TcpClient connection. - /// - public TcpClient TcpClient - { - get { return _tcpClientCached; } - set { _tcpClientCached = value; } - } - - /// - /// Creates a TCP connection to the destination host through the proxy server - /// host. - /// - /// Destination host name or IP address of the destination server. - /// Port number to connect to on the destination server. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - public TcpClient CreateConnection(string destinationHost, int destinationPort) - { - if (String.IsNullOrEmpty(destinationHost)) - throw new ArgumentNullException("destinationHost"); - - if (destinationPort <= 0 || destinationPort > 65535) - throw new ArgumentOutOfRangeException("destinationPort", "port must be greater than zero and less than 65535"); - - try - { - // if we have no cached tcpip connection then create one - if (_tcpClientCached == null) - { - if (String.IsNullOrEmpty(_proxyHost)) - throw new ProxyException("ProxyHost property must contain a value."); - - if (_proxyPort <= 0 || _proxyPort > 65535) - throw new ProxyException("ProxyPort value must be greater than zero and less than 65535"); - - // create new tcp client object to the proxy server - _tcpClient = new TcpClient(); - - // attempt to open the connection - _tcpClient.Connect(_proxyHost, _proxyPort); - } - else - { - _tcpClient = _tcpClientCached; - } - - // send connection command to proxy host for the specified destination host and port - SendCommand(_tcpClient.GetStream(), SOCKS4_CMD_CONNECT, destinationHost, destinationPort, _proxyUserId); - - // remove the private reference to the tcp client so the proxy object does not keep it - // return the open proxied tcp client object to the caller for normal use - TcpClient rtn = _tcpClient; - _tcpClient = null; - return rtn; - } - catch (Exception ex) - { - throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "Connection to proxy host {0} on port {1} failed.", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient)), ex); - } - } - - - /// - /// Sends a command to the proxy server. - /// - /// Proxy server data stream. - /// Proxy byte command to execute. - /// Destination host name or IP address. - /// Destination port number - /// IDENTD user ID value. - internal virtual void SendCommand(NetworkStream proxy, byte command, string destinationHost, int destinationPort, string userId) - { - // PROXY SERVER REQUEST - // The client connects to the SOCKS server and sends a CONNECT request when - // it wants to establish a connection to an application server. The client - // includes in the request packet the IP address and the port number of the - // destination host, and userid, in the following format. - // - // +----+----+----+----+----+----+----+----+----+----+....+----+ - // | VN | CD | DSTPORT | DSTIP | USERID |NULL| - // +----+----+----+----+----+----+----+----+----+----+....+----+ - // # of bytes: 1 1 2 4 variable 1 - // - // VN is the SOCKS protocol version number and should be 4. CD is the - // SOCKS command code and should be 1 for CONNECT request. NULL is a byte - // of all zero bits. - - // userId needs to be a zero length string so that the GetBytes method - // works properly - if (userId == null) - userId = ""; - - byte[] destIp = GetIPAddressBytes(destinationHost); - byte[] destPort = GetDestinationPortBytes(destinationPort); - byte[] userIdBytes = ASCIIEncoding.ASCII.GetBytes(userId); - byte[] request = new byte[9 + userIdBytes.Length]; - - // set the bits on the request byte array - request[0] = SOCKS4_VERSION_NUMBER; - request[1] = command; - destPort.CopyTo(request, 2); - destIp.CopyTo(request, 4); - userIdBytes.CopyTo(request, 8); - request[8 + userIdBytes.Length] = 0x00; // null (byte with all zeros) terminator for userId - - // send the connect request - proxy.Write(request, 0, request.Length); - - // wait for the proxy server to respond - WaitForData(proxy); - - // PROXY SERVER RESPONSE - // The SOCKS server checks to see whether such a request should be granted - // based on any combination of source IP address, destination IP address, - // destination port number, the userid, and information it may obtain by - // consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS - // server makes a connection to the specified port of the destination host. - // A reply packet is sent to the client when this connection is established, - // or when the request is rejected or the operation fails. - // - // +----+----+----+----+----+----+----+----+ - // | VN | CD | DSTPORT | DSTIP | - // +----+----+----+----+----+----+----+----+ - // # of bytes: 1 1 2 4 - // - // VN is the version of the reply code and should be 0. CD is the result - // code with one of the following values: - // - // 90: request granted - // 91: request rejected or failed - // 92: request rejected becuase SOCKS server cannot connect to - // identd on the client - // 93: request rejected because the client program and identd - // report different user-ids - // - // The remaining fields are ignored. - // - // The SOCKS server closes its connection immediately after notifying - // the client of a failed or rejected request. For a successful request, - // the SOCKS server gets ready to relay traffic on both directions. This - // enables the client to do I/O on its connection as if it were directly - // connected to the application server. - - // create an 8 byte response array - byte[] response = new byte[8]; - - // read the resonse from the network stream - proxy.Read(response, 0, 8); - - // evaluate the reply code for an error condition - if (response[1] != SOCKS4_CMD_REPLY_REQUEST_GRANTED) - HandleProxyCommandError(response, destinationHost, destinationPort); - } - - /// - /// Translate the host name or IP address to a byte array. - /// - /// Host name or IP address. - /// Byte array representing IP address in bytes. - internal byte[] GetIPAddressBytes(string destinationHost) - { - IPAddress ipAddr = null; - - // if the address doesn't parse then try to resolve with dns - if (!IPAddress.TryParse(destinationHost, out ipAddr)) - { - try - { - ipAddr = Dns.GetHostEntry(destinationHost).AddressList[0]; - } - catch (Exception ex) - { - throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "A error occurred while attempting to DNS resolve the host name {0}.", destinationHost), ex); - } - } - - // return address bytes - return ipAddr.GetAddressBytes(); - } - - /// - /// Translate the destination port value to a byte array. - /// - /// Destination port. - /// Byte array representing an 16 bit port number as two bytes. - internal byte[] GetDestinationPortBytes(int value) - { - byte[] array = new byte[2]; - array[0] = Convert.ToByte(value / 256); - array[1] = Convert.ToByte(value % 256); - return array; - } - - /// - /// Receive a byte array from the proxy server and determine and handle and errors that may have occurred. - /// - /// Proxy server command response as a byte array. - /// Destination host. - /// Destination port number. - internal void HandleProxyCommandError(byte[] response, string destinationHost, int destinationPort) - { - - if (response == null) - throw new ArgumentNullException("response"); - - // extract the reply code - byte replyCode = response[1]; - - // extract the ip v4 address (4 bytes) - byte[] ipBytes = new byte[4]; - for (int i = 0; i < 4; i++) - ipBytes[i] = response[i + 4]; - - // convert the ip address to an IPAddress object - IPAddress ipAddr = new IPAddress(ipBytes); - - // extract the port number big endian (2 bytes) - byte[] portBytes = new byte[2]; - portBytes[0] = response[3]; - portBytes[1] = response[2]; - Int16 port = BitConverter.ToInt16(portBytes, 0); - - // translate the reply code error number to human readable text - string proxyErrorText; - switch (replyCode) - { - case SOCKS4_CMD_REPLY_REQUEST_REJECTED_OR_FAILED: - proxyErrorText = "connection request was rejected or failed"; - break; - case SOCKS4_CMD_REPLY_REQUEST_REJECTED_CANNOT_CONNECT_TO_IDENTD: - proxyErrorText = "connection request was rejected because SOCKS destination cannot connect to identd on the client"; - break; - case SOCKS4_CMD_REPLY_REQUEST_REJECTED_DIFFERENT_IDENTD: - proxyErrorText = "connection request rejected because the client program and identd report different user-ids"; - break; - default: - proxyErrorText = String.Format(CultureInfo.InvariantCulture, "proxy client received an unknown reply with the code value '{0}' from the proxy destination", replyCode.ToString(CultureInfo.InvariantCulture)); - break; - } - - // build the exeception message string - string exceptionMsg = String.Format(CultureInfo.InvariantCulture, "The {0} concerning destination host {1} port number {2}. The destination reported the host as {3} port {4}.", proxyErrorText, destinationHost, destinationPort, ipAddr.ToString(), port.ToString(CultureInfo.InvariantCulture)); - - // throw a new application exception - throw new ProxyException(exceptionMsg); - } - - internal void WaitForData(NetworkStream stream) - { - int sleepTime = 0; - while (!stream.DataAvailable) - { - Thread.Sleep(WAIT_FOR_DATA_INTERVAL); - sleepTime += WAIT_FOR_DATA_INTERVAL; - if (sleepTime > WAIT_FOR_DATA_TIMEOUT) - throw new ProxyException("A timeout while waiting for the proxy destination to respond."); - } - } - - -#region "Async Methods" - - private BackgroundWorker _asyncWorker; - private Exception _asyncException; - bool _asyncCancelled; - - /// - /// Gets a value indicating whether an asynchronous operation is running. - /// - /// Returns true if an asynchronous operation is running; otherwise, false. - /// - public bool IsBusy - { - get { return _asyncWorker == null ? false : _asyncWorker.IsBusy; } - } - - /// - /// Gets a value indicating whether an asynchronous operation is cancelled. - /// - /// Returns true if an asynchronous operation is cancelled; otherwise, false. - /// - public bool IsAsyncCancelled - { - get { return _asyncCancelled; } - } - - /// - /// Cancels any asychronous operation that is currently active. - /// - public void CancelAsync() - { - if (_asyncWorker != null && !_asyncWorker.CancellationPending && _asyncWorker.IsBusy) - { - _asyncCancelled = true; - _asyncWorker.CancelAsync(); - } - } - - private void CreateAsyncWorker() - { - if (_asyncWorker != null) - _asyncWorker.Dispose(); - _asyncException = null; - _asyncWorker = null; - _asyncCancelled = false; - _asyncWorker = new BackgroundWorker(); - } - - /// - /// Event handler for CreateConnectionAsync method completed. - /// - public event EventHandler CreateConnectionAsyncCompleted; - - /// - /// Asynchronously creates a remote TCP connection through a proxy server to the destination host on the destination port - /// using the supplied open TcpClient object with an open connection to proxy server. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns TcpClient object that can be used normally to communicate - /// with the destination server. - /// - /// - /// This instructs the proxy server to make a pass through connection to the specified destination host on the specified - /// port. - /// - public void CreateConnectionAsync(string destinationHost, int destinationPort) - { - if (_asyncWorker != null && _asyncWorker.IsBusy) - throw new InvalidOperationException("The Socks4/4a object is already busy executing another asynchronous operation. You can only execute one asychronous method at a time."); - - CreateAsyncWorker(); - _asyncWorker.WorkerSupportsCancellation = true; - _asyncWorker.DoWork += new DoWorkEventHandler(CreateConnectionAsync_DoWork); - _asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateConnectionAsync_RunWorkerCompleted); - Object[] args = new Object[2]; - args[0] = destinationHost; - args[1] = destinationPort; - _asyncWorker.RunWorkerAsync(args); - } - - private void CreateConnectionAsync_DoWork(object sender, DoWorkEventArgs e) - { - try - { - Object[] args = (Object[])e.Argument; - e.Result = CreateConnection((string)args[0], (int)args[1]); - } - catch (Exception ex) - { - _asyncException = ex; - } - } - - private void CreateConnectionAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - if (CreateConnectionAsyncCompleted != null) - CreateConnectionAsyncCompleted(this, new CreateConnectionAsyncCompletedEventArgs(_asyncException, _asyncCancelled, (TcpClient)e.Result)); - } - -#endregion - - } - -} diff --git a/MinecraftClient/Proxy/Handlers/Socks4aProxyClient.cs b/MinecraftClient/Proxy/Handlers/Socks4aProxyClient.cs deleted file mode 100644 index d6e6ee21..00000000 --- a/MinecraftClient/Proxy/Handlers/Socks4aProxyClient.cs +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Text; -using System.Net; -using System.Net.Sockets; -using System.IO; - -namespace Starksoft.Net.Proxy -{ - /// - /// Socks4a connection proxy class. This class implements the Socks4a standard proxy protocol - /// which is an extension of the Socks4 protocol - /// - /// - /// In Socks version 4A if the client cannot resolve the destination host's domain name - /// to find its IP address the server will attempt to resolve it. - /// - public class Socks4aProxyClient : Socks4ProxyClient - { - private const string PROXY_NAME = "SOCKS4a"; - - /// - /// Default constructor. - /// - public Socks4aProxyClient() - : base() - { } - - /// - /// Creates a Socks4 proxy client object using the supplied TcpClient object connection. - /// - /// An open TcpClient object with an established connection. - public Socks4aProxyClient(TcpClient tcpClient) - : base(tcpClient) - { } - - /// - /// Create a Socks4a proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - /// Proxy user identification information for an IDENTD server. - public Socks4aProxyClient(string proxyHost, string proxyUserId) - : base(proxyHost, proxyUserId) - { } - - /// - /// Create a Socks4a proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - /// Proxy user identification information. - public Socks4aProxyClient(string proxyHost, int proxyPort, string proxyUserId) - : base(proxyHost, proxyPort, proxyUserId) - { } - - /// - /// Create a Socks4 proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - public Socks4aProxyClient(string proxyHost) : base(proxyHost) - { } - - /// - /// Create a Socks4a proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - public Socks4aProxyClient(string proxyHost, int proxyPort) - : base(proxyHost, proxyPort) - { } - - /// - /// Gets String representing the name of the proxy. - /// - /// This property will always return the value 'SOCKS4a' - public override string ProxyName - { - get { return PROXY_NAME; } - } - - - /// - /// Sends a command to the proxy server. - /// - /// Proxy server data stream. - /// Proxy byte command to execute. - /// Destination host name or IP address. - /// Destination port number - /// IDENTD user ID value. - /// - /// This method override the SendCommand message in the Sock4ProxyClient object. The override adds support for the - /// Socks4a extensions which allow the proxy client to optionally command the proxy server to resolve the - /// destination host IP address. - /// - internal override void SendCommand(NetworkStream proxy, byte command, string destinationHost, int destinationPort, string userId) - { - // PROXY SERVER REQUEST - //Please read SOCKS4.protocol first for an description of the version 4 - //protocol. This extension is intended to allow the use of SOCKS on hosts - //which are not capable of resolving all domain names. - // - //In version 4, the client sends the following packet to the SOCKS server - //to request a CONNECT or a BIND operation: - // - // +----+----+----+----+----+----+----+----+----+----+....+----+ - // | VN | CD | DSTPORT | DSTIP | USERID |NULL| - // +----+----+----+----+----+----+----+----+----+----+....+----+ - // # of bytes: 1 1 2 4 variable 1 - // - //VN is the SOCKS protocol version number and should be 4. CD is the - //SOCKS command code and should be 1 for CONNECT or 2 for BIND. NULL - //is a byte of all zero bits. - // - //For version 4A, if the client cannot resolve the destination host's - //domain name to find its IP address, it should set the first three bytes - //of DSTIP to NULL and the last byte to a non-zero value. (This corresponds - //to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The - //Internet Assigned Numbers Authority -- such an address is inadmissible - //as a destination IP address and thus should never occur if the client - //can resolve the domain name.) Following the NULL byte terminating - //USERID, the client must sends the destination domain name and termiantes - //it with another NULL byte. This is used for both CONNECT and BIND requests. - // - //A server using protocol 4A must check the DSTIP in the request packet. - //If it represent address 0.0.0.x with nonzero x, the server must read - //in the domain name that the client sends in the packet. The server - //should resolve the domain name and make connection to the destination - //host if it can. - // - //SOCKSified sockd may pass domain names that it cannot resolve to - //the next-hop SOCKS server. - - // userId needs to be a zero length string so that the GetBytes method - // works properly - if (userId == null) - userId = ""; - - byte[] destIp = {0,0,0,1}; // build the invalid ip address as specified in the 4a protocol - byte[] destPort = GetDestinationPortBytes(destinationPort); - byte[] userIdBytes = ASCIIEncoding.ASCII.GetBytes(userId); - byte[] hostBytes = ASCIIEncoding.ASCII.GetBytes(destinationHost); - byte[] request = new byte[10 + userIdBytes.Length + hostBytes.Length]; - - // set the bits on the request byte array - request[0] = SOCKS4_VERSION_NUMBER; - request[1] = command; - destPort.CopyTo(request, 2); - destIp.CopyTo(request, 4); - userIdBytes.CopyTo(request, 8); // copy the userid to the request byte array - request[8 + userIdBytes.Length] = 0x00; // null (byte with all zeros) terminator for userId - hostBytes.CopyTo(request, 9 + userIdBytes.Length); // copy the host name to the request byte array - request[9 + userIdBytes.Length + hostBytes.Length] = 0x00; // null (byte with all zeros) terminator for userId - - // send the connect request - proxy.Write(request, 0, request.Length); - - // wait for the proxy server to send a response - base.WaitForData(proxy); - - // PROXY SERVER RESPONSE - // The SOCKS server checks to see whether such a request should be granted - // based on any combination of source IP address, destination IP address, - // destination port number, the userid, and information it may obtain by - // consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS - // server makes a connection to the specified port of the destination host. - // A reply packet is sent to the client when this connection is established, - // or when the request is rejected or the operation fails. - // - // +----+----+----+----+----+----+----+----+ - // | VN | CD | DSTPORT | DSTIP | - // +----+----+----+----+----+----+----+----+ - // # of bytes: 1 1 2 4 - // - // VN is the version of the reply code and should be 0. CD is the result - // code with one of the following values: - // - // 90: request granted - // 91: request rejected or failed - // 92: request rejected becuase SOCKS server cannot connect to - // identd on the client - // 93: request rejected because the client program and identd - // report different user-ids - // - // The remaining fields are ignored. - // - // The SOCKS server closes its connection immediately after notifying - // the client of a failed or rejected request. For a successful request, - // the SOCKS server gets ready to relay traffic on both directions. This - // enables the client to do I/O on its connection as if it were directly - // connected to the application server. - - // create an 8 byte response array - byte[] response = new byte[8]; - - // read the resonse from the network stream - proxy.Read(response, 0, 8); - - // evaluate the reply code for an error condition - if (response[1] != SOCKS4_CMD_REPLY_REQUEST_GRANTED) - HandleProxyCommandError(response, destinationHost, destinationPort); - } - - - - } -} diff --git a/MinecraftClient/Proxy/Handlers/Socks5ProxyClient.cs b/MinecraftClient/Proxy/Handlers/Socks5ProxyClient.cs deleted file mode 100644 index a001e12b..00000000 --- a/MinecraftClient/Proxy/Handlers/Socks5ProxyClient.cs +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Authors: Benton Stark - * - * Copyright (c) 2007-2012 Starksoft, LLC (http://www.starksoft.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -using System; -using System.Text; -using System.Net; -using System.Net.Sockets; -using System.Globalization; -using System.ComponentModel; - -namespace Starksoft.Net.Proxy -{ - /// - /// Socks5 connection proxy class. This class implements the Socks5 standard proxy protocol. - /// - /// - /// This implementation supports TCP proxy connections with a Socks v5 server. - /// - public class Socks5ProxyClient : IProxyClient - { - private string _proxyHost; - private int _proxyPort; - private string _proxyUserName; - private string _proxyPassword; - private SocksAuthentication _proxyAuthMethod; - private TcpClient _tcpClient; - private TcpClient _tcpClientCached; - - private const string PROXY_NAME = "SOCKS5"; - private const int SOCKS5_DEFAULT_PORT = 1080; - - private const byte SOCKS5_VERSION_NUMBER = 5; - private const byte SOCKS5_RESERVED = 0x00; - private const byte SOCKS5_AUTH_NUMBER_OF_AUTH_METHODS_SUPPORTED = 2; - private const byte SOCKS5_AUTH_METHOD_NO_AUTHENTICATION_REQUIRED = 0x00; - private const byte SOCKS5_AUTH_METHOD_GSSAPI = 0x01; - private const byte SOCKS5_AUTH_METHOD_USERNAME_PASSWORD = 0x02; - private const byte SOCKS5_AUTH_METHOD_IANA_ASSIGNED_RANGE_BEGIN = 0x03; - private const byte SOCKS5_AUTH_METHOD_IANA_ASSIGNED_RANGE_END = 0x7f; - private const byte SOCKS5_AUTH_METHOD_RESERVED_RANGE_BEGIN = 0x80; - private const byte SOCKS5_AUTH_METHOD_RESERVED_RANGE_END = 0xfe; - private const byte SOCKS5_AUTH_METHOD_REPLY_NO_ACCEPTABLE_METHODS = 0xff; - private const byte SOCKS5_CMD_CONNECT = 0x01; - private const byte SOCKS5_CMD_BIND = 0x02; - private const byte SOCKS5_CMD_UDP_ASSOCIATE = 0x03; - private const byte SOCKS5_CMD_REPLY_SUCCEEDED = 0x00; - private const byte SOCKS5_CMD_REPLY_GENERAL_SOCKS_SERVER_FAILURE = 0x01; - private const byte SOCKS5_CMD_REPLY_CONNECTION_NOT_ALLOWED_BY_RULESET = 0x02; - private const byte SOCKS5_CMD_REPLY_NETWORK_UNREACHABLE = 0x03; - private const byte SOCKS5_CMD_REPLY_HOST_UNREACHABLE = 0x04; - private const byte SOCKS5_CMD_REPLY_CONNECTION_REFUSED = 0x05; - private const byte SOCKS5_CMD_REPLY_TTL_EXPIRED = 0x06; - private const byte SOCKS5_CMD_REPLY_COMMAND_NOT_SUPPORTED = 0x07; - private const byte SOCKS5_CMD_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; - private const byte SOCKS5_ADDRTYPE_IPV4 = 0x01; - private const byte SOCKS5_ADDRTYPE_DOMAIN_NAME = 0x03; - private const byte SOCKS5_ADDRTYPE_IPV6 = 0x04; - - /// - /// Authentication itemType. - /// - private enum SocksAuthentication - { - /// - /// No authentication used. - /// - None, - /// - /// Username and password authentication. - /// - UsernamePassword - } - - /// - /// Create a Socks5 proxy client object. - /// - public Socks5ProxyClient() { } - - /// - /// Creates a Socks5 proxy client object using the supplied TcpClient object connection. - /// - /// A TcpClient connection object. - public Socks5ProxyClient(TcpClient tcpClient) - { - if (tcpClient == null) - throw new ArgumentNullException("tcpClient"); - - _tcpClientCached = tcpClient; - } - - /// - /// Create a Socks5 proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - public Socks5ProxyClient(string proxyHost) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - _proxyHost = proxyHost; - _proxyPort = SOCKS5_DEFAULT_PORT; - } - - /// - /// Create a Socks5 proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - public Socks5ProxyClient(string proxyHost, int proxyPort) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - } - - /// - /// Create a Socks5 proxy client object. The default proxy port 1080 is used. - /// - /// Host name or IP address of the proxy server. - /// Proxy authentication user name. - /// Proxy authentication password. - public Socks5ProxyClient(string proxyHost, string proxyUserName, string proxyPassword) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyUserName == null) - throw new ArgumentNullException("proxyUserName"); - - if (proxyPassword == null) - throw new ArgumentNullException("proxyPassword"); - - _proxyHost = proxyHost; - _proxyPort = SOCKS5_DEFAULT_PORT; - _proxyUserName = proxyUserName; - _proxyPassword = proxyPassword; - } - - /// - /// Create a Socks5 proxy client object. - /// - /// Host name or IP address of the proxy server. - /// Port used to connect to proxy server. - /// Proxy authentication user name. - /// Proxy authentication password. - public Socks5ProxyClient(string proxyHost, int proxyPort, string proxyUserName, string proxyPassword) - { - if (String.IsNullOrEmpty(proxyHost)) - throw new ArgumentNullException("proxyHost"); - - if (proxyPort <= 0 || proxyPort > 65535) - throw new ArgumentOutOfRangeException("proxyPort", "port must be greater than zero and less than 65535"); - - if (proxyUserName == null) - throw new ArgumentNullException("proxyUserName"); - - if (proxyPassword == null) - throw new ArgumentNullException("proxyPassword"); - - _proxyHost = proxyHost; - _proxyPort = proxyPort; - _proxyUserName = proxyUserName; - _proxyPassword = proxyPassword; - } - - /// - /// Gets or sets host name or IP address of the proxy server. - /// - public string ProxyHost - { - get { return _proxyHost; } - set { _proxyHost = value; } - } - - /// - /// Gets or sets port used to connect to proxy server. - /// - public int ProxyPort - { - get { return _proxyPort; } - set { _proxyPort = value; } - } - - /// - /// Gets String representing the name of the proxy. - /// - /// This property will always return the value 'SOCKS5' - public string ProxyName - { - get { return PROXY_NAME; } - } - - /// - /// Gets or sets proxy authentication user name. - /// - public string ProxyUserName - { - get { return _proxyUserName; } - set { _proxyUserName = value; } - } - - /// - /// Gets or sets proxy authentication password. - /// - public string ProxyPassword - { - get { return _proxyPassword; } - set { _proxyPassword = value; } - } - - /// - /// Gets or sets the TcpClient object. - /// This property can be set prior to executing CreateConnection to use an existing TcpClient connection. - /// - public TcpClient TcpClient - { - get { return _tcpClientCached; } - set { _tcpClientCached = value; } - } - - /// - /// Creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address of the destination server. - /// Port number to connect to on the destination host. - /// - /// Returns an open TcpClient object that can be used normally to communicate - /// with the destination server - /// - /// - /// This method creates a connection to the proxy server and instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - public TcpClient CreateConnection(string destinationHost, int destinationPort) - { - if (String.IsNullOrEmpty(destinationHost)) - throw new ArgumentNullException("destinationHost"); - - if (destinationPort <= 0 || destinationPort > 65535) - throw new ArgumentOutOfRangeException("destinationPort", "port must be greater than zero and less than 65535"); - - try - { - // if we have no cached tcpip connection then create one - if (_tcpClientCached == null) - { - if (String.IsNullOrEmpty(_proxyHost)) - throw new ProxyException("ProxyHost property must contain a value."); - - if (_proxyPort <= 0 || _proxyPort > 65535) - throw new ProxyException("ProxyPort value must be greater than zero and less than 65535"); - - // create new tcp client object to the proxy server - _tcpClient = new TcpClient(); - - // attempt to open the connection - _tcpClient.Connect(_proxyHost, _proxyPort); - } - else - { - _tcpClient = _tcpClientCached; - } - - // determine which authentication method the client would like to use - DetermineClientAuthMethod(); - - // negotiate which authentication methods are supported / accepted by the server - NegotiateServerAuthMethod(); - - // send a connect command to the proxy server for destination host and port - SendCommand(SOCKS5_CMD_CONNECT, destinationHost, destinationPort); - - // remove the private reference to the tcp client so the proxy object does not keep it - // return the open proxied tcp client object to the caller for normal use - TcpClient rtn = _tcpClient; - _tcpClient = null; - return rtn; - } - catch (Exception ex) - { - throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "Connection to proxy host {0} on port {1} failed.", Utils.GetHost(_tcpClient), Utils.GetPort(_tcpClient)), ex); - } - } - - - private void DetermineClientAuthMethod() - { - // set the authentication itemType used based on values inputed by the user - if (_proxyUserName != null && _proxyPassword != null) - _proxyAuthMethod = SocksAuthentication.UsernamePassword; - else - _proxyAuthMethod = SocksAuthentication.None; - } - - private void NegotiateServerAuthMethod() - { - // get a reference to the network stream - NetworkStream stream = _tcpClient.GetStream(); - - // SERVER AUTHENTICATION REQUEST - // The client connects to the server, and sends a version - // identifier/method selection message: - // - // +----+----------+----------+ - // |VER | NMETHODS | METHODS | - // +----+----------+----------+ - // | 1 | 1 | 1 to 255 | - // +----+----------+----------+ - - byte[] authRequest = new byte[4]; - authRequest[0] = SOCKS5_VERSION_NUMBER; - authRequest[1] = SOCKS5_AUTH_NUMBER_OF_AUTH_METHODS_SUPPORTED; - authRequest[2] = SOCKS5_AUTH_METHOD_NO_AUTHENTICATION_REQUIRED; - authRequest[3] = SOCKS5_AUTH_METHOD_USERNAME_PASSWORD; - - // send the request to the server specifying authentication types supported by the client. - stream.Write(authRequest, 0, authRequest.Length); - - // SERVER AUTHENTICATION RESPONSE - // The server selects from one of the methods given in METHODS, and - // sends a METHOD selection message: - // - // +----+--------+ - // |VER | METHOD | - // +----+--------+ - // | 1 | 1 | - // +----+--------+ - // - // If the selected METHOD is X'FF', none of the methods listed by the - // client are acceptable, and the client MUST close the connection. - // - // The values currently defined for METHOD are: - // * X'00' NO AUTHENTICATION REQUIRED - // * X'01' GSSAPI - // * X'02' USERNAME/PASSWORD - // * X'03' to X'7F' IANA ASSIGNED - // * X'80' to X'FE' RESERVED FOR PRIVATE METHODS - // * X'FF' NO ACCEPTABLE METHODS - - // receive the server response - byte[] response = new byte[2]; - stream.Read(response, 0, response.Length); - - // the first byte contains the socks version number (e.g. 5) - // the second byte contains the auth method acceptable to the proxy server - byte acceptedAuthMethod = response[1]; - - // if the server does not accept any of our supported authenication methods then throw an error - if (acceptedAuthMethod == SOCKS5_AUTH_METHOD_REPLY_NO_ACCEPTABLE_METHODS) - { - _tcpClient.Close(); - throw new ProxyException("The proxy destination does not accept the supported proxy client authentication methods."); - } - - // if the server accepts a username and password authentication and none is provided by the user then throw an error - if (acceptedAuthMethod == SOCKS5_AUTH_METHOD_USERNAME_PASSWORD && _proxyAuthMethod == SocksAuthentication.None) - { - _tcpClient.Close(); - throw new ProxyException("The proxy destination requires a username and password for authentication."); - } - - if (acceptedAuthMethod == SOCKS5_AUTH_METHOD_USERNAME_PASSWORD) - { - - // USERNAME / PASSWORD SERVER REQUEST - // Once the SOCKS V5 server has started, and the client has selected the - // Username/Password Authentication protocol, the Username/Password - // subnegotiation begins. This begins with the client producing a - // Username/Password request: - // - // +----+------+----------+------+----------+ - // |VER | ULEN | UNAME | PLEN | PASSWD | - // +----+------+----------+------+----------+ - // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | - // +----+------+----------+------+----------+ - - // create a data structure (binary array) containing credentials - // to send to the proxy server which consists of clear username and password data - byte[] credentials = new byte[_proxyUserName.Length + _proxyPassword.Length + 3]; - - // for SOCKS5 username/password authentication the VER field must be set to 0x01 - // http://en.wikipedia.org/wiki/SOCKS - // field 1: version number, 1 byte (must be 0x01)" - credentials[0] = 0x01; - credentials[1] = (byte)_proxyUserName.Length; - Array.Copy(ASCIIEncoding.ASCII.GetBytes(_proxyUserName), 0, credentials, 2, _proxyUserName.Length); - credentials[_proxyUserName.Length + 2] = (byte)_proxyPassword.Length; - Array.Copy(ASCIIEncoding.ASCII.GetBytes(_proxyPassword), 0, credentials, _proxyUserName.Length + 3, _proxyPassword.Length); - - // USERNAME / PASSWORD SERVER RESPONSE - // The server verifies the supplied UNAME and PASSWD, and sends the - // following response: - // - // +----+--------+ - // |VER | STATUS | - // +----+--------+ - // | 1 | 1 | - // +----+--------+ - // - // A STATUS field of X'00' indicates success. If the server returns a - // `failure' (STATUS value other than X'00') status, it MUST close the - // connection. - - // transmit credentials to the proxy server - stream.Write(credentials, 0, credentials.Length); - - // read the response from the proxy server - byte[] crResponse = new byte[2]; - stream.Read(crResponse, 0, crResponse.Length); - - // check to see if the proxy server accepted the credentials - if (crResponse[1] != 0) - { - _tcpClient.Close(); - throw new ProxyException("Proxy authentification failure! The proxy server has reported that the userid and/or password is not valid."); - } - - } - } - - private byte GetDestAddressType(string host) - { - IPAddress ipAddr = null; - - bool result = IPAddress.TryParse(host, out ipAddr); - - if (!result) - return SOCKS5_ADDRTYPE_DOMAIN_NAME; - - switch (ipAddr.AddressFamily) - { - case AddressFamily.InterNetwork: - return SOCKS5_ADDRTYPE_IPV4; - case AddressFamily.InterNetworkV6: - return SOCKS5_ADDRTYPE_IPV6; - default: - throw new ProxyException(String.Format(CultureInfo.InvariantCulture, "The host addess {0} of type '{1}' is not a supported address type. The supported types are InterNetwork and InterNetworkV6.", host, Enum.GetName(typeof(AddressFamily), ipAddr.AddressFamily))); - } - - } - - private byte[] GetDestAddressBytes(byte addressType, string host) - { - switch (addressType) - { - case SOCKS5_ADDRTYPE_IPV4: - case SOCKS5_ADDRTYPE_IPV6: - return IPAddress.Parse(host).GetAddressBytes(); - case SOCKS5_ADDRTYPE_DOMAIN_NAME: - // create a byte array to hold the host name bytes plus one byte to store the length - byte[] bytes = new byte[host.Length + 1]; - // if the address field contains a fully-qualified domain name. The first - // octet of the address field contains the number of octets of name that - // follow, there is no terminating NUL octet. - bytes[0] = Convert.ToByte(host.Length); - Encoding.ASCII.GetBytes(host).CopyTo(bytes, 1); - return bytes; - default: - return null; - } - } - - private byte[] GetDestPortBytes(int value) - { - byte[] array = new byte[2]; - array[0] = Convert.ToByte(value / 256); - array[1] = Convert.ToByte(value % 256); - return array; - } - - private void SendCommand(byte command, string destinationHost, int destinationPort) - { - NetworkStream stream = _tcpClient.GetStream(); - - byte addressType = GetDestAddressType(destinationHost); - byte[] destAddr = GetDestAddressBytes(addressType, destinationHost); - byte[] destPort = GetDestPortBytes(destinationPort); - - // The connection request is made up of 6 bytes plus the - // length of the variable address byte array - // - // +----+-----+-------+------+----------+----------+ - // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | - // +----+-----+-------+------+----------+----------+ - // | 1 | 1 | X'00' | 1 | Variable | 2 | - // +----+-----+-------+------+----------+----------+ - // - // * VER protocol version: X'05' - // * CMD - // * CONNECT X'01' - // * BIND X'02' - // * UDP ASSOCIATE X'03' - // * RSV RESERVED - // * ATYP address itemType of following address - // * IP V4 address: X'01' - // * DOMAINNAME: X'03' - // * IP V6 address: X'04' - // * DST.ADDR desired destination address - // * DST.PORT desired destination port in network octet order - - byte[] request = new byte[4 + destAddr.Length + 2]; - request[0] = SOCKS5_VERSION_NUMBER; - request[1] = command; - request[2] = SOCKS5_RESERVED; - request[3] = addressType; - destAddr.CopyTo(request, 4); - destPort.CopyTo(request, 4 + destAddr.Length); - - // send connect request. - stream.Write(request, 0, request.Length); - - // PROXY SERVER RESPONSE - // +----+-----+-------+------+----------+----------+ - // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | - // +----+-----+-------+------+----------+----------+ - // | 1 | 1 | X'00' | 1 | Variable | 2 | - // +----+-----+-------+------+----------+----------+ - // - // * VER protocol version: X'05' - // * REP Reply field: - // * X'00' succeeded - // * X'01' general SOCKS server failure - // * X'02' connection not allowed by ruleset - // * X'03' Network unreachable - // * X'04' Host unreachable - // * X'05' Connection refused - // * X'06' TTL expired - // * X'07' Command not supported - // * X'08' Address itemType not supported - // * X'09' to X'FF' unassigned - //* RSV RESERVED - //* ATYP address itemType of following address - - byte[] response = new byte[255]; - - // read proxy server response - stream.Read(response, 0, response.Length); - - byte replyCode = response[1]; - - // evaluate the reply code for an error condition - if (replyCode != SOCKS5_CMD_REPLY_SUCCEEDED) - HandleProxyCommandError(response, destinationHost, destinationPort ); - } - - private void HandleProxyCommandError(byte[] response, string destinationHost, int destinationPort) - { - string proxyErrorText; - byte replyCode = response[1]; - byte addrType = response[3]; - string addr = ""; - Int16 port = 0; - - switch (addrType) - { - case SOCKS5_ADDRTYPE_DOMAIN_NAME: - int addrLen = Convert.ToInt32(response[4]); - byte[] addrBytes = new byte[addrLen]; - for (int i = 0; i < addrLen; i++) - addrBytes[i] = response[i + 5]; - addr = System.Text.ASCIIEncoding.ASCII.GetString(addrBytes); - byte[] portBytesDomain = new byte[2]; - portBytesDomain[0] = response[6 + addrLen]; - portBytesDomain[1] = response[5 + addrLen]; - port = BitConverter.ToInt16(portBytesDomain, 0); - break; - - case SOCKS5_ADDRTYPE_IPV4: - byte[] ipv4Bytes = new byte[4]; - for (int i = 0; i < 4; i++) - ipv4Bytes[i] = response[i + 4]; - IPAddress ipv4 = new IPAddress(ipv4Bytes); - addr = ipv4.ToString(); - byte[] portBytesIpv4 = new byte[2]; - portBytesIpv4[0] = response[9]; - portBytesIpv4[1] = response[8]; - port = BitConverter.ToInt16(portBytesIpv4, 0); - break; - - case SOCKS5_ADDRTYPE_IPV6: - byte[] ipv6Bytes = new byte[16]; - for (int i = 0; i < 16; i++) - ipv6Bytes[i] = response[i + 4]; - IPAddress ipv6 = new IPAddress(ipv6Bytes); - addr = ipv6.ToString(); - byte[] portBytesIpv6 = new byte[2]; - portBytesIpv6[0] = response[21]; - portBytesIpv6[1] = response[20]; - port = BitConverter.ToInt16(portBytesIpv6, 0); - break; - } - - - switch (replyCode) - { - case SOCKS5_CMD_REPLY_GENERAL_SOCKS_SERVER_FAILURE: - proxyErrorText = "a general socks destination failure occurred"; - break; - case SOCKS5_CMD_REPLY_CONNECTION_NOT_ALLOWED_BY_RULESET: - proxyErrorText = "the connection is not allowed by proxy destination rule set"; - break; - case SOCKS5_CMD_REPLY_NETWORK_UNREACHABLE: - proxyErrorText = "the network was unreachable"; - break; - case SOCKS5_CMD_REPLY_HOST_UNREACHABLE: - proxyErrorText = "the host was unreachable"; - break; - case SOCKS5_CMD_REPLY_CONNECTION_REFUSED: - proxyErrorText = "the connection was refused by the remote network"; - break; - case SOCKS5_CMD_REPLY_TTL_EXPIRED: - proxyErrorText = "the time to live (TTL) has expired"; - break; - case SOCKS5_CMD_REPLY_COMMAND_NOT_SUPPORTED: - proxyErrorText = "the command issued by the proxy client is not supported by the proxy destination"; - break; - case SOCKS5_CMD_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: - proxyErrorText = "the address type specified is not supported"; - break; - default: - proxyErrorText = String.Format(CultureInfo.InvariantCulture, "that an unknown reply with the code value '{0}' was received by the destination", replyCode.ToString(CultureInfo.InvariantCulture)); - break; - } - string exceptionMsg = String.Format(CultureInfo.InvariantCulture, "The {0} concerning destination host {1} port number {2}. The destination reported the host as {3} port {4}.", proxyErrorText, destinationHost, destinationPort, addr, port.ToString(CultureInfo.InvariantCulture)); - - throw new ProxyException(exceptionMsg); - - } - - -#region "Async Methods" - - private BackgroundWorker _asyncWorker; - private Exception _asyncException; - bool _asyncCancelled; - - /// - /// Gets a value indicating whether an asynchronous operation is running. - /// - /// Returns true if an asynchronous operation is running; otherwise, false. - /// - public bool IsBusy - { - get { return _asyncWorker == null ? false : _asyncWorker.IsBusy; } - } - - /// - /// Gets a value indicating whether an asynchronous operation is cancelled. - /// - /// Returns true if an asynchronous operation is cancelled; otherwise, false. - /// - public bool IsAsyncCancelled - { - get { return _asyncCancelled; } - } - - /// - /// Cancels any asychronous operation that is currently active. - /// - public void CancelAsync() - { - if (_asyncWorker != null && !_asyncWorker.CancellationPending && _asyncWorker.IsBusy) - { - _asyncCancelled = true; - _asyncWorker.CancelAsync(); - } - } - - private void CreateAsyncWorker() - { - if (_asyncWorker != null) - _asyncWorker.Dispose(); - _asyncException = null; - _asyncWorker = null; - _asyncCancelled = false; - _asyncWorker = new BackgroundWorker(); - } - - /// - /// Event handler for CreateConnectionAsync method completed. - /// - public event EventHandler CreateConnectionAsyncCompleted; - - - /// - /// Asynchronously creates a remote TCP connection through a proxy server to the destination host on the destination port. - /// - /// Destination host name or IP address. - /// Port number to connect to on the destination host. - /// - /// Returns TcpClient object that can be used normally to communicate - /// with the destination server. - /// - /// - /// This method instructs the proxy server - /// to make a pass through connection to the specified destination host on the specified - /// port. - /// - public void CreateConnectionAsync(string destinationHost, int destinationPort) - { - if (_asyncWorker != null && _asyncWorker.IsBusy) - throw new InvalidOperationException("The Socks4 object is already busy executing another asynchronous operation. You can only execute one asychronous method at a time."); - - CreateAsyncWorker(); - _asyncWorker.WorkerSupportsCancellation = true; - _asyncWorker.DoWork += new DoWorkEventHandler(CreateConnectionAsync_DoWork); - _asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CreateConnectionAsync_RunWorkerCompleted); - Object[] args = new Object[2]; - args[0] = destinationHost; - args[1] = destinationPort; - _asyncWorker.RunWorkerAsync(args); - } - - private void CreateConnectionAsync_DoWork(object sender, DoWorkEventArgs e) - { - try - { - Object[] args = (Object[])e.Argument; - e.Result = CreateConnection((string)args[0], (int)args[1]); - } - catch (Exception ex) - { - _asyncException = ex; - } - } - - private void CreateConnectionAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - if (CreateConnectionAsyncCompleted != null) - CreateConnectionAsyncCompleted(this, new CreateConnectionAsyncCompletedEventArgs(_asyncException, _asyncCancelled, (TcpClient)e.Result)); - } - - - -#endregion - } -} diff --git a/MinecraftClient/Proxy/Handlers/Utils.cs b/MinecraftClient/Proxy/Handlers/Utils.cs deleted file mode 100644 index bdee40c4..00000000 --- a/MinecraftClient/Proxy/Handlers/Utils.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Text; -using System.Globalization; -using System.Net.Sockets; - -namespace Starksoft.Net.Proxy -{ - internal static class Utils - { - internal static string GetHost(TcpClient client) - { - if (client == null) - throw new ArgumentNullException("client"); - - string host = ""; - try - { - host = ((System.Net.IPEndPoint)client.Client.RemoteEndPoint).Address.ToString(); - } - catch - { }; - - return host; - } - - internal static string GetPort(TcpClient client) - { - if (client == null) - throw new ArgumentNullException("client"); - - string port = ""; - try - { - port = ((System.Net.IPEndPoint)client.Client.RemoteEndPoint).Port.ToString(CultureInfo.InvariantCulture); - } - catch - { }; - - return port; - } - - } -} diff --git a/MinecraftClient/Proxy/ProxyHandler.cs b/MinecraftClient/Proxy/ProxyHandler.cs index 2bd54f28..9dbd1086 100644 --- a/MinecraftClient/Proxy/ProxyHandler.cs +++ b/MinecraftClient/Proxy/ProxyHandler.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Net.Sockets; -using Starksoft.Net.Proxy; +using System.Net.Sockets; +using Starksoft.Aspen.Proxy; namespace MinecraftClient.Proxy {