Unverified Commit 4c5d4cd7 authored by honfika's avatar honfika Committed by GitHub

Merge pull request #712 from justcoding121/master

beta
parents 8cbf0f43 b67ad5d5
......@@ -90,8 +90,12 @@ namespace Titanium.Web.Proxy.Examples.Basic
//};
//proxyServer.AddEndPoint(transparentEndPoint);
//proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpProxy = new ExternalProxy("localhost", 8888);
//proxyServer.UpStreamHttpsProxy = new ExternalProxy("localhost", 8888);
// SOCKS proxy
//proxyServer.UpStreamHttpProxy = new ExternalProxy("46.63.0.17", 4145) { ProxyType = ExternalProxyType.Socks4 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy("46.63.0.17", 4145) { ProxyType = ExternalProxyType.Socks4 };
foreach (var endPoint in proxyServer.ProxyEndPoints)
{
......
......@@ -5,24 +5,6 @@ namespace Titanium.Web.Proxy.Extensions
{
internal static class TcpExtensions
{
internal static void CloseSocket(this TcpClient tcpClient)
{
if (tcpClient == null)
{
return;
}
try
{
tcpClient.Close();
}
catch
{
// ignored
}
}
/// <summary>
/// Check if a TcpClient is good to be used.
/// This only checks if send is working so local socket is still connected.
......@@ -30,13 +12,11 @@ namespace Titanium.Web.Proxy.Extensions
/// So in our case we should retry with new connection from pool if first read after getting the connection fails.
/// https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.connected(v=vs.110).aspx
/// </summary>
/// <param name="client"></param>
/// <param name="socket"></param>
/// <returns></returns>
internal static bool IsGoodConnection(this TcpClient client)
internal static bool IsGoodConnection(this Socket socket)
{
var socket = client.Client;
if (!client.Connected || !socket.Connected)
if (!socket.Connected)
{
return false;
}
......
......@@ -2,6 +2,7 @@
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.Http
......@@ -103,10 +104,14 @@ namespace Titanium.Web.Proxy.Http
{
var upstreamProxy = Connection.UpStreamProxy;
bool useUpstreamProxy = upstreamProxy != null && Connection.IsHttps == false;
bool useUpstreamProxy = upstreamProxy != null && upstreamProxy.ProxyType == ExternalProxyType.Http &&
!Connection.IsHttps;
var serverStream = Connection.Stream;
string? upstreamProxyUserName = null;
string? upstreamProxyPassword = null;
string url;
if (!useUpstreamProxy || isTransparent)
{
......@@ -115,19 +120,13 @@ namespace Titanium.Web.Proxy.Http
else
{
url = Request.RequestUri.ToString();
}
string? upstreamProxyUserName = null;
string? upstreamProxyPassword = null;
// Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null
&& Connection.IsHttps == false
&& !string.IsNullOrEmpty(upstreamProxy.UserName)
&& upstreamProxy.Password != null)
{
upstreamProxyUserName = upstreamProxy.UserName;
upstreamProxyPassword = upstreamProxy.Password;
// Send Authentication to Upstream proxy if needed
if (!string.IsNullOrEmpty(upstreamProxy!.UserName) && upstreamProxy.Password != null)
{
upstreamProxyUserName = upstreamProxy.UserName;
upstreamProxyPassword = upstreamProxy.Password;
}
}
// prepare the request & headers
......
......@@ -25,6 +25,8 @@ namespace Titanium.Web.Proxy.Models
/// </summary>
public bool BypassLocalhost { get; set; }
public ExternalProxyType ProxyType { get; set; }
/// <summary>
/// Username.
/// </summary>
......@@ -111,4 +113,16 @@ namespace Titanium.Web.Proxy.Models
return $"{HostName}:{Port}";
}
}
public enum ExternalProxyType
{
/// <summary>A HTTP/HTTPS proxy server.</summary>
Http,
/// <summary>A SOCKS4[A] proxy server.</summary>
Socks4,
/// <summary>A SOCKS5 proxy server.</summary>
Socks5
}
}
......@@ -12,6 +12,8 @@
/// </summary>
bool BypassLocalhost { get; set; }
ExternalProxyType ProxyType { get; set; }
/// <summary>
/// Username.
/// </summary>
......
......@@ -18,9 +18,9 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
public object ClientUserData { get; set; }
internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient)
internal TcpClientConnection(ProxyServer proxyServer, Socket tcpClientSocket)
{
this.tcpClient = tcpClient;
this.tcpClientSocket = tcpClientSocket;
this.proxyServer = proxyServer;
this.proxyServer.UpdateClientConnectionCount(true);
}
......@@ -29,21 +29,21 @@ namespace Titanium.Web.Proxy.Network.Tcp
public Guid Id { get; } = Guid.NewGuid();
public EndPoint LocalEndPoint => tcpClient.Client.LocalEndPoint;
public EndPoint LocalEndPoint => tcpClientSocket.LocalEndPoint;
public EndPoint RemoteEndPoint => tcpClient.Client.RemoteEndPoint;
public EndPoint RemoteEndPoint => tcpClientSocket.RemoteEndPoint;
internal SslProtocols SslProtocol { get; set; }
internal SslApplicationProtocol NegotiatedApplicationProtocol { get; set; }
private readonly TcpClient tcpClient;
private readonly Socket tcpClientSocket;
private int? processId;
public Stream GetStream()
{
return tcpClient.GetStream();
return new NetworkStream(tcpClientSocket, true);
}
public int GetProcessId(ProxyEndPoint endPoint)
......@@ -86,7 +86,15 @@ namespace Titanium.Web.Proxy.Network.Tcp
// This way we can push tcp Time_Wait to client side when possible.
await Task.Delay(1000);
proxyServer.UpdateClientConnectionCount(false);
tcpClient.CloseSocket();
try
{
tcpClientSocket.Close();
}
catch
{
// ignore
}
});
}
}
......
......@@ -16,11 +16,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
public Guid Id { get; } = Guid.NewGuid();
internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient, HttpServerStream stream,
internal TcpServerConnection(ProxyServer proxyServer, Socket tcpSocket, HttpServerStream stream,
string hostName, int port, bool isHttps, SslApplicationProtocol negotiatedApplicationProtocol,
Version version, IExternalProxy? upStreamProxy, IPEndPoint? upStreamEndPoint, string cacheKey)
{
TcpClient = tcpClient;
TcpSocket = tcpSocket;
LastAccess = DateTime.Now;
this.proxyServer = proxyServer;
this.proxyServer.UpdateServerConnectionCount(true);
......@@ -63,7 +63,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary>
/// The TcpClient.
/// </summary>
internal TcpClient TcpClient { get; }
internal Socket TcpSocket { get; }
/// <summary>
/// Used to write lines to server
......@@ -98,7 +98,15 @@ namespace Titanium.Web.Proxy.Network.Tcp
await Task.Delay(1000);
proxyServer.UpdateServerConnectionCount(false);
Stream.Dispose();
TcpClient.CloseSocket();
try
{
TcpSocket.Close();
}
catch
{
// ignore
}
});
}
......
......@@ -359,12 +359,12 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Customize TcpClient used for client connection upon create.
/// </summary>
public event AsyncEventHandler<TcpClient>? OnClientConnectionCreate;
public event AsyncEventHandler<Socket>? OnClientConnectionCreate;
/// <summary>
/// Customize TcpClient used for server connection upon create.
/// </summary>
public event AsyncEventHandler<TcpClient>? OnServerConnectionCreate;
public event AsyncEventHandler<Socket>? OnServerConnectionCreate;
/// <summary>
/// Customize the minimum ThreadPool size (increase it on a server)
......@@ -733,12 +733,12 @@ namespace Titanium.Web.Proxy
{
var endPoint = (ProxyEndPoint)asyn.AsyncState;
TcpClient? tcpClient = null;
Socket? tcpClient = null;
try
{
// based on end point type call appropriate request handlers
tcpClient = endPoint.Listener!.EndAcceptTcpClient(asyn);
tcpClient = endPoint.Listener!.EndAcceptSocket(asyn);
tcpClient.NoDelay = NoDelay;
}
catch (ObjectDisposedException)
......@@ -784,19 +784,19 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Handle the client.
/// </summary>
/// <param name="tcpClient">The client.</param>
/// <param name="tcpClientSocket">The client socket.</param>
/// <param name="endPoint">The proxy endpoint.</param>
/// <returns>The task.</returns>
private async Task handleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
private async Task handleClient(Socket tcpClientSocket, ProxyEndPoint endPoint)
{
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
tcpClientSocket.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClientSocket.SendTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds);
tcpClientSocket.LingerState = new LingerOption(true, TcpTimeWaitSeconds);
await InvokeClientConnectionCreateEvent(tcpClient);
await InvokeClientConnectionCreateEvent(tcpClientSocket);
using (var clientConnection = new TcpClientConnection(this, tcpClient))
using (var clientConnection = new TcpClientConnection(this, tcpClientSocket))
{
if (endPoint is TransparentProxyEndPoint tep)
{
......@@ -867,28 +867,28 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Invoke client tcp connection events if subscribed by API user.
/// </summary>
/// <param name="client">The TcpClient object.</param>
/// <param name="clientSocket">The TcpClient object.</param>
/// <returns></returns>
internal async Task InvokeClientConnectionCreateEvent(TcpClient client)
internal async Task InvokeClientConnectionCreateEvent(Socket clientSocket)
{
// client connection created
if (OnClientConnectionCreate != null)
{
await OnClientConnectionCreate.InvokeAsync(this, client, ExceptionFunc);
await OnClientConnectionCreate.InvokeAsync(this, clientSocket, ExceptionFunc);
}
}
/// <summary>
/// Invoke server tcp connection events if subscribed by API user.
/// </summary>
/// <param name="client">The TcpClient object.</param>
/// <param name="serverSocket">The Socket object.</param>
/// <returns></returns>
internal async Task InvokeServerConnectionCreateEvent(TcpClient client)
internal async Task InvokeServerConnectionCreateEvent(Socket serverSocket)
{
// server connection created
if (OnServerConnectionCreate != null)
{
await OnServerConnectionCreate.InvokeAsync(this, client, ExceptionFunc);
await OnServerConnectionCreate.InvokeAsync(this, serverSocket, ExceptionFunc);
}
}
......
/*
Copyright © 2002, The KPD-Team
All rights reserved.
http://www.mentalis.org/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the KPD-Team, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Net;
using System.Net.Sockets;
namespace Titanium.Web.Proxy.ProxySocket.Authentication
{
/// <summary>
/// Implements a SOCKS authentication scheme.
/// </summary>
/// <remarks>This is an abstract class; it must be inherited.</remarks>
internal abstract class AuthMethod
{
/// <summary>
/// Initializes an AuthMethod instance.
/// </summary>
/// <param name="server">The socket connection with the proxy server.</param>
public AuthMethod(Socket server)
{
Server = server;
}
/// <summary>
/// Authenticates the user.
/// </summary>
/// <exception cref="ProxyException">Authentication with the proxy server failed.</exception>
/// <exception cref="ProtocolViolationException">The proxy server uses an invalid protocol.</exception>
/// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception>
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
public abstract void Authenticate();
/// <summary>
/// Authenticates the user asynchronously.
/// </summary>
/// <param name="callback">The method to call when the authentication is complete.</param>
/// <exception cref="ProxyException">Authentication with the proxy server failed.</exception>
/// <exception cref="ProtocolViolationException">The proxy server uses an invalid protocol.</exception>
/// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception>
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
public abstract void BeginAuthenticate(HandShakeComplete callback);
/// <summary>
/// Gets or sets the socket connection with the proxy server.
/// </summary>
/// <value>The socket connection with the proxy server.</value>
protected Socket Server
{
get
{
return _server;
}
set
{
if (value == null)
throw new ArgumentNullException();
_server = value;
}
}
/// <summary>
/// Gets or sets a byt array that can be used to store data.
/// </summary>
/// <value>A byte array to store data.</value>
protected byte[] Buffer
{
get
{
return _buffer;
}
set
{
_buffer = value;
}
}
/// <summary>
/// Gets or sets the number of bytes that have been received from the remote proxy server.
/// </summary>
/// <value>An integer that holds the number of bytes that have been received from the remote proxy server.</value>
protected int Received
{
get
{
return _received;
}
set
{
_received = value;
}
}
// private variables
/// <summary>Holds the value of the Buffer property.</summary>
private byte[] _buffer;
/// <summary>Holds the value of the Server property.</summary>
private Socket _server;
/// <summary>Holds the address of the method to call when the proxy has authenticated the client.</summary>
protected HandShakeComplete CallBack;
/// <summary>Holds the value of the Received property.</summary>
private int _received;
}
}
/*
Copyright © 2002, The KPD-Team
All rights reserved.
http://www.mentalis.org/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the KPD-Team, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Net.Sockets;
namespace Titanium.Web.Proxy.ProxySocket.Authentication
{
/// <summary>
/// This class implements the 'No Authentication' scheme.
/// </summary>
internal sealed class AuthNone : AuthMethod
{
/// <summary>
/// Initializes an AuthNone instance.
/// </summary>
/// <param name="server">The socket connection with the proxy server.</param>
public AuthNone(Socket server) : base(server) { }
/// <summary>
/// Authenticates the user.
/// </summary>
public override void Authenticate()
{
return; // Do Nothing
}
/// <summary>
/// Authenticates the user asynchronously.
/// </summary>
/// <param name="callback">The method to call when the authentication is complete.</param>
/// <remarks>This method immediately calls the callback method.</remarks>
public override void BeginAuthenticate(HandShakeComplete callback)
{
callback(null);
}
}
}
/*
Copyright © 2002, The KPD-Team
All rights reserved.
http://www.mentalis.org/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the KPD-Team, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Net.Sockets;
using System.Text;
namespace Titanium.Web.Proxy.ProxySocket.Authentication
{
/// <summary>
/// This class implements the 'username/password authentication' scheme.
/// </summary>
internal sealed class AuthUserPass : AuthMethod
{
/// <summary>
/// Initializes a new AuthUserPass instance.
/// </summary>
/// <param name="server">The socket connection with the proxy server.</param>
/// <param name="user">The username to use.</param>
/// <param name="pass">The password to use.</param>
/// <exception cref="ArgumentNullException"><c>user</c> -or- <c>pass</c> is null.</exception>
public AuthUserPass(Socket server, string user, string pass) : base(server)
{
Username = user;
Password = pass;
}
/// <summary>
/// Creates an array of bytes that has to be sent if the user wants to authenticate with the username/password authentication scheme.
/// </summary>
/// <returns>An array of bytes that has to be sent if the user wants to authenticate with the username/password authentication scheme.</returns>
private byte[] GetAuthenticationBytes()
{
byte[] buffer = new byte[3 + Username.Length + Password.Length];
buffer[0] = 1;
buffer[1] = (byte)Username.Length;
Array.Copy(Encoding.ASCII.GetBytes(Username), 0, buffer, 2, Username.Length);
buffer[Username.Length + 2] = (byte)Password.Length;
Array.Copy(Encoding.ASCII.GetBytes(Password), 0, buffer, Username.Length + 3, Password.Length);
return buffer;
}
private int GetAuthenticationLength()
{
return 3 + Username.Length + Password.Length;
}
/// <summary>
/// Starts the authentication process.
/// </summary>
public override void Authenticate()
{
if (Server.Send(GetAuthenticationBytes()) < GetAuthenticationLength())
{
throw new SocketException(10054);
}
;
byte[] buffer = new byte[2];
int received = 0;
while (received != 2)
{
int recv = Server.Receive(buffer, received, 2 - received, SocketFlags.None);
if (recv == 0)
throw new SocketException(10054);
received += recv;
}
if (buffer[1] != 0)
{
Server.Close();
throw new ProxyException("Username/password combination rejected.");
}
return;
}
/// <summary>
/// Starts the asynchronous authentication process.
/// </summary>
/// <param name="callback">The method to call when the authentication is complete.</param>
public override void BeginAuthenticate(HandShakeComplete callback)
{
CallBack = callback;
Server.BeginSend(GetAuthenticationBytes(), 0, GetAuthenticationLength(), SocketFlags.None,
new AsyncCallback(this.OnSent), Server);
return;
}
/// <summary>
/// Called when the authentication bytes have been sent.
/// </summary>
/// <param name="ar">Stores state information for this asynchronous operation as well as any user-defined data.</param>
private void OnSent(IAsyncResult ar)
{
try
{
if (Server.EndSend(ar) < GetAuthenticationLength())
throw new SocketException(10054);
Buffer = new byte[2];
Server.BeginReceive(Buffer, 0, 2, SocketFlags.None, new AsyncCallback(this.OnReceive), Server);
}
catch (Exception e)
{
CallBack(e);
}
}
/// <summary>
/// Called when the socket received an authentication reply.
/// </summary>
/// <param name="ar">Stores state information for this asynchronous operation as well as any user-defined data.</param>
private void OnReceive(IAsyncResult ar)
{
try
{
int recv = Server.EndReceive(ar);
if (recv <= 0)
throw new SocketException(10054);
Received += recv;
if (Received == Buffer.Length)
if (Buffer[1] == 0)
CallBack(null);
else
throw new ProxyException("Username/password combination not accepted.");
else
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnReceive), Server);
}
catch (Exception e)
{
CallBack(e);
}
}
/// <summary>
/// Gets or sets the username to use when authenticating with the proxy server.
/// </summary>
/// <value>The username to use when authenticating with the proxy server.</value>
/// <exception cref="ArgumentNullException">The specified value is null.</exception>
private string Username
{
get
{
return _username;
}
set
{
_username = value ?? throw new ArgumentNullException();
}
}
/// <summary>
/// Gets or sets the password to use when authenticating with the proxy server.
/// </summary>
/// <value>The password to use when authenticating with the proxy server.</value>
/// <exception cref="ArgumentNullException">The specified value is null.</exception>
private string Password
{
get
{
return _password;
}
set
{
_password = value ?? throw new ArgumentNullException();
}
}
// private variables
/// <summary>Holds the value of the Username property.</summary>
private string _username;
/// <summary>Holds the value of the Password property.</summary>
private string _password;
}
}
This diff is collapsed.
/*
Copyright © 2002, The KPD-Team
All rights reserved.
http://www.mentalis.org/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the KPD-Team, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Threading;
namespace Titanium.Web.Proxy.ProxySocket
{
/// <summary>
/// A class that implements the IAsyncResult interface. Objects from this class are returned by the BeginConnect method of the ProxySocket class.
/// </summary>
internal class IAsyncProxyResult : IAsyncResult
{
/// <summary>Initializes the internal variables of this object</summary>
/// <param name="stateObject">An object that contains state information for this request.</param>
internal IAsyncProxyResult(object stateObject = null)
{
_stateObject = stateObject;
_completed = false;
if (_waitHandle != null)
_waitHandle.Reset();
}
/// <summary>Initializes the internal variables of this object</summary>
internal void Reset()
{
_stateObject = null;
_completed = true;
if (_waitHandle != null)
_waitHandle.Set();
}
/// <summary>Gets a value that indicates whether the server has completed processing the call. It is illegal for the server to use any client supplied resources outside of the agreed upon sharing semantics after it sets the IsCompleted property to "true". Thus, it is safe for the client to destroy the resources after IsCompleted property returns "true".</summary>
/// <value>A boolean that indicates whether the server has completed processing the call.</value>
public bool IsCompleted
{
get
{
return _completed;
}
}
/// <summary>Gets a value that indicates whether the BeginXXXX call has been completed synchronously. If this is detected in the AsyncCallback delegate, it is probable that the thread that called BeginInvoke is the current thread.</summary>
/// <value>Returns false.</value>
public bool CompletedSynchronously
{
get
{
return false;
}
}
/// <summary>Gets an object that was passed as the state parameter of the BeginXXXX method call.</summary>
/// <value>The object that was passed as the state parameter of the BeginXXXX method call.</value>
public object AsyncState
{
get
{
return _stateObject;
}
}
/// <summary>
/// The AsyncWaitHandle property returns the WaitHandle that can use to perform a WaitHandle.WaitOne or WaitAny or WaitAll. The object which implements IAsyncResult need not derive from the System.WaitHandle classes directly. The WaitHandle wraps its underlying synchronization primitive and should be signaled after the call is completed. This enables the client to wait for the call to complete instead polling. The Runtime supplies a number of waitable objects that mirror Win32 synchronization primitives e.g. ManualResetEvent, AutoResetEvent and Mutex.
/// WaitHandle supplies methods that support waiting for such synchronization objects to become signaled with "any" or "all" semantics i.e. WaitHandle.WaitOne, WaitAny and WaitAll. Such methods are context aware to avoid deadlocks. The AsyncWaitHandle can be allocated eagerly or on demand. It is the choice of the IAsyncResult implementer.
///</summary>
/// <value>The WaitHandle associated with this asynchronous result.</value>
public WaitHandle AsyncWaitHandle
{
get
{
if (_waitHandle == null)
_waitHandle = new ManualResetEvent(false);
return _waitHandle;
}
}
// private variables
/// <summary>Used internally to represent the state of the asynchronous request</summary>
private bool _completed;
/// <summary>Holds the value of the StateObject property.</summary>
private object _stateObject;
/// <summary>Holds the value of the WaitHandle property.</summary>
private ManualResetEvent _waitHandle;
}
}
/*
Copyright © 2002, The KPD-Team
All rights reserved.
http://www.mentalis.org/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the KPD-Team, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
namespace Titanium.Web.Proxy.ProxySocket
{
/// <summary>
/// The exception that is thrown when a proxy error occurs.
/// </summary>
[Serializable]
internal class ProxyException : Exception
{
/// <summary>
/// Initializes a new instance of the ProxyException class.
/// </summary>
public ProxyException() : this("An error occured while talking to the proxy server.") { }
/// <summary>
/// Initializes a new instance of the ProxyException class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ProxyException(string message) : base(message) { }
/// <summary>
/// Initializes a new instance of the ProxyException class.
/// </summary>
/// <param name="socks5Error">The error number returned by a SOCKS5 server.</param>
public ProxyException(int socks5Error) : this(ProxyException.Socks5ToString(socks5Error)) { }
/// <summary>
/// Converts a SOCKS5 error number to a human readable string.
/// </summary>
/// <param name="socks5Error">The error number returned by a SOCKS5 server.</param>
/// <returns>A string representation of the specified SOCKS5 error number.</returns>
public static string Socks5ToString(int socks5Error)
{
switch (socks5Error)
{
case 0:
return "Connection succeeded.";
case 1:
return "General SOCKS server failure.";
case 2:
return "Connection not allowed by ruleset.";
case 3:
return "Network unreachable.";
case 4:
return "Host unreachable.";
case 5:
return "Connection refused.";
case 6:
return "TTL expired.";
case 7:
return "Command not supported.";
case 8:
return "Address type not supported.";
default:
return "Unspecified SOCKS error.";
}
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment